diff --git a/.github/update.log b/.github/update.log index f0b5900999..527d7896ef 100644 --- a/.github/update.log +++ b/.github/update.log @@ -1120,3 +1120,4 @@ Update On Wed Sep 10 20:42:57 CEST 2025 Update On Thu Sep 11 20:34:24 CEST 2025 Update On Fri Sep 12 20:36:01 CEST 2025 Update On Sat Sep 13 20:34:27 CEST 2025 +Update On Sun Sep 14 20:31:36 CEST 2025 diff --git a/brook/ping/ping.json b/brook/ping/ping.json index 8917960eff..c73501a732 100644 --- a/brook/ping/ping.json +++ b/brook/ping/ping.json @@ -1,7 +1,7 @@ { "version": "20250808", - "text": "", - "link": "", - "text_zh": "", - "link_zh": "" + "text": "I've purchased code signing certificates for all my product Windows apps", + "link": "https://www.txthinking.com/talks/articles/windows-code-sign-en.article", + "text_zh": "我已经为我的所有产品的 Windows 客户端购买了代码签名证书", + "link_zh": "https://www.txthinking.com/talks/articles/windows-code-sign.article" } diff --git a/clash-meta/transport/vless/vision/padding.go b/clash-meta/transport/vless/vision/padding.go index 157dfee861..ac6de886dd 100644 --- a/clash-meta/transport/vless/vision/padding.go +++ b/clash-meta/transport/vless/vision/padding.go @@ -47,15 +47,21 @@ func ApplyPadding(buffer *buf.Buffer, command byte, userUUID *[]byte, paddingTLS const xrayBufSize = 8192 func (vc *Conn) ReshapeBuffer(buffer *buf.Buffer) []*buf.Buffer { - if buffer.Len() <= xrayBufSize-PaddingHeaderLen { + const bufferLimit = xrayBufSize - PaddingHeaderLen + if buffer.Len() < bufferLimit { return []*buf.Buffer{buffer} } - cutAt := bytes.LastIndex(buffer.Bytes(), tlsApplicationDataStart) - if cutAt == -1 { - cutAt = xrayBufSize / 2 + options := N.NewReadWaitOptions(nil, vc) + var buffers []*buf.Buffer + for buffer.Len() >= bufferLimit { + cutAt := bytes.LastIndex(buffer.Bytes(), tlsApplicationDataStart) + if cutAt < 21 || cutAt > bufferLimit { + cutAt = xrayBufSize / 2 + } + buffer2 := options.NewBuffer() // ensure the new buffer can send used in vc.WriteBuffer + buf.Must(buf.Error(buffer2.ReadFullFrom(buffer, cutAt))) + buffers = append(buffers, buffer2) } - buffer2 := N.NewReadWaitOptions(nil, vc).NewBuffer() // ensure the new buffer can send used in vc.WriteBuffer - buffer2.Write(buffer.From(cutAt)) - buffer.Truncate(cutAt) - return []*buf.Buffer{buffer, buffer2} + buffers = append(buffers, buffer) + return buffers } diff --git a/clash-meta/transport/vless/vision/vision.go b/clash-meta/transport/vless/vision/vision.go index c5cf3783b2..e9786981eb 100644 --- a/clash-meta/transport/vless/vision/vision.go +++ b/clash-meta/transport/vless/vision/vision.go @@ -1,4 +1,6 @@ // Package vision implements VLESS flow `xtls-rprx-vision` introduced by Xray-core. +// +// same logic as https://github.com/XTLS/Xray-core/blob/v25.9.11/proxy/proxy.go package vision import ( @@ -27,7 +29,7 @@ func NewConn(conn net.Conn, tlsConn net.Conn, userUUID uuid.UUID) (*Conn, error) ExtendedWriter: N.NewExtendedWriter(conn), Conn: conn, userUUID: userUUID, - packetsToFilter: 6, + packetsToFilter: 8, readProcess: true, readFilterUUID: true, writeFilterApplicationData: true, diff --git a/clash-nyanpasu/backend/Cargo.lock b/clash-nyanpasu/backend/Cargo.lock index 8115e5dab2..9b272b8f9d 100644 --- a/clash-nyanpasu/backend/Cargo.lock +++ b/clash-nyanpasu/backend/Cargo.lock @@ -8033,10 +8033,11 @@ checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" [[package]] name = "serde" -version = "1.0.219" +version = "1.0.221" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "341877e04a22458705eb4e131a1508483c877dca2792b3781d4e5d8a6019ec43" dependencies = [ + "serde_core", "serde_derive", ] @@ -8062,10 +8063,19 @@ dependencies = [ ] [[package]] -name = "serde_derive" -version = "1.0.219" +name = "serde_core" +version = "1.0.221" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "0c459bc0a14c840cb403fc14b148620de1e0778c96ecd6e0c8c3cacb6d8d00fe" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.221" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6185cf75117e20e62b1ff867b9518577271e58abe0037c40bb4794969355ab0" dependencies = [ "proc-macro2", "quote", @@ -8085,15 +8095,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.143" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +checksum = "56177480b00303e689183f110b4e727bb4211d692c62d4fcd16d02be93077d40" dependencies = [ "indexmap 2.11.1", "itoa", "memchr", "ryu", - "serde", + "serde_core", ] [[package]] diff --git a/clash-nyanpasu/frontend/nyanpasu/package.json b/clash-nyanpasu/frontend/nyanpasu/package.json index 0879014f81..e760cb670c 100644 --- a/clash-nyanpasu/frontend/nyanpasu/package.json +++ b/clash-nyanpasu/frontend/nyanpasu/package.json @@ -49,7 +49,7 @@ "react-use": "17.6.0", "rxjs": "7.8.2", "swr": "2.3.6", - "virtua": "0.43.0", + "virtua": "0.43.1", "vite-bundle-visualizer": "1.2.1" }, "devDependencies": { @@ -59,9 +59,9 @@ "@iconify/json": "2.2.383", "@monaco-editor/react": "4.7.0", "@tanstack/react-query": "5.87.4", - "@tanstack/react-router": "1.131.36", - "@tanstack/react-router-devtools": "1.131.36", - "@tanstack/router-plugin": "1.131.36", + "@tanstack/react-router": "1.131.41", + "@tanstack/react-router-devtools": "1.131.42", + "@tanstack/router-plugin": "1.131.43", "@tauri-apps/plugin-clipboard-manager": "2.3.0", "@tauri-apps/plugin-dialog": "2.4.0", "@tauri-apps/plugin-fs": "2.4.2", @@ -93,6 +93,6 @@ "vite-plugin-sass-dts": "1.3.31", "vite-plugin-svgr": "4.5.0", "vite-tsconfig-paths": "5.1.4", - "zod": "4.1.5" + "zod": "4.1.8" } } diff --git a/clash-nyanpasu/frontend/nyanpasu/src/components/setting/setting-system-proxy.tsx b/clash-nyanpasu/frontend/nyanpasu/src/components/setting/setting-system-proxy.tsx index e28f548036..2a5deb3696 100644 --- a/clash-nyanpasu/frontend/nyanpasu/src/components/setting/setting-system-proxy.tsx +++ b/clash-nyanpasu/frontend/nyanpasu/src/components/setting/setting-system-proxy.tsx @@ -119,6 +119,9 @@ const ProxyGuardInterval = () => { ) } +const DEFAULT_BYPASS = + 'localhost;127.;192.168.;10.;172.16.;172.17.;172.18.;172.19.;172.20.;172.21.;172.22.;172.23.;172.24.;172.25.;172.26.;172.27.;172.28.;172.29.;172.30.;172.31.*' + const SystemProxyBypass = () => { const { t } = useTranslation() @@ -129,7 +132,13 @@ const SystemProxyBypass = () => { label={t('Proxy Bypass')} value={systemProxyBypass.data || ''} onApply={(value) => { - systemProxyBypass.upsert(value) + if (!value || value.trim() === '') { + // 输入为空 → 重置为默认规则 + systemProxyBypass.upsert(DEFAULT_BYPASS) + } else { + // 正常写入用户配置 + systemProxyBypass.upsert(value) + } }} /> ) diff --git a/clash-nyanpasu/manifest/version.json b/clash-nyanpasu/manifest/version.json index 80290dfdc5..a9a276f0c6 100644 --- a/clash-nyanpasu/manifest/version.json +++ b/clash-nyanpasu/manifest/version.json @@ -2,7 +2,7 @@ "manifest_version": 1, "latest": { "mihomo": "v1.19.13", - "mihomo_alpha": "alpha-4f4f13d", + "mihomo_alpha": "alpha-cea29e2", "clash_rs": "v0.9.0", "clash_premium": "2023-09-05-gdcc8d87", "clash_rs_alpha": "0.9.0-alpha+sha.50f295d" @@ -69,5 +69,5 @@ "linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf" } }, - "updated_at": "2025-09-12T22:20:41.506Z" + "updated_at": "2025-09-13T22:20:30.078Z" } diff --git a/clash-nyanpasu/package.json b/clash-nyanpasu/package.json index 537fbdd751..7f6a9787f6 100644 --- a/clash-nyanpasu/package.json +++ b/clash-nyanpasu/package.json @@ -78,7 +78,7 @@ "eslint-import-resolver-alias": "1.1.2", "eslint-plugin-html": "8.1.3", "eslint-plugin-import": "2.32.0", - "eslint-plugin-n": "17.21.3", + "eslint-plugin-n": "17.22.0", "eslint-plugin-prettier": "5.5.4", "eslint-plugin-promise": "7.2.1", "eslint-plugin-react": "7.37.5", diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index 9e0d7bbe42..9d18c9b643 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -83,8 +83,8 @@ importers: specifier: 2.32.0 version: 2.32.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.35.0(jiti@2.5.1)) eslint-plugin-n: - specifier: 17.21.3 - version: 17.21.3(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + specifier: 17.22.0 + version: 17.22.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) eslint-plugin-prettier: specifier: 5.5.4 version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.35.0(jiti@2.5.1)))(eslint@9.35.0(jiti@2.5.1))(prettier@3.6.2) @@ -253,7 +253,7 @@ importers: version: 4.1.13 '@tanstack/router-zod-adapter': specifier: 1.81.5 - version: 1.81.5(@tanstack/react-router@1.131.36(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(zod@4.1.5) + version: 1.81.5(@tanstack/react-router@1.131.41(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(zod@4.1.8) '@tauri-apps/api': specifier: 2.8.0 version: 2.8.0 @@ -330,8 +330,8 @@ importers: specifier: 2.3.6 version: 2.3.6(react@19.1.1) virtua: - specifier: 0.43.0 - version: 0.43.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5) + specifier: 0.43.1 + version: 0.43.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5) vite-bundle-visualizer: specifier: 1.2.1 version: 1.2.1(rollup@4.46.2) @@ -355,14 +355,14 @@ importers: specifier: 5.87.4 version: 5.87.4(react@19.1.1) '@tanstack/react-router': - specifier: 1.131.36 - version: 1.131.36(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + specifier: 1.131.41 + version: 1.131.41(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@tanstack/react-router-devtools': - specifier: 1.131.36 - version: 1.131.36(@tanstack/react-router@1.131.36(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.131.36)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5)(tiny-invariant@1.3.3) + specifier: 1.131.42 + version: 1.131.42(@tanstack/react-router@1.131.41(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.131.41)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5)(tiny-invariant@1.3.3) '@tanstack/router-plugin': - specifier: 1.131.36 - version: 1.131.36(@tanstack/react-router@1.131.36(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.5(@types/node@24.3.1)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) + specifier: 1.131.43 + version: 1.131.43(@tanstack/react-router@1.131.41(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.5(@types/node@24.3.1)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) '@tauri-apps/plugin-clipboard-manager': specifier: 2.3.0 version: 2.3.0 @@ -457,8 +457,8 @@ importers: specifier: 5.1.4 version: 5.1.4(typescript@5.9.2)(vite@7.1.5(@types/node@24.3.1)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) zod: - specifier: 4.1.5 - version: 4.1.5 + specifier: 4.1.8 + version: 4.1.8 frontend/ui: dependencies: @@ -575,8 +575,8 @@ importers: specifier: 7.7.2 version: 7.7.2 zod: - specifier: 4.1.5 - version: 4.1.5 + specifier: 4.1.8 + version: 4.1.8 devDependencies: '@octokit/types': specifier: 14.1.0 @@ -1696,12 +1696,6 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/eslint-utils@4.7.0': - resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/eslint-utils@4.8.0': resolution: {integrity: sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3034,16 +3028,16 @@ packages: peerDependencies: react: ^18 || ^19 - '@tanstack/react-router-devtools@1.131.36': - resolution: {integrity: sha512-2huBmW+mqPoJs6ZHfjuunEkVRfgWZh67IUjgdSyqdaYGLa3qsG3zcG4bpTIq6HwJuzcK00JRM3AQ4NLPdttaJQ==} + '@tanstack/react-router-devtools@1.131.42': + resolution: {integrity: sha512-7pymFB1CCimRHot2Zp0ZekQjd1iN812V88n9NLPSeiv9sVRtRVIaLphJjDeudx1NNgkfSJPx2lOhz6K38cuZog==} engines: {node: '>=12'} peerDependencies: - '@tanstack/react-router': ^1.131.36 + '@tanstack/react-router': ^1.131.41 react: '>=18.0.0 || >=19.0.0' react-dom: '>=18.0.0 || >=19.0.0' - '@tanstack/react-router@1.131.36': - resolution: {integrity: sha512-9tglm3Rf9qkANBIyYLbGlOjNj7GDBr0jOEOaADfwiGV3Ua3P562MGn7nHUOrfRfA6u2MCg0EKJ+LH7AeWxAqkg==} + '@tanstack/react-router@1.131.41': + resolution: {integrity: sha512-QEbTYpAosiD8e4qEZRr9aJipGSb8pQc+pfZwK6NCD2Tcxwu2oF6MVtwv0bIDLRpZP0VJMBpxXlTRISUDNMNqIA==} engines: {node: '>=12'} peerDependencies: react: '>=18.0.0 || >=19.0.0' @@ -3068,15 +3062,15 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - '@tanstack/router-core@1.131.36': - resolution: {integrity: sha512-faGrKwrJBjJDxbcyeaOXgQcyccmzIGkwk+tnFeJuMTnH5OMfArykYnTZ9BxIrlOY2Mori9DXmYKMlig6mVqmGA==} + '@tanstack/router-core@1.131.41': + resolution: {integrity: sha512-VoLly00DWM0abKuVPRm8wiwGtRBHOKs6K896fy48Q/KYoDVLs8kRCRjFGS7rGnYC2FIkmmvHqYRqNg7jgCx2yg==} engines: {node: '>=12'} - '@tanstack/router-devtools-core@1.131.36': - resolution: {integrity: sha512-ToZVh1kBAcOt4lp7p/v9g4cjbSBlodxngIFx+lvmhCZ7Y+SG7Y6uP7ivw8WsUAdXAWLzIhIW6Jg57TT7sz8tkg==} + '@tanstack/router-devtools-core@1.131.42': + resolution: {integrity: sha512-o8jKTiwXcUSjmkozcMjIw1yhjVYeXcuQO7DtfgjKW3B85iveH6VzYK+bGEVU7wmLNMuUSe2eI/7RBzJ6a5+MCA==} engines: {node: '>=12'} peerDependencies: - '@tanstack/router-core': ^1.131.36 + '@tanstack/router-core': ^1.131.41 csstype: ^3.0.10 solid-js: '>=1.9.5' tiny-invariant: ^1.3.3 @@ -3084,16 +3078,16 @@ packages: csstype: optional: true - '@tanstack/router-generator@1.131.36': - resolution: {integrity: sha512-Rl1Q2DFcAFXaYSvHQwO+HKmp5zSBz8D3qZl+fJ0a0w4/2I+Km1xwjzDwBUkFVNJtTUor40uU76SYJzV0/9s1tw==} + '@tanstack/router-generator@1.131.41': + resolution: {integrity: sha512-HsDkBU1u/KvHrzn76v/9oeyMFuxvVlE3dfIu4fldZbPy/i903DWBwODIDGe6fVUsYtzPPrRvNtbjV18HVz5GCA==} engines: {node: '>=12'} - '@tanstack/router-plugin@1.131.36': - resolution: {integrity: sha512-EU/NopEkQw3AyjZvB33r4uIfUtbU64rbdJDCgGfumv1wpi/B4lJTO9W6iiUsoIsi1mtlNQKbFKNIbx+VyGh19Q==} + '@tanstack/router-plugin@1.131.43': + resolution: {integrity: sha512-vBPBw5LBl+ogGZnFVyLmH65rYnr88cKRT1WtDZ+QYNsgto/SQbD+JxJgbm8YJdpteo3KZL6zHyZz30nmwbhC4A==} engines: {node: '>=12'} peerDependencies: '@rsbuild/core': '>=1.0.2' - '@tanstack/react-router': ^1.131.36 + '@tanstack/react-router': ^1.131.41 vite: '>=5.0.0 || >=6.0.0' vite-plugin-solid: ^2.11.2 webpack: '>=5.92.0' @@ -4777,10 +4771,6 @@ packages: end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} - enhanced-resolve@5.18.1: - resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} - engines: {node: '>=10.13.0'} - enhanced-resolve@5.18.3: resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==} engines: {node: '>=10.13.0'} @@ -5005,8 +4995,8 @@ packages: '@typescript-eslint/parser': optional: true - eslint-plugin-n@17.21.3: - resolution: {integrity: sha512-MtxYjDZhMQgsWRm/4xYLL0i2EhusWT7itDxlJ80l1NND2AL2Vi5Mvneqv/ikG9+zpran0VsVRXTEHrpLmUZRNw==} + eslint-plugin-n@17.22.0: + resolution: {integrity: sha512-+YQ4dW8gg3eVZ3A8lL6zugEmA+Le5IEpCXsI8vKvDvSIB8gEh2N3PKqDwI+J8uLb7nphTJkwiv2e5OlnEDNvpQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: '>=8.23.0' @@ -8397,8 +8387,8 @@ packages: vfile@6.0.1: resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==} - virtua@0.43.0: - resolution: {integrity: sha512-sUjpvYcJ2UBq3RoES65BFt8SQvVllN8JWScGR1ETKW15GgocaDW4+R1ZriYdUGejFfFZkPEF02WsFOMhiyjqEw==} + virtua@0.43.1: + resolution: {integrity: sha512-379ETgqWgzugIJ/crFxNGbqUSMUv0cGxJdpXC7SYvsUpdFWzaqFJIz1XXnJVlTjmE5CYjT+2ipQvAn5N9efGag==} peerDependencies: react: '>=16.14.0' react-dom: '>=16.14.0' @@ -8694,8 +8684,8 @@ packages: zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} - zod@4.1.5: - resolution: {integrity: sha512-rcUUZqlLJgBC33IT3PNMgsCq6TzLQEG/Ei/KTCU0PedSWRMAXoOUN+4t/0H+Q8bdnLPdqUYnvboJT0bn/229qg==} + zod@4.1.8: + resolution: {integrity: sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ==} zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -10086,11 +10076,6 @@ snapshots: eslint: 9.35.0(jiti@2.5.1) eslint-visitor-keys: 3.4.3 - '@eslint-community/eslint-utils@4.7.0(eslint@9.35.0(jiti@2.5.1))': - dependencies: - eslint: 9.35.0(jiti@2.5.1) - eslint-visitor-keys: 3.4.3 - '@eslint-community/eslint-utils@4.8.0(eslint@9.35.0(jiti@2.5.1))': dependencies: eslint: 9.35.0(jiti@2.5.1) @@ -11306,10 +11291,10 @@ snapshots: '@tanstack/query-core': 5.87.4 react: 19.1.1 - '@tanstack/react-router-devtools@1.131.36(@tanstack/react-router@1.131.36(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.131.36)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5)(tiny-invariant@1.3.3)': + '@tanstack/react-router-devtools@1.131.42(@tanstack/react-router@1.131.41(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.131.41)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5)(tiny-invariant@1.3.3)': dependencies: - '@tanstack/react-router': 1.131.36(react-dom@19.1.1(react@19.1.1))(react@19.1.1) - '@tanstack/router-devtools-core': 1.131.36(@tanstack/router-core@1.131.36)(csstype@3.1.3)(solid-js@1.9.5)(tiny-invariant@1.3.3) + '@tanstack/react-router': 1.131.41(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@tanstack/router-devtools-core': 1.131.42(@tanstack/router-core@1.131.41)(csstype@3.1.3)(solid-js@1.9.5)(tiny-invariant@1.3.3) react: 19.1.1 react-dom: 19.1.1(react@19.1.1) transitivePeerDependencies: @@ -11318,11 +11303,11 @@ snapshots: - solid-js - tiny-invariant - '@tanstack/react-router@1.131.36(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@tanstack/react-router@1.131.41(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@tanstack/history': 1.131.2 '@tanstack/react-store': 0.7.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) - '@tanstack/router-core': 1.131.36 + '@tanstack/router-core': 1.131.41 isbot: 5.1.28 react: 19.1.1 react-dom: 19.1.1(react@19.1.1) @@ -11348,7 +11333,7 @@ snapshots: react: 19.1.1 react-dom: 19.1.1(react@19.1.1) - '@tanstack/router-core@1.131.36': + '@tanstack/router-core@1.131.41': dependencies: '@tanstack/history': 1.131.2 '@tanstack/store': 0.7.0 @@ -11358,9 +11343,9 @@ snapshots: tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - '@tanstack/router-devtools-core@1.131.36(@tanstack/router-core@1.131.36)(csstype@3.1.3)(solid-js@1.9.5)(tiny-invariant@1.3.3)': + '@tanstack/router-devtools-core@1.131.42(@tanstack/router-core@1.131.41)(csstype@3.1.3)(solid-js@1.9.5)(tiny-invariant@1.3.3)': dependencies: - '@tanstack/router-core': 1.131.36 + '@tanstack/router-core': 1.131.41 clsx: 2.1.1 goober: 2.1.16(csstype@3.1.3) solid-js: 1.9.5 @@ -11368,9 +11353,9 @@ snapshots: optionalDependencies: csstype: 3.1.3 - '@tanstack/router-generator@1.131.36': + '@tanstack/router-generator@1.131.41': dependencies: - '@tanstack/router-core': 1.131.36 + '@tanstack/router-core': 1.131.41 '@tanstack/router-utils': 1.131.2 '@tanstack/virtual-file-routes': 1.131.2 prettier: 3.6.2 @@ -11381,7 +11366,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-plugin@1.131.36(@tanstack/react-router@1.131.36(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.5(@types/node@24.3.1)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1))': + '@tanstack/router-plugin@1.131.43(@tanstack/react-router@1.131.41(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.5(@types/node@24.3.1)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1))': dependencies: '@babel/core': 7.28.3 '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.3) @@ -11389,8 +11374,8 @@ snapshots: '@babel/template': 7.27.2 '@babel/traverse': 7.28.3 '@babel/types': 7.28.2 - '@tanstack/router-core': 1.131.36 - '@tanstack/router-generator': 1.131.36 + '@tanstack/router-core': 1.131.41 + '@tanstack/router-generator': 1.131.41 '@tanstack/router-utils': 1.131.2 '@tanstack/virtual-file-routes': 1.131.2 babel-dead-code-elimination: 1.0.10 @@ -11398,7 +11383,7 @@ snapshots: unplugin: 2.3.9 zod: 3.25.76 optionalDependencies: - '@tanstack/react-router': 1.131.36(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@tanstack/react-router': 1.131.41(react-dom@19.1.1(react@19.1.1))(react@19.1.1) vite: 7.1.5(@types/node@24.3.1)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) transitivePeerDependencies: - supports-color @@ -11414,10 +11399,10 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-zod-adapter@1.81.5(@tanstack/react-router@1.131.36(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(zod@4.1.5)': + '@tanstack/router-zod-adapter@1.81.5(@tanstack/react-router@1.131.41(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(zod@4.1.8)': dependencies: - '@tanstack/react-router': 1.131.36(react-dom@19.1.1(react@19.1.1))(react@19.1.1) - zod: 4.1.5 + '@tanstack/react-router': 1.131.41(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + zod: 4.1.8 '@tanstack/store@0.7.0': {} @@ -11923,7 +11908,7 @@ snapshots: '@typescript-eslint/utils@8.41.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2)': dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.35.0(jiti@2.5.1)) + '@eslint-community/eslint-utils': 4.8.0(eslint@9.35.0(jiti@2.5.1)) '@typescript-eslint/scope-manager': 8.41.0 '@typescript-eslint/types': 8.41.0 '@typescript-eslint/typescript-estree': 8.41.0(typescript@5.9.2) @@ -13205,11 +13190,6 @@ snapshots: dependencies: once: 1.4.0 - enhanced-resolve@5.18.1: - dependencies: - graceful-fs: 4.2.11 - tapable: 2.2.1 - enhanced-resolve@5.18.3: dependencies: graceful-fs: 4.2.11 @@ -13575,7 +13555,7 @@ snapshots: eslint-plugin-es-x@7.8.0(eslint@9.35.0(jiti@2.5.1)): dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.35.0(jiti@2.5.1)) + '@eslint-community/eslint-utils': 4.8.0(eslint@9.35.0(jiti@2.5.1)) '@eslint-community/regexpp': 4.12.1 eslint: 9.35.0(jiti@2.5.1) eslint-compat-utils: 0.5.1(eslint@9.35.0(jiti@2.5.1)) @@ -13631,10 +13611,10 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-n@17.21.3(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2): + eslint-plugin-n@17.22.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2): dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.35.0(jiti@2.5.1)) - enhanced-resolve: 5.18.1 + '@eslint-community/eslint-utils': 4.8.0(eslint@9.35.0(jiti@2.5.1)) + enhanced-resolve: 5.18.3 eslint: 9.35.0(jiti@2.5.1) eslint-plugin-es-x: 7.8.0(eslint@9.35.0(jiti@2.5.1)) get-tsconfig: 4.10.1 @@ -15425,7 +15405,7 @@ snapshots: eslint: 9.35.0(jiti@2.5.1) eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.35.0(jiti@2.5.1)))(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.35.0(jiti@2.5.1)))(eslint@9.35.0(jiti@2.5.1)) eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.35.0(jiti@2.5.1)) - eslint-plugin-n: 17.21.3(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + eslint-plugin-n: 17.22.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) eslint-plugin-promise: 7.2.1(eslint@9.35.0(jiti@2.5.1)) eslint-plugin-react: 7.37.5(eslint@9.35.0(jiti@2.5.1)) find-up: 5.0.0 @@ -17428,7 +17408,7 @@ snapshots: unist-util-stringify-position: 4.0.0 vfile-message: 4.0.2 - virtua@0.43.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5): + virtua@0.43.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5): optionalDependencies: react: 19.1.1 react-dom: 19.1.1(react@19.1.1) @@ -17750,6 +17730,6 @@ snapshots: zod@3.25.76: {} - zod@4.1.5: {} + zod@4.1.8: {} zwitch@2.0.4: {} diff --git a/clash-nyanpasu/scripts/package.json b/clash-nyanpasu/scripts/package.json index e2e70b139f..1c8e690b7b 100644 --- a/clash-nyanpasu/scripts/package.json +++ b/clash-nyanpasu/scripts/package.json @@ -10,7 +10,7 @@ "filesize": "11.0.2", "p-retry": "7.0.0", "semver": "7.7.2", - "zod": "4.1.5" + "zod": "4.1.8" }, "devDependencies": { "@octokit/types": "14.1.0", diff --git a/lede/target/linux/mediatek/filogic/config-6.12 b/lede/target/linux/mediatek/filogic/config-6.12 index 7ca13768b5..8e47cb8adb 100644 --- a/lede/target/linux/mediatek/filogic/config-6.12 +++ b/lede/target/linux/mediatek/filogic/config-6.12 @@ -221,6 +221,7 @@ CONFIG_HAS_IOPORT_MAP=y CONFIG_HWMON=y CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_MTK=y +CONFIG_HW_RANDOM_MTK_V2=y CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y CONFIG_I2C_CHARDEV=y diff --git a/lede/target/linux/mediatek/mt7622/config-6.12 b/lede/target/linux/mediatek/mt7622/config-6.12 index d7e767a1a8..fb2064e899 100644 --- a/lede/target/linux/mediatek/mt7622/config-6.12 +++ b/lede/target/linux/mediatek/mt7622/config-6.12 @@ -220,6 +220,7 @@ CONFIG_HAS_IOPORT_MAP=y CONFIG_HWMON=y CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_MTK=y +# CONFIG_HW_RANDOM_MTK_V2 is not set CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y CONFIG_I2C_CHARDEV=y diff --git a/lede/target/linux/mediatek/mt7623/config-6.12 b/lede/target/linux/mediatek/mt7623/config-6.12 index 3731f2a018..0dbacb0f00 100644 --- a/lede/target/linux/mediatek/mt7623/config-6.12 +++ b/lede/target/linux/mediatek/mt7623/config-6.12 @@ -315,6 +315,7 @@ CONFIG_HOTPLUG_CPU=y CONFIG_HWMON=y CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_MTK=y +# CONFIG_HW_RANDOM_MTK_V2 is not set CONFIG_HZ_FIXED=0 CONFIG_I2C=y CONFIG_I2C_ALGOBIT=y diff --git a/lede/target/linux/mediatek/mt7629/config-6.12 b/lede/target/linux/mediatek/mt7629/config-6.12 index 2bdfb6baf9..80053bdbcd 100644 --- a/lede/target/linux/mediatek/mt7629/config-6.12 +++ b/lede/target/linux/mediatek/mt7629/config-6.12 @@ -160,6 +160,7 @@ CONFIG_HOTPLUG_CORE_SYNC_DEAD=y CONFIG_HOTPLUG_CPU=y CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_MTK=y +# CONFIG_HW_RANDOM_MTK_V2 is not set CONFIG_HZ_FIXED=0 # CONFIG_IDPF is not set CONFIG_INITRAMFS_SOURCE="" diff --git a/lede/target/linux/mediatek/patches-6.12/320-hwrng-add-driver-for-MediaTek-TRNG-SMC.patch b/lede/target/linux/mediatek/patches-6.12/320-hwrng-add-driver-for-MediaTek-TRNG-SMC.patch new file mode 100644 index 0000000000..e738883800 --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.12/320-hwrng-add-driver-for-MediaTek-TRNG-SMC.patch @@ -0,0 +1,133 @@ +From 9837930d6738e9fdc323ad887ace7c236a61d70c Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 25 Jan 2023 00:27:49 +0000 +Subject: [PATCH] hwrng: add driver for MediaTek TRNG SMC + +Add driver providing kernel-side support for the Random Number +Generator hardware found on Mediatek SoCs which have a driver in ARM +TrustedFirmware-A allowing Linux to read random numbers using a +non-standard vendor-defined Secure Monitor Call. + +Signed-off-by: Daniel Golle +--- + drivers/char/hw_random/Kconfig | 16 +++++++ + drivers/char/hw_random/Makefile | 1 + + drivers/char/hw_random/mtk-rng-v2.c | 74 +++++++++++++++++++++++++++++ + 3 files changed, 91 insertions(+) + create mode 100644 drivers/char/hw_random/mtk-rng-v2.c + +--- a/drivers/char/hw_random/Kconfig ++++ b/drivers/char/hw_random/Kconfig +@@ -451,6 +451,23 @@ config HW_RANDOM_MTK + + If unsure, say Y. + ++config HW_RANDOM_MTK_V2 ++ tristate "Mediatek Random Number Generator support (v2/SMC)" ++ depends on HAVE_ARM_SMCCC ++ depends on HW_RANDOM ++ depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST ++ default y ++ help ++ This driver provides kernel-side support for the Random Number ++ Generator hardware found on Mediatek SoCs which have a driver ++ in ARM TrustedFirmware-A allowing Linux to read using a non- ++ standard vendor-defined Secure Monitor Call. ++ ++ To compile this driver as a module, choose M here. the ++ module will be called mtk-rng-v2. ++ ++ If unsure, say Y. ++ + config HW_RANDOM_S390 + tristate "S390 True Random Number Generator support" + depends on S390 +--- a/drivers/char/hw_random/Makefile ++++ b/drivers/char/hw_random/Makefile +@@ -39,6 +39,7 @@ obj-$(CONFIG_HW_RANDOM_PIC32) += pic32-r + obj-$(CONFIG_HW_RANDOM_MESON) += meson-rng.o + obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o + obj-$(CONFIG_HW_RANDOM_MTK) += mtk-rng.o ++obj-$(CONFIG_HW_RANDOM_MTK_V2) += mtk-rng-v2.o + obj-$(CONFIG_HW_RANDOM_S390) += s390-trng.o + obj-$(CONFIG_HW_RANDOM_KEYSTONE) += ks-sa-rng.o + obj-$(CONFIG_HW_RANDOM_OPTEE) += optee-rng.o +--- /dev/null ++++ b/drivers/char/hw_random/mtk-rng-v2.c +@@ -0,0 +1,76 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Driver for Mediatek Hardware Random Number Generator (v2/SMCC) ++ * ++ * Copyright (C) 2023 Daniel Golle ++ * based on patch from Mingming Su ++ */ ++#define MTK_RNG_DEV KBUILD_MODNAME ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MTK_SIP_KERNEL_GET_RND MTK_SIP_SMC_CMD(0x550) ++ ++static int mtk_rng_v2_read(struct hwrng *rng, void *buf, size_t max, bool wait) ++{ ++ struct arm_smccc_res res; ++ int retval = 0; ++ ++ while (max >= sizeof(u32)) { ++ arm_smccc_smc(MTK_SIP_KERNEL_GET_RND, 0, 0, 0, 0, 0, 0, 0, ++ &res); ++ if (res.a0) ++ break; ++ ++ *(u32 *)buf = res.a1; ++ retval += sizeof(u32); ++ buf += sizeof(u32); ++ max -= sizeof(u32); ++ } ++ ++ return retval || !wait ? retval : -EIO; ++} ++ ++static int mtk_rng_v2_probe(struct platform_device *pdev) ++{ ++ struct hwrng *trng; ++ ++ trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL); ++ if (!trng) ++ return -ENOMEM; ++ ++ trng->name = pdev->name; ++ trng->read = mtk_rng_v2_read; ++ trng->quality = 900; ++ ++ return devm_hwrng_register(&pdev->dev, trng); ++} ++ ++static const struct of_device_id mtk_rng_v2_match[] = { ++ { .compatible = "mediatek,mt7981-rng" }, ++ { .compatible = "mediatek,mt7987-rng" }, ++ { .compatible = "mediatek,mt7988-rng" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, mtk_rng_v2_match); ++ ++static struct platform_driver mtk_rng_v2_driver = { ++ .probe = mtk_rng_v2_probe, ++ .driver = { ++ .name = KBUILD_MODNAME, ++ .of_match_table = mtk_rng_v2_match, ++ }, ++}; ++module_platform_driver(mtk_rng_v2_driver); ++ ++MODULE_DESCRIPTION("Mediatek Random Number Generator Driver (v2/SMC)"); ++MODULE_AUTHOR("Daniel Golle "); ++MODULE_LICENSE("GPL"); diff --git a/mihomo/transport/vless/vision/padding.go b/mihomo/transport/vless/vision/padding.go index 157dfee861..ac6de886dd 100644 --- a/mihomo/transport/vless/vision/padding.go +++ b/mihomo/transport/vless/vision/padding.go @@ -47,15 +47,21 @@ func ApplyPadding(buffer *buf.Buffer, command byte, userUUID *[]byte, paddingTLS const xrayBufSize = 8192 func (vc *Conn) ReshapeBuffer(buffer *buf.Buffer) []*buf.Buffer { - if buffer.Len() <= xrayBufSize-PaddingHeaderLen { + const bufferLimit = xrayBufSize - PaddingHeaderLen + if buffer.Len() < bufferLimit { return []*buf.Buffer{buffer} } - cutAt := bytes.LastIndex(buffer.Bytes(), tlsApplicationDataStart) - if cutAt == -1 { - cutAt = xrayBufSize / 2 + options := N.NewReadWaitOptions(nil, vc) + var buffers []*buf.Buffer + for buffer.Len() >= bufferLimit { + cutAt := bytes.LastIndex(buffer.Bytes(), tlsApplicationDataStart) + if cutAt < 21 || cutAt > bufferLimit { + cutAt = xrayBufSize / 2 + } + buffer2 := options.NewBuffer() // ensure the new buffer can send used in vc.WriteBuffer + buf.Must(buf.Error(buffer2.ReadFullFrom(buffer, cutAt))) + buffers = append(buffers, buffer2) } - buffer2 := N.NewReadWaitOptions(nil, vc).NewBuffer() // ensure the new buffer can send used in vc.WriteBuffer - buffer2.Write(buffer.From(cutAt)) - buffer.Truncate(cutAt) - return []*buf.Buffer{buffer, buffer2} + buffers = append(buffers, buffer) + return buffers } diff --git a/mihomo/transport/vless/vision/vision.go b/mihomo/transport/vless/vision/vision.go index c5cf3783b2..e9786981eb 100644 --- a/mihomo/transport/vless/vision/vision.go +++ b/mihomo/transport/vless/vision/vision.go @@ -1,4 +1,6 @@ // Package vision implements VLESS flow `xtls-rprx-vision` introduced by Xray-core. +// +// same logic as https://github.com/XTLS/Xray-core/blob/v25.9.11/proxy/proxy.go package vision import ( @@ -27,7 +29,7 @@ func NewConn(conn net.Conn, tlsConn net.Conn, userUUID uuid.UUID) (*Conn, error) ExtendedWriter: N.NewExtendedWriter(conn), Conn: conn, userUUID: userUUID, - packetsToFilter: 6, + packetsToFilter: 8, readProcess: true, readFilterUUID: true, writeFilterApplicationData: true, diff --git a/naiveproxy/.github/workflows/build.yml b/naiveproxy/.github/workflows/build.yml index 9b816615de..790531ed45 100644 --- a/naiveproxy/.github/workflows/build.yml +++ b/naiveproxy/.github/workflows/build.yml @@ -519,7 +519,7 @@ jobs: openwrt_release: '24.10.0' openwrt_gcc_ver: '13.3.0' env: - EXTRA_FLAGS: target_cpu="${{ matrix.target_cpu }}" target_os="openwrt" ${{ matrix.extra }} enable_shadow_metadata=false + EXTRA_FLAGS: target_cpu="${{ matrix.target_cpu }}" target_os="openwrt" ${{ matrix.extra }} OPENWRT_FLAGS: arch=${{ matrix.arch }} release=${{ matrix.openwrt_release || '18.06.0' }} gcc_ver=${{ matrix.openwrt_gcc_ver || '7.3.0' }} ${{ matrix.openwrt }} BUNDLE: naiveproxy-${{ github.event.release.tag_name }}-${{ github.job }}-${{ matrix.arch }} steps: diff --git a/naiveproxy/CHROMIUM_VERSION b/naiveproxy/CHROMIUM_VERSION index bd10cb7e88..80179b13f3 100644 --- a/naiveproxy/CHROMIUM_VERSION +++ b/naiveproxy/CHROMIUM_VERSION @@ -1 +1 @@ -139.0.7258.62 +140.0.7339.123 diff --git a/naiveproxy/src/.clang-format b/naiveproxy/src/.clang-format index 688253e53a..c3c4e3eb8f 100644 --- a/naiveproxy/src/.clang-format +++ b/naiveproxy/src/.clang-format @@ -49,7 +49,7 @@ IncludeCategories: Priority: 5 # ref: https://clang.llvm.org/docs/ClangFormatStyleOptions.html#includeismainregex IncludeIsMainRegex: "\ -(_(32|64|android|apple|chromeos|freebsd|fuchsia|fuzzer|ios|linux|mac|nacl|openbsd|posix|stubs?|win))?\ +(_(32|64|android|apple|chromeos|freebsd|fuchsia|fuzzer|ios|linux|mac|openbsd|posix|stubs?|win))?\ (_(unit|browser|perf)?tests?)?$" # Make sure code like: @@ -65,8 +65,6 @@ CR_BEGIN_MSG_MAP_EX|\ IPC_BEGIN_MESSAGE_MAP|\ IPC_BEGIN_MESSAGE_MAP_WITH_PARAM|\ IPC_PROTOBUF_MESSAGE_TRAITS_BEGIN|\ -IPC_STRUCT_BEGIN|\ -IPC_STRUCT_BEGIN_WITH_PARENT|\ IPC_STRUCT_TRAITS_BEGIN|\ POLPARAMS_BEGIN|\ PPAPI_BEGIN_MESSAGE_MAP$" @@ -75,7 +73,6 @@ CR_END_MSG_MAP|\ END_MSG_MAP|\ IPC_END_MESSAGE_MAP|\ IPC_PROTOBUF_MESSAGE_TRAITS_END|\ -IPC_STRUCT_END|\ IPC_STRUCT_TRAITS_END|\ POLPARAMS_END|\ PPAPI_END_MESSAGE_MAP$" diff --git a/naiveproxy/src/AUTHORS b/naiveproxy/src/AUTHORS index 9ef5696297..be87235814 100644 --- a/naiveproxy/src/AUTHORS +++ b/naiveproxy/src/AUTHORS @@ -100,6 +100,7 @@ Alper Çakan Alvaro Silva Ambareesh Balaji Ambarish Rapte +Ameen Basha Amey Jahagirdar Amit Paul Amit Sarkar @@ -187,6 +188,7 @@ Ayush Dubey Ayush Khandelwal Azhar Shaikh Balazs Kelemen +Baoyu Xu Baul Eun Behara Mani Shyam Patro Bem Jones-Bey @@ -460,6 +462,7 @@ Fernando Jiménez Moreno Finbar Crago François Beaufort François Devatine +Franco Pieri Francois Kritzinger Francois Rauch Frankie Dintino @@ -506,6 +509,7 @@ Guangzhen Li Guobin Wu Gurpreet Kaur Gustav Tiger +Gustavo Martin Gyuyoung Kim Gzob Qq Habib Virji @@ -526,6 +530,7 @@ Haoxuan Zhang Hari Singh Harpreet Singh Khurana Harry Chen +Harsh Singh Harshal Gupta Harshikesh Kumar Harshit Pal @@ -699,6 +704,7 @@ Jihun Brent Kim Jihwan Marc Kim Jihye Hyun Jihyeon Lee +Jim Wu Jin Yang Jincheol Jo Jinfeng Ma @@ -1280,6 +1286,7 @@ Ruben Terrazas Rufus Hamade Ruiyi Luo Rulong Chen +Rulong Chen(陈汝龙) Russell Davis Ryan Ackley Ryan Gonzalez @@ -1399,6 +1406,7 @@ Simeon Kuran Simon Arlott Simon Cadman Simon Jackson +Simon Knott Simon La Macchia Siva Kumar Gunturi Slava Aseev @@ -1577,6 +1585,7 @@ Wanming Lin Wei Li Weicong Yu Wen Fan +Wendi Gan Wenxiang Qian WenSheng He Wesley Lancel @@ -1627,6 +1636,7 @@ Yash Vempati Yash Vinayak Ye Liu Yeol Park +Yeonghan Kim Yeonwoo Jo Yi Shen Yi Sun @@ -1711,6 +1721,8 @@ Zsolt Borbely 郑苏波 (Super Zheng) 一丝 (Yisi) 林训杰 (XunJie Lin) +郭燚 (Yi Guo) +Kevin Wang # Please DO NOT APPEND here. See comments at the top of the file. # END individuals section. diff --git a/naiveproxy/src/DEPS b/naiveproxy/src/DEPS index f42eb01325..6668d42680 100644 --- a/naiveproxy/src/DEPS +++ b/naiveproxy/src/DEPS @@ -49,6 +49,7 @@ gclient_gn_args = [ 'checkout_openxr', 'checkout_src_internal', 'checkout_src_internal_infra', + 'checkout_clusterfuzz_data', 'cros_boards', 'cros_boards_with_qemu_images', 'generate_location_tags', @@ -239,7 +240,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:b0488766ec2a119f97c0189ffa5fff13e4da0131', + 'luci_go': 'git_revision:69966f1a4984c4ade24b8e2e1af0bbc51b64d3c0', # This can be overridden, e.g. with custom_vars, to build clang from HEAD # instead of downloading the prebuilt pinned revision. @@ -261,14 +262,14 @@ vars = { 'reclient_version': 're_client_version:0.179.0.28341fc7-gomaip', # screen-ai CIPD packages - 'screen_ai_linux': 'version:138.06', - 'screen_ai_macos_amd64': 'version:138.06', - 'screen_ai_macos_arm64': 'version:138.06', - 'screen_ai_windows_amd64': 'version:138.06', - 'screen_ai_windows_386': 'version:138.06', + 'screen_ai_linux': 'version:140.02', + 'screen_ai_macos_amd64': 'version:140.02', + 'screen_ai_macos_arm64': 'version:140.02', + 'screen_ai_windows_amd64': 'version:140.02', + 'screen_ai_windows_386': 'version:140.02', # siso CIPD package version. - 'siso_version': 'git_revision:c23de742b8483ddc09d8b68ef845efc7f5c6192f', + 'siso_version': 'git_revision:887a10bc8a038d8e330d06d1ad5ae6ec646f3040', # download libaom test data 'download_libaom_testdata': False, @@ -290,35 +291,35 @@ 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': '87e9a6c12bf53e47654fad919dc90f734e1b08a4', + 'src_internal_revision': 'f4c49123a405af8472494ccdef01a2c27b1ac99e', # 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': 'cbc694239b06ecf694676aba22d5263dbc23ee5e', + 'skia_revision': '1fdbea293a53b270e3f5e74c92cc6670d68412ff', # 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': 'b07b4e9376489c7f7c0ff2af5eceb4261b3bb784', + 'v8_revision': 'fdb12b460f148895f6af2ff0e0d870ff8889f154', # 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': '0145c376fadde16390298681252785f98ae90185', + 'angle_revision': 'a8c8a6febe630c6239a5e207530e9fac651ae373', # 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': 'ed01d9931de34d3a6fb4d615050db5080d9cea16', + 'swiftshader_revision': 'fdb6700ecb04103b658d2e4623d6bc663ba80ea8', # 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': '849572b5c41e5bf59dc88bf54c41067faa9b5b00', + 'pdfium_revision': '1afaa1a380fcd06cec420f3e5b6ec1d2ccb920dc', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. - 'boringssl_revision': '81be8eb2ca225281bb263ac09ece5370d6462a7d', + 'boringssl_revision': '0a0009998fa180695f3e2071805dc03c9a5f3124', # 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:28.20250609.4.1', + 'fuchsia_version': 'version:29.20250730.5.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. @@ -326,7 +327,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': '35b75a2cba6ef72b7ce2b6b94b05c54ca07df866', + 'googletest_revision': '373af2e3df71599b87a40ce0e37164523849166b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling lighttpd # and whatever else without interference from each other. @@ -338,11 +339,11 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling breakpad # and whatever else without interference from each other. - 'breakpad_revision': '9d1f417714a6883f8d4e345c07802eb79edd2e90', + 'breakpad_revision': 'ff252ff6faf5e3a52dc4955aab0d84831697dc94', # 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': '43940e4cb8fa6fec96cd52669544629c5eef58fa', + 'freetype_revision': '27c1cb10a52420515ce66729dfca897be21691b8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling HarfBuzz # and whatever else without interference from each other. @@ -358,19 +359,23 @@ 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': 'c4f7831fe85d210ed50572e54d0cb1a26ccc401a', + 'catapult_revision': '0fd1415f0cf3219ba097d37336141897fab7c5e9', # 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': '77308ff3c8445656fd104cd80e3bd933b23cb05d', + 'crossbench_revision': '69b7e2bb8e1d8d92d4efbb92bcddba3af2716577', + # 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_web_tests_revision': '3c76c8201f0732fe9781742229ab8ac43bf90cbf', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. - 'libfuzzer_revision': 'e31b99917861f891308269c36a32363b120126bb', + 'libfuzzer_revision': 'bea408a6e01f0f7e6c82a43121fe3af4506c932e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling fuzztest # and whatever else without interference from each other. - 'fuzztest_revision': '45a1c3ad5ac3de58c8e9a3f89036e3f954820d4c', + 'fuzztest_revision': '7bab06ff5fbbf8b8cce05a8661369dc2e11cde66', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling domato # and whatever else without interference from each other. @@ -378,7 +383,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': 'bc417052ebef6175721d690a4910e717d92181be', + 'devtools_frontend_revision': '5dbb6f71a9bd613c0403242c7c021652fbf155fd', # 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. @@ -394,7 +399,7 @@ 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': 'mjFmRj7k_XR9yj60pYbr9mG38FyEbU5oWdU56bZQ5cwC', + 'android_sdk_platform-tools_version': 'qTD9QdBlBf3dyHsN1lJ0RH6AhHxR42Hmg2Ih-Vj4zIEC', # 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. @@ -402,11 +407,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. - 'dawn_revision': '46b4670bc67cb4f6d34f6ce6a46ba7e1d6059abf', + 'dawn_revision': '8550f9c1ff8859d25cc49bdfacef083cff2c5121', # 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': '823662119bac4eb4a2771a1d45a8c00b5c6737ce', + 'quiche_revision': '42832178b3b6ae20f0d1c9634c040c528614f45f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ink # and whatever else without interference from each other. @@ -426,7 +431,7 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling jetstream-main # and whatever else without interference from each other. - 'jetstream_main_revision': '6947a460f6b55ef5613c36263049ecf74c5ec1cd', + 'jetstream_main_revision': 'fe1f348226d4b7c3447e606577960a606cc058e4', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling jetstream-v2.2 # and whatever else without interference from each other. @@ -438,11 +443,11 @@ vars = { # 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': 'eb883022a5886739f07f0241f918e2be97d65ff0', + 'crabbyavif_revision': '644c9d84c123ac811a611760a9adc807e3eb5be5', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Speedometer main # and whatever else without interference from each other. - 'speedometer_main_revision': 'ba41f91e480cfd79c97a9d1d70a4c3d42d16c72b', + 'speedometer_main_revision': '87f9ed88c8f8abe3a3bb19b9ec5ea49623d803ad', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Speedometer v3.1 # and whatever else without interference from each other. @@ -462,7 +467,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': 'fff5c22e3178a633f57e4ad1fb5ad96a6116240a', + 'nearby_revision': 'a8889d12a27ef7006d1a47dfefc272e0815f5c41', # 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 +479,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': '97dc8c7a1df880206cc54d9913a7e9d73677072a', + 'cros_components_revision': '7ccdbf60606671c2c057628125908fbfef9bd0c8', # 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 +487,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': 'e44c3c4560f1742744ef3f9fb4217a5f26ebca1b', + 'libcxxabi_revision': 'a6c815c69d55ec59d020abde636754d120b402ad', # 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': '5bbf35ae6801f579c523893176789774c0726e22', + 'libunwind_revision': '84c5262b57147e9934c0a8f2302d989b44ec7093', # 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,26 +503,30 @@ 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': 'dcdd0fa51b65a0b1688ff6b8f0cc81908f09ded2', + 'ffmpeg_revision': 'd2d06b12c22d27af58114e779270521074ff1f85', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling webpagereplay # and whatever else without interference from each other. - 'webpagereplay_revision': 'f3397454e39a7c0b35af192e6d8a1896af7bd9ec', + 'webpagereplay_revision': 'eebd5c62cb5c6a5afbb36eccdcc3b3e01f28adc9', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling llvm-libc # and whatever else without interference from each other. - 'llvm_libc_revision': '79a5aa1b7fcbdf3397bc2a08cbd6ef5c302dfb5a', + 'llvm_libc_revision': '6adc0aa946a413c124758a3a0ac12e5a536c7dd3', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling llvm-libc # and whatever else without interference from each other. - 'compiler_rt_revision': '2a4f69a118bdc5d03c415de1b9b166b2f1d4084f', + 'compiler_rt_revision': 'dc425afb37a69b60c8c02fef815af29e91b61773', + # Three lines of non-changing comments so that + # the commit queue can handle CLs rolling clusterfuzz-data + # and whatever else without interference from each other. + 'clusterfuzz_data_revision':'392cb8a05c3db5963d09b615987fe5fcb081088e', # If you change this, also update the libc++ revision in # //buildtools/deps_revisions.gni. - 'libcxx_revision': '2c359c239b138a20a03f798e47889448ef131c22', + 'libcxx_revision': 'adbb4a5210ae2a8a4e27fa6199221156c02a9b1a', # GN CIPD package version. - 'gn_version': 'git_revision:97b68a0bb62b7528bc3491c7949d6804223c2b82', + 'gn_version': 'git_revision:3a4f5cea73eca32e9586e8145f97b04cbd4a1aee', # ninja CIPD package. 'ninja_package': 'infra/3pp/tools/ninja/', @@ -745,7 +754,7 @@ deps = { 'packages': [ { 'package': 'chrome_internal/third_party/google3/data_sharing_sdk', - 'version': 'UIfm6JqoDwxBPA4coc_W6eoc3FQ7wzG6f66DOgsuU3MC', + 'version': 'i8ho99FBppSWsHbREBeWk-0Ap0kBuB7MRSWBJxWPO_QC', }, ], 'condition': 'checkout_src_internal and non_git_source', @@ -837,143 +846,157 @@ deps = { 'objects': [ { # The Android libclang_rt.builtins libraries are currently only included in the Linux clang package. - 'object_name': 'Linux_x64/clang-llvmorg-21-init-11777-gfd3fecfc-1.tar.xz', - 'sha256sum': '5f69279b3697166facfc354634157e0a8a32fa6e36864200ad8a8f85add3f3f6', - 'size_bytes': 55654416, - 'generation': 1747138963230938, + 'object_name': 'Linux_x64/clang-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': 'b448a78b42740352a37b458115a9482f213097bbf28f1f839e72cab829bdfa6d', + 'size_bytes': 55133120, + 'generation': 1753983011666559, 'condition': '(host_os == "linux" or checkout_android) and non_git_source', }, { - 'object_name': 'Linux_x64/clang-tidy-llvmorg-21-init-11777-gfd3fecfc-1.tar.xz', - 'sha256sum': '9c9cd089b46f36232d7553d03a0b30cf509f5e42b2113fe8172ba14f905b91df', - 'size_bytes': 13597708, - 'generation': 1747138963497696, + 'object_name': 'Linux_x64/clang-tidy-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': '98da47515c1f996bdf884487afff4cca0bbbd6a23347b5fc9442ba4210ca66a2', + 'size_bytes': 13659920, + 'generation': 1753983011671003, 'condition': 'host_os == "linux" and checkout_clang_tidy and non_git_source', }, { - 'object_name': 'Linux_x64/clangd-llvmorg-21-init-11777-gfd3fecfc-1.tar.xz', - 'sha256sum': 'cf580450a46e262d899c2d48fff2b6ea8f6691a6bcfc0c280f87d8b6da088e5f', - 'size_bytes': 13854788, - 'generation': 1747138963598582, + 'object_name': 'Linux_x64/clangd-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': 'e133b8b139770ab170832e1fe68d03453bec0315dbc53ffa6928a61d0f348d41', + 'size_bytes': 13852732, + 'generation': 1753983011663674, 'condition': 'host_os == "linux" and checkout_clangd and non_git_source', }, { - 'object_name': 'Linux_x64/llvm-code-coverage-llvmorg-21-init-11777-gfd3fecfc-1.tar.xz', - 'sha256sum': '1a3488e55d62bda48d09b69fb4e5267ac64247258dc51fd9dabdb7fe5d66da4c', - 'size_bytes': 2297996, - 'generation': 1747138964068040, + 'object_name': 'Linux_x64/llvm-code-coverage-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': '2a61faffe37a31330cd825b567c4a422724b8d35426d79d4ac265f07ab8ecedf', + 'size_bytes': 2314532, + 'generation': 1753983011700114, 'condition': 'host_os == "linux" and checkout_clang_coverage_tools and non_git_source', }, { - 'object_name': 'Linux_x64/llvmobjdump-llvmorg-21-init-11777-gfd3fecfc-1.tar.xz', - 'sha256sum': 'efb127c69ac198284ff3622cd173e9dc4839d0bed33dbcaa96501db169607a2e', - 'size_bytes': 5701128, - 'generation': 1747138963789285, + 'object_name': 'Linux_x64/llvmobjdump-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': '1e4be8737102bff65c33e37867d28960b297bdd718fb43d544e5a977aa73e58e', + 'size_bytes': 5675780, + 'generation': 1753983011751371, 'condition': '((checkout_linux or checkout_mac or checkout_android) and host_os == "linux") and non_git_source', }, { - 'object_name': 'Mac/clang-llvmorg-21-init-11777-gfd3fecfc-1.tar.xz', - 'sha256sum': '3d83bd33ae0a0331ba8e23340023ae05174128503d94116cd8a855913fca88c7', - 'size_bytes': 52212572, - 'generation': 1747138966013176, + 'object_name': 'Mac/clang-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': '0cfd4ac1d5c922f3868b7d0f59731596c9f7651541a4e2cd32fcae91cb707389', + 'size_bytes': 52423592, + 'generation': 1753983013393204, 'condition': 'host_os == "mac" and host_cpu == "x64"', }, { - 'object_name': 'Mac/clang-mac-runtime-library-llvmorg-21-init-11777-gfd3fecfc-1.tar.xz', - 'sha256sum': '809b6f72718d9bcbf25ad6ab80517f215ed2526435a095ee9bceb5ed40f989a2', - 'size_bytes': 993800, - 'generation': 1747138984414942, + 'object_name': 'Mac/clang-mac-runtime-library-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': '6267cf2fdd697c4f5ff60c1ea949dcde2c5638c86c254e410fd8093d8ba88854', + 'size_bytes': 995072, + 'generation': 1753983021140243, 'condition': 'checkout_mac and not host_os == "mac"', }, { - 'object_name': 'Mac/clang-tidy-llvmorg-21-init-11777-gfd3fecfc-1.tar.xz', - 'sha256sum': 'c1fd7930eadede03470cbc8d38697669c6254069da2f6bd58328a8654d68f70d', - 'size_bytes': 13699584, - 'generation': 1747138966324770, + 'object_name': 'Mac/clang-tidy-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': 'cb6aeb04f059f1d504efb4a8e018ce3dd6e71c9ca3b37e07974c1bce9a473444', + 'size_bytes': 13738952, + 'generation': 1753983013426743, 'condition': 'host_os == "mac" and host_cpu == "x64" and checkout_clang_tidy', }, { - 'object_name': 'Mac/clangd-llvmorg-21-init-11777-gfd3fecfc-1.tar.xz', - 'sha256sum': '3aa82177f6e03da693d93aa9f8052fa669af1bd897359a20eaf01379db0924b8', - 'size_bytes': 15136432, - 'generation': 1747138966446697, + 'object_name': 'Mac/clangd-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': 'd4bd53a928a682b68d9f268ef2a7e5fc098090a051944bd3bd293f34920bfa1a', + 'size_bytes': 15157732, + 'generation': 1753983013465928, 'condition': 'host_os == "mac" and host_cpu == "x64" and checkout_clangd', }, { - 'object_name': 'Mac/llvm-code-coverage-llvmorg-21-init-11777-gfd3fecfc-1.tar.xz', - 'sha256sum': '1f8d0d65f9d027707890c28433b0bfe29e32551008e9f3c1b9803318ede2bfc6', - 'size_bytes': 2272500, - 'generation': 1747138966854415, + 'object_name': 'Mac/llvm-code-coverage-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': 'a3aa1c0792baa8aba7e91fb9d72ec80c2fe6bb88ced406660f23e5b93c40e88c', + 'size_bytes': 2282708, + 'generation': 1753983013526049, 'condition': 'host_os == "mac" and host_cpu == "x64" and checkout_clang_coverage_tools', }, { - 'object_name': 'Mac_arm64/clang-llvmorg-21-init-11777-gfd3fecfc-1.tar.xz', - 'sha256sum': '2d5660c50637a7ee6e5501525e7588bb255cdfd48e792b12b86ae7113c31b8ae', - 'size_bytes': 44214476, - 'generation': 1747138986010150, + 'object_name': 'Mac/llvmobjdump-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': '3ee5d49e92ad6cd1e532118f0713532962d6ef14aa119f81a893b72c95046ac6', + 'size_bytes': 5484504, + 'generation': 1753983013468350, + 'condition': 'host_os == "mac" and host_cpu == "x64"', + }, + { + 'object_name': 'Mac_arm64/clang-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': 'afed7bb50e1e7f25472f3a43e942a774c3ef5dcc31a1a9cf817224aec411f4fb', + 'size_bytes': 44337520, + 'generation': 1753983022809149, 'condition': 'host_os == "mac" and host_cpu == "arm64"', }, { - 'object_name': 'Mac_arm64/clang-tidy-llvmorg-21-init-11777-gfd3fecfc-1.tar.xz', - 'sha256sum': 'c17b6d7d112ff54699477d5fc7f5009e7b650d263d127cad4f8406f8df914996', - 'size_bytes': 11838956, - 'generation': 1747138986259606, + 'object_name': 'Mac_arm64/clang-tidy-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': '51e2940861747013b11833da69821364552776e29be54287e7d8b299c35357de', + 'size_bytes': 11873540, + 'generation': 1753983022864078, 'condition': 'host_os == "mac" and host_cpu == "arm64" and checkout_clang_tidy', }, { - 'object_name': 'Mac_arm64/clangd-llvmorg-21-init-11777-gfd3fecfc-1.tar.xz', - 'sha256sum': 'd6c134df8273fe9c4c2b5ff5786f2ceeb9ed5f251e223e55edbc0cd7aa772e83', - 'size_bytes': 12115024, - 'generation': 1747138986359326, + 'object_name': 'Mac_arm64/clangd-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': '3344e7ed3d42be6c827502e2c4addbae42dfbe9699e5e391649fdf53ce3d16d7', + 'size_bytes': 12136100, + 'generation': 1753983022893296, 'condition': 'host_os == "mac" and host_cpu == "arm64" and checkout_clangd', }, { - 'object_name': 'Mac_arm64/llvm-code-coverage-llvmorg-21-init-11777-gfd3fecfc-1.tar.xz', - 'sha256sum': '82ca9187d1fd5ed14266612339b921d560b1008f92e1719255b755ff882d23e3', - 'size_bytes': 1982036, - 'generation': 1747138986831545, + 'object_name': 'Mac_arm64/llvm-code-coverage-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': '59709d0a6bc2f1930c0971b4f0cf4d8932d1321621cff570419342ee396cc43e', + 'size_bytes': 1989132, + 'generation': 1753983022902753, 'condition': 'host_os == "mac" and host_cpu == "arm64" and checkout_clang_coverage_tools', }, { - 'object_name': 'Win/clang-llvmorg-21-init-11777-gfd3fecfc-1.tar.xz', - 'sha256sum': '39e17b8282b9f1e3cbc6b22d3144696728c867f3ae66694b0125c3ed60755401', - 'size_bytes': 47250032, - 'generation': 1747139012194774, + 'object_name': 'Mac_arm64/llvmobjdump-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': '76f2d491e7535e6051f3a6bc4a6948602a8e4a231882305e13c9adb9ce6af125', + 'size_bytes': 5313688, + 'generation': 1753983022869504, + 'condition': 'host_os == "mac" and host_cpu == "arm64"', + }, + { + 'object_name': 'Win/clang-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': '418c186740c926b9ba85c173540ffa3ed459e3fab06ee45fe524f9b480c2a7a6', + 'size_bytes': 47378940, + 'generation': 1753983032535097, 'condition': 'host_os == "win"', }, { - 'object_name': 'Win/clang-tidy-llvmorg-21-init-11777-gfd3fecfc-1.tar.xz', - 'sha256sum': '9dec82a917bd55947e39891137ba5c13663ca94d2c102d56eb52b9b176365910', - 'size_bytes': 13492960, - 'generation': 1747139012510054, + 'object_name': 'Win/clang-tidy-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': '0865195b3efdaab630f9acb06d4a4e414813752b28f7511dddf3cd69e38df4a0', + 'size_bytes': 13488148, + 'generation': 1753983032729035, 'condition': 'host_os == "win" and checkout_clang_tidy', }, { - 'object_name': 'Win/clang-win-runtime-library-llvmorg-21-init-11777-gfd3fecfc-1.tar.xz', - 'sha256sum': '220abd9ce9a85446a2e7879aab3c1f2f5393665f6b13b067f8cec565ae7d36eb', - 'size_bytes': 2486856, - 'generation': 1747139033547001, + 'object_name': 'Win/clang-win-runtime-library-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': '2a7678deda052620fa8aff586922d1607d1e39e51726dee9e9325a668c495df4', + 'size_bytes': 2506544, + 'generation': 1753983040294404, 'condition': 'checkout_win and not host_os == "win"', }, { - 'object_name': 'Win/clangd-llvmorg-21-init-11777-gfd3fecfc-1.tar.xz', - 'sha256sum': '81fa230b6311e3e50147cae3acd6d2c83c1bef13ff46df3df3d580ca911e9d15', - 'size_bytes': 13918432, - 'generation': 1747139013351355, + 'object_name': 'Win/clangd-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': '79a70ce9405ed33f4dfddb4d3be82d827964fb79b898b82f892d9855d5dd3195', + 'size_bytes': 13904768, + 'generation': 1753983032665184, 'condition': 'host_os == "win" and checkout_clangd', }, { - 'object_name': 'Win/llvm-code-coverage-llvmorg-21-init-11777-gfd3fecfc-1.tar.xz', - 'sha256sum': '611b9689c3d3e80ab7485e698f6b67e0df328b5407f30f177c29fe394b81a13e', - 'size_bytes': 2378584, - 'generation': 1747139013764369, + 'object_name': 'Win/llvm-code-coverage-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': 'b57dddb09757df2bb2bfd83e57a87c3f1da72a700afb66e853f60fe0102e1ba3', + 'size_bytes': 2384644, + 'generation': 1753983032706862, 'condition': 'host_os == "win" and checkout_clang_coverage_tools', }, { - 'object_name': 'Win/llvmobjdump-llvmorg-21-init-11777-gfd3fecfc-1.tar.xz', - 'sha256sum': '67a05210ee38b2f575df3cc1feb04ed36b4186748c2d769e2201572b413305fe', - 'size_bytes': 5698204, - 'generation': 1747139013159526, + 'object_name': 'Win/llvmobjdump-llvmorg-21-init-16348-gbd809ffb-15.tar.xz', + 'sha256sum': '4fd02b442dcb5cc8f4a80e4c8e6aeb972dc0163a8ee79b3ce3416d9cc24cb137', + 'size_bytes': 5654156, + 'generation': 1753983032704697, 'condition': '(checkout_linux or checkout_mac or checkout_android) and host_os == "win"', }, ] @@ -984,31 +1007,31 @@ deps = { 'bucket': 'chromium-browser-clang', 'objects': [ { - 'object_name': 'Linux_x64/rust-toolchain-4a0969e06dbeaaa43914d2d00b2e843d49aa3886-1-llvmorg-21-init-11777-gfd3fecfc.tar.xz', - 'sha256sum': 'df1573701599cb7d00c1050b71636a436320b8ad47bb09cb46d6e96b3f8ac585', - 'size_bytes': 118529212, - 'generation': 1747160498430964, + 'object_name': 'Linux_x64/rust-toolchain-22be76b7e259f27bf3e55eb931f354cd8b69d55f-3-llvmorg-21-init-16348-gbd809ffb.tar.xz', + 'sha256sum': '5f8e9ad847e5bf586e0de1bb563c9a49e05ad36edfad5037900d7510004fc577', + 'size_bytes': 138573136, + 'generation': 1750840933611077, 'condition': 'host_os == "linux" and non_git_source', }, { - 'object_name': 'Mac/rust-toolchain-4a0969e06dbeaaa43914d2d00b2e843d49aa3886-1-llvmorg-21-init-11777-gfd3fecfc.tar.xz', - 'sha256sum': '83836493c8a81b212c20e16666c6b918bff28748f4d6685c5107eb7e9d16f6fe', - 'size_bytes': 111691772, - 'generation': 1747160500088595, + 'object_name': 'Mac/rust-toolchain-22be76b7e259f27bf3e55eb931f354cd8b69d55f-3-llvmorg-21-init-16348-gbd809ffb.tar.xz', + 'sha256sum': '357db812ca0a518ef0fc4394ddc859d68f23384931294412b7424bb3aabb3c09', + 'size_bytes': 132392604, + 'generation': 1750840935469331, 'condition': 'host_os == "mac" and host_cpu == "x64"', }, { - 'object_name': 'Mac_arm64/rust-toolchain-4a0969e06dbeaaa43914d2d00b2e843d49aa3886-1-llvmorg-21-init-11777-gfd3fecfc.tar.xz', - 'sha256sum': 'd975e322a2e5c680b54f27a6545c63c0de2c5367ca6ffefda04de491d6b76553', - 'size_bytes': 102206348, - 'generation': 1747160501743827, + 'object_name': 'Mac_arm64/rust-toolchain-22be76b7e259f27bf3e55eb931f354cd8b69d55f-3-llvmorg-21-init-16348-gbd809ffb.tar.xz', + 'sha256sum': 'd3cb60c6388e86d3d1a0c46c539f1ea0ed1ff48cf907dc21b2cb5ff441b23c03', + 'size_bytes': 120354192, + 'generation': 1750840937280735, 'condition': 'host_os == "mac" and host_cpu == "arm64"', }, { - 'object_name': 'Win/rust-toolchain-4a0969e06dbeaaa43914d2d00b2e843d49aa3886-1-llvmorg-21-init-11777-gfd3fecfc.tar.xz', - 'sha256sum': '25c51b4c2e0e8b4e974973f0357b12ecb645a0a7a136f9e0a6604e87c21acc7a', - 'size_bytes': 193582440, - 'generation': 1747160503376785, + 'object_name': 'Win/rust-toolchain-22be76b7e259f27bf3e55eb931f354cd8b69d55f-3-llvmorg-21-init-16348-gbd809ffb.tar.xz', + 'sha256sum': '7e804f3a8bef4c8ca32d3368ca7564e5c12b684899453d9a522bdd05b1f1df7b', + 'size_bytes': 195000356, + 'generation': 1750840939064273, 'condition': 'host_os == "win"', }, ], @@ -1159,6 +1182,28 @@ deps = { 'dep_type': 'cipd', }, + 'src/chrome/android/orderfiles/arm': { + 'packages': [ + { + 'package': 'chromium/chrome/android/orderfiles/arm', + 'version': 'Zwbd6e_c1R4CLUGOn6nPr6PS4s3FADAGPvrOkCU_gb0C', + }, + ], + 'condition': 'checkout_android', + 'dep_type': 'cipd', + }, + + 'src/chrome/android/orderfiles/arm64': { + 'packages': [ + { + 'package': 'chromium/chrome/android/orderfiles/arm64', + 'version': 'zGVpdGw8UhIPfmSfbyetTbDtROZ9HxEbT1uMmOW_F3YC', + }, + ], + 'condition': 'checkout_android', + 'dep_type': 'cipd', + }, + 'src/chrome/browser/resources/preinstalled_web_apps/internal': { 'url': Var('chrome_git') + '/chrome/components/default_apps.git' + '@' + '656ac90405cdbb7d7ab05c54a1628c6d7418832e', 'condition': 'checkout_src_internal', @@ -1196,7 +1241,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/updater/chrome_linux64', - 'version': 'ytJ0UbU9gMLUMLRQlmqQpGpOy1dYswI3rOJ0ILnIFbUC', + 'version': 'version:2@140.0.7273.0', }, ], }, @@ -1207,7 +1252,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/updater/chrome_mac_universal', - 'version': 'gzutuY-G7u8n5746jgmishm8uWjUR070TXdFc23Ea7YC', + 'version': 'version:2@140.0.7273.0', }, ], }, @@ -1218,44 +1263,40 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/updater/chrome_mac_universal_prod', - # 138.0.7194.0 - 'version': 'RUzQ5K8MJXrR4gyHEiCfYR2AMjD-zb6b6c242SR6IOkC', + 'version': 'version:2@140.0.7273.0', }, ], }, - # version:2@132.0.6833.0 'src/third_party/updater/chrome_win_arm64/cipd': { 'dep_type': 'cipd', 'condition': 'checkout_win', 'packages': [ { 'package': 'chromium/third_party/updater/chrome_win_arm64', - 'version': 'OoGMyCUHah7D_AOVm4RpVoPOdkGqjFHuSMcoKTZ0rlsC', + 'version': 'version:2@140.0.7273.0', }, ], }, - # version:2@132.0.6833.0 'src/third_party/updater/chrome_win_x86/cipd': { 'dep_type': 'cipd', 'condition': 'checkout_win', 'packages': [ { 'package': 'chromium/third_party/updater/chrome_win_x86', - 'version': 'gqhcrVQFtXAKUu7yEISTlbrBpPaBUnQZ6FdOo5E4HLQC', + 'version': 'version:2@140.0.7273.0', }, ], }, - # version:2@132.0.6833.0 'src/third_party/updater/chrome_win_x86_64/cipd': { 'dep_type': 'cipd', 'condition': 'checkout_win', 'packages': [ { 'package': 'chromium/third_party/updater/chrome_win_x86_64', - 'version': 'koo1i4cAVdOK2-re2VGbx-crCcbTz9h0qumUk1hyEt0C', + 'version': 'version:2@140.0.7273.0', }, ], }, @@ -1289,7 +1330,6 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/updater/chrome_mac_universal_prod', - # 129.0.6651.0 'version': 'IrAigaqukp1GbaksroZcR3Jo0oOYKg9kzatjzNNbXKQC', }, ], @@ -1334,7 +1374,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/updater/chromium_linux64', - 'version': 'OLbfeePAbqPnFqcPmkFtR-GK8dN3T3NeH2AChZwBHjgC', + 'version': 'version:2@1496001', }, ], }, @@ -1346,7 +1386,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/updater/chromium_mac_amd64', - 'version': 'zVv93X5XSClxTR1YejkQuBdSpye7JfPS_h6GcH1N4i4C', + 'version': 'version:2@1491002', }, ], }, @@ -1358,43 +1398,40 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/updater/chromium_mac_arm64', - 'version': 'Va20qxSst3lq4WfEZlWiwzXCpSo5XbhhuqJXyqzvhF8C', + 'version': 'version:2@1490005', }, ], }, - # r1372006 'src/third_party/updater/chromium_win_arm64/cipd': { 'dep_type': 'cipd', 'condition': 'checkout_win', 'packages': [ { 'package': 'chromium/third_party/updater/chromium_win_arm64', - 'version': 'ksRzLnqewvz7P-YMX2e8mxZuDI1hgPtLNCuAXIisXhoC', + 'version': 'version:2@1491011', }, ], }, - # r1372046 'src/third_party/updater/chromium_win_x86/cipd': { 'dep_type': 'cipd', 'condition': 'checkout_win', 'packages': [ { 'package': 'chromium/third_party/updater/chromium_win_x86', - 'version': 'tcFWGGE3wmwKDhT_s-9mzPiQVYxMOI1U9sRAhm1_5QcC', + 'version': 'version:2@1496001', }, ], }, - # r1372030 'src/third_party/updater/chromium_win_x86_64/cipd': { 'dep_type': 'cipd', 'condition': 'checkout_win', 'packages': [ { 'package': 'chromium/third_party/updater/chromium_win_x86_64', - 'version': 'iXamEEmbStVBV_c-vEG4Xtrda8tTqSRCZ-tmE7VRHb0C', + 'version': 'version:2@1496004', }, ], }, @@ -1406,7 +1443,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/updater/chromium_linux64', - 'version': 'version:2@1477001', + 'version': 'OLbfeePAbqPnFqcPmkFtR-GK8dN3T3NeH2AChZwBHjgC', }, ], }, @@ -1417,7 +1454,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/updater/chromium_mac_amd64', - 'version': 'version:2@1477001', + 'version': 'zVv93X5XSClxTR1YejkQuBdSpye7JfPS_h6GcH1N4i4C', }, ], }, @@ -1428,7 +1465,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/updater/chromium_mac_arm64', - 'version': 'version:2@1477001', + 'version': 'Va20qxSst3lq4WfEZlWiwzXCpSo5XbhhuqJXyqzvhF8C', }, ], }, @@ -1472,7 +1509,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/enterprise_companion/chromium_linux64', - 'version': 'iwCwxMXVY0_oAVNP7XtqnJKKL9jfI9WK_Jwv_DL7qjQC', + 'version': 'c-3HHiNKBHRve_MJrrUnwxI5SZ7giWyIaaGJHU8pjTEC', }, ], }, @@ -1483,7 +1520,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/enterprise_companion/chromium_mac_amd64', - 'version': '2LSXZdphQPwKLxjSeMUhkHedkGFEAK55ymGWiOcnfLQC', + 'version': 'ZXik2MzB8S6g1-HZA6oFeGDAt_0wJc8FSis7qRKpkEYC', }, ], }, @@ -1494,7 +1531,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/enterprise_companion/chromium_mac_arm64', - 'version': 'vYq1wh1oMhbtZjMiMsX2BtyHqHAyT1EmfrW1kXGNj3YC', + 'version': 'kPgLQAjvoRkS1vb_CENY8g5YWhaRhSzZyrHyz3GaMF4C', }, ], }, @@ -1505,7 +1542,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/enterprise_companion/chromium_win_x86', - 'version': 'dnOfSfX6zBCjpn1hA43h0D1uBls4BnJoAkHMDQo85ScC', + 'version': 'YoKJcQ41yn2CLo3UEebIJ6ba7nqV_6EJHRHW3f0FhjAC', }, ], }, @@ -1516,13 +1553,13 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/enterprise_companion/chromium_win_x86_64', - 'version': 'q7xjPQfd7rTuo4OjmjLq2F-wpDXnPsPZKlmzrlFQkYYC', + 'version': 'c6fb8bBjJbS3FTvo7ahNm30kd-zLLc-YO13KTDe60ZcC', }, ], }, 'src/chrome/test/data/autofill/captured_sites/artifacts': { - 'url': Var('chrome_git') + '/chrome/test/captured_sites/autofill.git' + '@' + 'e5aa37b4b290c94d642cbc85e7777de838db86f7', + 'url': Var('chrome_git') + '/chrome/test/captured_sites/autofill.git' + '@' + '9745df742e0a2875264ac9d0288a7cea4b8124ff', 'condition': 'checkout_chromium_autofill_test_dependencies', }, @@ -1552,7 +1589,7 @@ deps = { 'packages': [ { 'package': 'chromium/chrome/test/data/variations/cipd', - 'version': 'ReWAdAhFsmTN1Z6g09iwNFqpNxVIeGzINfzDf4EumCUC', + 'version': 'JuyQiG_WK-ei7GyfJTjYoEiBh4bmo4lIc8ZFrDUv8t8C', }, ], 'dep_type': 'cipd', @@ -1563,21 +1600,21 @@ deps = { 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '55ad8668428d4af7ba27030669a0eeaff98fee13', + '058e9b2aa355eaba5eaf0b2511a814dea5e75a8a', 'condition': 'checkout_android and checkout_src_internal', }, 'src/docs/website': { - 'url': Var('chromium_git') + '/website.git' + '@' + 'a812d22617824ad2cd291e110378ccec5ae7735f', + 'url': Var('chromium_git') + '/website.git' + '@' + 'a89f6810f6a5b0e11e4ec00387e9f97e8f6c23ae', }, 'src/ios/third_party/earl_grey2/src': { - 'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '3894e319725773683ded248ee6dedea5b29a3189', + 'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + 'd5b5f18f3cf231f3b3c53a898780926aaeed2905', 'condition': 'checkout_ios', }, 'src/ios/third_party/edo/src': { - 'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + '38e71ff183d76f702db6966fa7236c98831acd80', + 'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + 'd228369931f0872e32743ca2cbfea72eaf2e44bc', 'condition': 'checkout_ios', }, @@ -1592,7 +1629,7 @@ deps = { }, 'src/ios/third_party/material_components_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'b29adefbd8be6d39542d679b8f9189fc466283b7', + 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '266bcd2e07d99bac742fd14f67b8fdc6e26169a5', 'condition': 'checkout_ios', }, @@ -1687,10 +1724,6 @@ deps = { 'dep_type': 'cipd', }, - 'src/third_party/accessibility_test_framework/src': { - 'url': Var('chromium_git') + '/external/github.com/google/Accessibility-Test-Framework-for-Android.git' + '@' + '4a764c690353ea136c82f1a696a70bf38d1ef5fe', - }, - 'src/third_party/android_build_tools/protoc/cipd': { 'packages': [ { @@ -1717,7 +1750,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': 'QYckO8Ulw3I5dZsuBNrg-nCGi9Xh6rVDTCewemHdCgsC', + 'version': 'IG08WxVoI4_gwNrbpXqXXmytPWFopEI1x0EaFC1KosAC', }, ], 'condition': 'checkout_android and non_git_source', @@ -1744,7 +1777,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_build_tools/aapt2', - 'version': '_lNsOL_GGlXLOIMGtrbMOqNd7TQHabaP1q8SlvUpFbMC', + 'version': '2Tff49a5dYTM5YvxxqyOsTQ9k8nOqM4ayydbCuKoxIwC', }, ], 'condition': 'checkout_android and non_git_source', @@ -1788,7 +1821,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_build_tools/error_prone', - 'version': 'KOECi08Fw4fRTVXkKocxg94coB-e_dlcHRokC21yxyoC', + 'version': '56Xo0VEDkKxzOr5L7pafI6SaIY2S7wnOOcgy4CNSANEC', }, ], 'condition': 'checkout_android and non_git_source', @@ -1810,7 +1843,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_build_tools/lint', - 'version': 'RevkTwhOQRk-oOzI4BBk3FYEeVAlBijeTqjNPrGsi_8C', + 'version': 'AGywP4kNoPZjZa3fVdf1g2cKgEPkXnVFRxhlFjroXJcC', }, ], 'condition': 'checkout_android and non_git_source', @@ -1821,7 +1854,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_build_tools/manifest_merger', - 'version': 'v0s5-TwZ9OxfzbqU5ULhQ7vufSuKIIld6Z7TK8artzoC', + 'version': 'K-0K2jznbc6LGEnKhT8NliSShwC43TBuVFZ6gRjOuxgC', }, ], 'condition': 'checkout_android and non_git_source', @@ -1870,7 +1903,7 @@ deps = { Var('chromium_git') + '/angle/angle.git' + '@' + Var('angle_revision'), 'src/third_party/anonymous_tokens/src': - Var('chromium_git') + '/external/github.com/google/anonymous-tokens.git' + '@' + 'd708a2602a5947ee068f784daa1594a673d47c4a', + Var('chromium_git') + '/external/github.com/google/anonymous-tokens.git' + '@' + '50b2ee441f1c3bad73ab7430c41fd1ea5a7a06a6', 'src/third_party/blink/renderer/core/css/perftest_data': { 'dep_type': 'gcs', @@ -1950,7 +1983,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' + '@' + '63bf075aada99afa112f84c61ddc9cead8ce04d3', + Var('chromium_git') + '/external/github.com/videolan/dav1d.git' + '@' + '716164239ad6e6b11c5dcdaa3fb540309d499833', 'src/third_party/dawn': Var('dawn_git') + '/dawn.git' + '@' + Var('dawn_revision'), @@ -1963,11 +1996,6 @@ deps = { 'condition': 'checkout_android', }, - 'src/third_party/barhopper': { - 'url': Var('chrome_git') + '/chrome/deps/barhopper.git' + '@' + '9230af4dc38c6d2cc9c0841692267762ebfca991', - 'condition': 'checkout_src_internal and checkout_chromeos', - }, - 'src/third_party/google_benchmark/src': Var('chromium_git') + '/external/github.com/google/benchmark.git' + '@' + '761305ec3b33abf30e08d50eb829e19a802581cc', @@ -2023,7 +2051,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' + '@' + '341c29acc0a4e66ced602961622ad06a434de62d', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '3411a369f26bdab1098052dcc0805fe3e1063e4b', 'condition': 'checkout_chromeos', }, @@ -2037,23 +2065,25 @@ 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' + '@' + 'd7427551d6531037da216d20cd36feb19ed4905f', + Var('chromium_git') + '/external/github.com/pytorch/cpuinfo.git' + '@' + '33ed0be77d7767d0e2010e2c3cf972ef36c7c307', 'src/third_party/crc32c/src': Var('chromium_git') + '/external/github.com/google/crc32c.git' + '@' + 'd3d60ac6e0f16780bcfcc825385e1d338801a558', # For Linux and Chromium OS. 'src/third_party/cros_system_api': { - 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '349c5cb547162b967df40a336fc08bb18819a5e1', + 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '07b9fafa3fff468afa2960789d2b28444c38db3e', 'condition': 'checkout_linux or checkout_chromeos', }, 'src/third_party/crossbench': Var('chromium_git') + '/crossbench.git' + '@' + Var('crossbench_revision'), + 'src/third_party/crossbench-web-tests': + Var('chromium_git') + '/chromium/web-tests.git' + '@' + Var('crossbench_web_tests_revision'), 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'ea7a0baff0d8554cf6d38f525b4e7882c2b4ec18', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '7d1e2bdb9168718566caba63a170a67cdab2356b', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -2065,7 +2095,7 @@ deps = { Var('chromium_git') + '/external/github.com/jk-jeon/dragonbox.git' + '@' + '6c7c925b571d54486b9ffae8d9d18a822801cbda', 'src/third_party/eigen3/src': - Var('chromium_git') + '/external/gitlab.com/libeigen/eigen.git' + '@' + 'd0b490ee091629068e0c11953419eb089f9e6bb2', + Var('chromium_git') + '/external/gitlab.com/libeigen/eigen.git' + '@' + '81044ec13df7608d0d9d86aff2ef9805fc69bed1', 'src/third_party/emoji-metadata/src': { 'url': Var('chromium_git') + '/external/github.com/googlefonts/emoji-metadata' + '@' + '045f146fca682a836e01cd265171312bfb300e06', @@ -2098,9 +2128,8 @@ deps = { 'src/third_party/flatbuffers/src': Var('chromium_git') + '/external/github.com/google/flatbuffers.git' + '@' + '8db59321d9f02cdffa30126654059c7d02f70c32', - # Used for embedded builds. CrOS & Linux use the system version. 'src/third_party/fontconfig/src': { - 'url': Var('chromium_git') + '/external/fontconfig.git' + '@' + 'c527fe1452d469e5fa1a211180dd40bcdb79fb2a', + 'url': Var('chromium_git') + '/external/fontconfig.git' + '@' + '86b48ec01ece451d5270d0c5181a43151e45a042', 'condition': 'checkout_linux', }, @@ -2163,7 +2192,7 @@ deps = { Var('chromium_git') + '/external/github.com/google/googletest.git' + '@' + Var('googletest_revision'), 'src/third_party/gperf': { - 'url': Var('chromium_git') + '/chromium/deps/gperf.git' + '@' + 'd892d79f64f9449770443fb06da49b5a1e5d33c1', + 'url': Var('chromium_git') + '/chromium/deps/gperf.git' + '@' + 'e9eeea862a18e77b945d98eff7e1bf065d3daf8e', 'condition': 'checkout_win', }, @@ -2229,7 +2258,7 @@ deps = { Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + '41cdffd71c9948f63c7ad36e1fb0ff519aa7a37e', 'src/third_party/icu': - Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'b929596baebf0ab4ac7ec07f38365db4c50a559d', + Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '1b2e3e8a421efae36141a7b932b41e315b089af8', 'src/third_party/icu4j/cipd': { 'packages': [ @@ -2296,7 +2325,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/kotlin_stdlib', - 'version': 'Ly_nOcmB3VyAmA3kTKonDTj_hmJ8y1ij5aTcLYpERbYC', + 'version': 'jHhaILmhjHo4cYTvCdIRMwWPOAGSwjhEtrMxwREj52gC', }, ], 'condition': 'checkout_android and non_git_source', @@ -2307,7 +2336,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/kotlinc', - 'version': 'Z5tCYfpRej0QQvZLXjrGdS4s0SY8h10GnAqpVv05eWsC', + 'version': 'clr2_okgxf1Zih4H2dIOKUWGJhrBo7fj3ZZ6nKV0dJIC', }, ], 'condition': 'checkout_android and non_git_source', @@ -2330,7 +2359,7 @@ deps = { Var('chromium_git') + '/external/libaddressinput.git' + '@' + '2610f7b1043d6784ada41392fc9392d1ea09ea07', 'src/third_party/libaom/source/libaom': - Var('aomedia_git') + '/aom.git' + '@' + '0ddc6630b3723b14b164752d46c27752f078ddd3', + Var('aomedia_git') + '/aom.git' + '@' + 'e91b7aa26d6d0979bba2bee5e1c27a7a695e0226', 'src/third_party/crabbyavif/src': Var('chromium_git') + '/external/github.com/webmproject/CrabbyAvif.git' + '@' + Var('crabbyavif_revision'), @@ -2436,7 +2465,7 @@ deps = { }, 'src/third_party/libunwindstack': { - 'url': Var('chromium_git') + '/chromium/src/third_party/libunwindstack.git' + '@' + '0d758dd57f42564acecdd7a1e7ac5c8521c1b01a', + 'url': Var('chromium_git') + '/chromium/src/third_party/libunwindstack.git' + '@' + '68973d9d4690b905cab27a553a0892868b697e4a', 'condition': 'checkout_android', }, @@ -2444,16 +2473,16 @@ deps = { Var('chromium_git') + '/chromiumos/platform/libva-fake-driver.git' + '@' + 'a9bcab9cd6b15d4e3634ca44d5e5f7652c612194', 'src/third_party/libvpx/source/libvpx': - Var('chromium_git') + '/webm/libvpx.git' + '@' + '686bf6f1cde888898498f89ba9aefa66b683566a', + Var('chromium_git') + '/webm/libvpx.git' + '@' + 'a985e5e847a2fe69bef3e547cf25088132194e39', 'src/third_party/libwebm/source': - Var('chromium_git') + '/webm/libwebm.git' + '@' + 'c4522d6cd68582d66f1adfd24debfa9bee202afa', + Var('chromium_git') + '/webm/libwebm.git' + '@' + 'f2a982d748b80586ae53b89a2e6ebbc305848b8c', 'src/third_party/libwebp/src': - Var('chromium_git') + '/webm/libwebp.git' + '@' + '2af6c034ac871c967e04c8c9f8bf2dbc2e271b18', + Var('chromium_git') + '/webm/libwebp.git' + '@' + '4fa21912338357f89e4fd51cf2368325b59e9bd9', 'src/third_party/libyuv': - Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '88798bcd636a93e92d69242da914deb4cec1dfb6', + Var('chromium_git') + '/libyuv/libyuv.git' + '@' + 'cdd3bae84818e78466fec1ce954eead8f403d10c', 'src/third_party/lighttpd': { 'url': Var('chromium_git') + '/chromium/deps/lighttpd.git' + '@' + Var('lighttpd_revision'), @@ -2498,7 +2527,7 @@ deps = { }, 'src/third_party/microsoft_dxheaders/src': { - 'url': Var('chromium_git') + '/external/github.com/microsoft/DirectX-Headers.git' + '@' + 'd9020edfc69b789653e04fa2d8d10ee3317ffa56', + 'url': Var('chromium_git') + '/external/github.com/microsoft/DirectX-Headers.git' + '@' + '8287305d36a2f717260dbbba7b6f5fae36f0f88a', 'condition': 'checkout_win', }, @@ -2533,7 +2562,7 @@ deps = { Var('chromium_git') + '/external/github.com/intel/ARM_NEON_2_x86_SSE.git' + '@' + 'eb8b80b28f956275e291ea04a7beb5ed8289e872', 'src/third_party/netty-tcnative/src': { - 'url': Var('chromium_git') + '/external/netty-tcnative.git' + '@' + '035726f76293d142ec3c4464be0703605feb4d02', + 'url': Var('chromium_git') + '/external/netty-tcnative.git' + '@' + 'b21c6eee658866b83122c674e3c0da054e09a3d7', 'condition': 'checkout_android', }, @@ -2567,10 +2596,10 @@ deps = { Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '652bdb7719f30b52b08e506645a7322ff1b2cc6f', 'src/third_party/openscreen/src': - Var('chromium_git') + '/openscreen' + '@' + 'dd421dc540e75bd4e52388dcb0656d4d96137a73', + Var('chromium_git') + '/openscreen' + '@' + 'f51be2dd676c855bc588a439f002bc941b87db6b', 'src/third_party/openxr/src': { - 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + '781f2eab3698d653c804ecbd11e0aed47eaad1c6', + 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + '57572a0e91890fe7183de25a62153aec955d64ba', 'condition': 'checkout_openxr', }, @@ -2593,7 +2622,7 @@ deps = { Var('pdfium_git') + '/pdfium.git' + '@' + Var('pdfium_revision'), 'src/third_party/perfetto': - Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + '18d4fdc15d027a989db705592585b924f93f1d42', + Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + '4ab725613a8ee64e9acd7930eceb8995e24df562', 'src/base/tracing/test/data': { 'bucket': 'perfetto', @@ -2737,7 +2766,7 @@ deps = { Var('chromium_git') + '/external/github.com/protocolbuffers/protobuf-javascript' + '@' + '28bf5df73ef2f345a936d9cc95d64ba8ed426a53', 'src/third_party/pthreadpool/src': - Var('chromium_git') + '/external/github.com/google/pthreadpool.git' + '@' + 'dcc9f28589066af0dbd4555579281230abbf74dd', + Var('chromium_git') + '/external/github.com/google/pthreadpool.git' + '@' + '149f0a86f5ad215e9f0441684385ce09f345dbe4', # Dependency of skia. 'src/third_party/pyelftools': { @@ -2764,13 +2793,13 @@ deps = { }, 'src/third_party/re2/src': - Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + 'c84a140c93352cdabbfb547c531be34515b12228', + Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + '8451125897dd7816a5c118925e8e42309d598ecc', 'src/third_party/r8/cipd': { 'packages': [ { 'package': 'chromium/third_party/r8', - 'version': '9vZCRnASPSjh3_T-2AsumCO_8C5PuBJ5-e84K9b7-80C', + 'version': 'qD5apdNjxRv3dBblf27nEZYf7r_pbLEgfN7hWyXvP_UC', }, ], 'condition': 'checkout_android and non_git_source', @@ -2784,7 +2813,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/r8', - 'version': 'F0pTWc6uG70kZPngypnQxCgD3CgY5D8O-pDqj_qeoQMC', + 'version': 'qD5apdNjxRv3dBblf27nEZYf7r_pbLEgfN7hWyXvP_UC', }, ], 'condition': 'checkout_android and non_git_source', @@ -2808,13 +2837,13 @@ deps = { }, 'src/third_party/ruy/src': - Var('chromium_git') + '/external/github.com/google/ruy.git' + '@' + '83fd40d730feb0804fafbc2d8814bcc19a17b2e5', + Var('chromium_git') + '/external/github.com/google/ruy.git' + '@' + '9940fbf1e0c0863907e77e0600b99bb3e2bc2b9f', 'src/third_party/search_engines_data/resources': - Var('chromium_git') + '/external/search_engines_data.git' + '@' + '273082bef7b1bc05eddb5079b83702938e40c677', + Var('chromium_git') + '/external/search_engines_data.git' + '@' + '5c5db51f8c13cb42379d8b333890971f1a1a1797', 'src/third_party/search_engines_data/resources_internal': { - 'url': Var('chrome_git') + '/external/search_engines_data_internal.git' + '@' + 'cc57055d268edc933691dccb2139d0ced064a6c2', + 'url': Var('chrome_git') + '/external/search_engines_data_internal.git' + '@' + '755c49d2ec005159a2f413f4cd5cda0598bcb555', 'condition': 'checkout_src_internal', }, @@ -2899,34 +2928,32 @@ 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' + '@' + 'e6c5574b82d7950f978447704a70971c478f0f50', + Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + 'fe38b1b8c23d86ed93c13ef367b19496e398462d', 'src/third_party/turbine/cipd': { 'packages': [ { 'package': 'chromium/third_party/turbine', - 'version': 'oD9ecDiZFUZfazjjD0N5yl6G4aJsgODDdNjqIp5m1GwC', + 'version': 'TkTaFqF4Bs-JmFtxFV_Nfh4u5jh_401ZQsLhC7vIEqQC', }, ], 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@f227ce323fb5a2fee1a98b6feea54b0e42b2f30d', - 'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@d176fb41992d5c091fb1c401e4e70306382e67fc', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@c466059b72815c7fbce8bb3ab4832407aabc5dc5', + 'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@38f6708b6b6f213010c51ffa8f577a7751e12ce7', '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@2a611a970fdbc41ac2e3e328802aed9985352dca', - 'src/third_party/spirv-tools/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@33e02568181e3312f49a3cf33df470bf96ef293a', - 'src/third_party/vulkan-headers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Headers@10739e8e00a7b6f74d22dd0a547f1406ff1f5eb9', - 'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@342da33fdec78d269657194c9082835d647d2e68', - 'src/third_party/vulkan-tools/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@e3fc64396755191b3c51e5c57d0454872e7fa487', - 'src/third_party/vulkan-utility-libraries/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@72665ee1e50db3d949080df8d727dffa8067f5f8', - 'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@e086a717059f54c94d090998628250ae8f238fd6', + 'src/third_party/spirv-headers/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@97e96f9e9defeb4bba3cfbd034dec516671dd7a3', + 'src/third_party/spirv-tools/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@3aeaaa088d37b86cff036eee1a9bf452abad7d9d', + 'src/third_party/vulkan-headers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Headers@a01329f307fa6067da824de9f587f292d761680b', + 'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@f2389e27734347c1d9f40e03be53f69f969976b1', + 'src/third_party/vulkan-tools/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@f766b30b2de3ffe2cf6b656d943720882617ec58', + 'src/third_party/vulkan-utility-libraries/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@b0a40d2e50310e9f84327061290a390a061125a3', + 'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@6b1b8e3d259241a68c0944ca0a7bb5320d086191', 'src/third_party/vulkan_memory_allocator': - Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + '56300b29fbfcc693ee6609ddad3fdd5b7a449a21', - - 'src/third_party/wasm_tts_engine/src': Var('chromium_git') + '/chromium/wasm-tts-engine' + '@' + '352880bb49e2410707543c252ef6b94a21b0f47f', + Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'cb0597213b0fcb999caa9ed08c2f88dc45eb7d50', # Display server protocol for Linux. 'src/third_party/wayland/src': { @@ -2936,7 +2963,7 @@ deps = { # Wayland protocols that add functionality not available in the core protocol. 'src/third_party/wayland-protocols/src': { - 'url': Var('chromium_git') + '/external/anongit.freedesktop.org/git/wayland/wayland-protocols.git' + '@' + '7d5a3a8b494ae44cd9651f9505e88a250082765e', + 'url': Var('chromium_git') + '/external/anongit.freedesktop.org/git/wayland/wayland-protocols.git' + '@' + 'efbc060534be948b63e1f395d69b583eebba3235', 'condition': 'checkout_linux', }, @@ -2960,13 +2987,13 @@ deps = { Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'c01b768bce4a143e152c1870b6ba99ea6267d2b0', 'src/third_party/webgpu-cts/src': - Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '2a8d4a83f751286302ce34573409ad75cc318508', + Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '07f4412e935c988d60fad2e373287d6450bcd231', 'src/third_party/webpagereplay': Var('chromium_git') + '/webpagereplay.git' + '@' + Var('webpagereplay_revision'), 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '23d8e44f84822170bee4425760b44237959423e5', + Var('webrtc_git') + '/src.git' + '@' + '36ea4535a500ac137dbf1f577ce40dc1aaa774ef', # 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. @@ -2990,7 +3017,7 @@ deps = { }, 'src/third_party/xnnpack/src': - Var('chromium_git') + '/external/github.com/google/XNNPACK.git' + '@' + '3c99186b3276aa891f94ebba35f6b16e627d57de', + Var('chromium_git') + '/external/github.com/google/XNNPACK.git' + '@' + 'ae40b1a2d93d5c516bc7657c6c3eea1470f917ae', 'src/third_party/libei/cipd': { @@ -3012,7 +3039,7 @@ deps = { 'packages': [ { 'package': 'skia/tools/goldctl/linux-amd64', - 'version': 'DuaWI_iN1aKYqw68BNRC2gsLbwarydFdh-0pBp8HS6UC', + 'version': 'UePaQAmB4znC2DdGIm_DqUAEKytlOUofw0oMO0VhStcC', }, ], 'dep_type': 'cipd', @@ -3022,7 +3049,7 @@ deps = { 'packages': [ { 'package': 'skia/tools/goldctl/windows-amd64', - 'version': '2KZkcCD9mC9MsaKQTOIECvyDm_gtn0YaOjpfdhXw9wcC', + 'version': 'Y69lYD2QQGCN58_A0A21UHInQVZU2kWqKStG-ls-4NkC', }, ], 'dep_type': 'cipd', @@ -3033,7 +3060,7 @@ deps = { 'packages': [ { 'package': 'skia/tools/goldctl/mac-amd64', - 'version': 'kfSAMIADvMhxx5OoeY0EajZqqvBTlkVsrDEiWApdnsMC', + 'version': 'RVm2d4iM3iQFkXafgLvvzi3KHIq_qhFWz3dNRFhamowC', }, ], 'dep_type': 'cipd', @@ -3044,7 +3071,7 @@ deps = { 'packages': [ { 'package': 'skia/tools/goldctl/mac-arm64', - 'version': 'TMdajugFqfAjHrtZbG5sFxtFgsHk5GeyYgO7Exhlx20C', + 'version': 'X4Xi1f4spVZ7l32U7eqx8LghvrWxh_NLSkTB_hqW3s4C', }, ], 'dep_type': 'cipd', @@ -3077,7 +3104,7 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/apps/eche_app/app', - 'version': 'UgKA0HNsj2ADAOb8F95SERt5rcJdyYXePvIV5ycV5_cC', + 'version': 'l3lxv3u6Ygb9O_8_rfz7yuJwBZ64trjGFMzyXIuNl6sC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -3088,7 +3115,7 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/apps/boca_app/app', - 'version': '2C2_QHqh5RgEqN162CQfR0FmIGF0MANKrcR9W4CWxv4C', + 'version': 'xgl9jD_VmFlx7HFsx-IJAklV9b1882ggreXnX68nO8UC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -3099,7 +3126,7 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': '6RE1LMc8lBy8XK6vNbGHCsuib6l1_5o_R3lh-NyO3s0C', + 'version': '7oDf3Vb5wiSo2ExFDfRhzhQl3wy6NovGkb4sDhyL6SEC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -3110,7 +3137,7 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 'jgUYZwoBLwTTXABtFfNVSniwUlmnn4ue-oKLXzkmxFwC', + 'version': 'FZZmilEd8YefiVLFtQBMp6iQXZ02wJlgbb-z_9YLoDwC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -3143,7 +3170,7 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/apps/projector_app/app', - 'version': 'AbrE_oILb_zjITzM-b71AVUd4sYJZCam8HpaxgVNMj8C', + 'version': '9D7jzzfEqOgiQNDU6Y_WiKzlO4Upjb94bUfDQ6Kjje0C', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -3170,7 +3197,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/autorolled', - 'version': 'A3dJOufp8dbBYcfXrWzJNEzSO4qpqACgdZsVLdeWym8C', + 'version': 'RcN7kx5OuQtBLrhCRBTO9NABzT2sjw-ogJBZmT3nOdAC', }, ], 'condition': 'checkout_android and non_git_source', @@ -3234,616 +3261,11 @@ deps = { 'dep_type': 'cipd', }, - '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@4.0.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - 'src/third_party/android_deps/cipd/libs/com_google_android_datatransport_transport_backend_cct': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_datatransport_transport_backend_cct', - 'version': 'version:2@4.0.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - 'src/third_party/android_deps/cipd/libs/com_google_android_datatransport_transport_runtime': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_datatransport_transport_runtime', - 'version': 'version:2@4.0.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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@21.3.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.1.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.1.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_auth_blockstore': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_auth_blockstore', - 'version': 'version:2@16.4.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.5.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.5.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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@22.0.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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@22.0.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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 and non_git_source', - 'dep_type': 'cipd', - }, - - '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@17.2.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_fido': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_fido', - 'version': 'version:2@21.1.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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@18.1.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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 and non_git_source', - 'dep_type': 'cipd', - }, - - 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_identity_credentials': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_identity_credentials', - 'version': 'version:2@16.0.0-alpha05.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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 and non_git_source', - 'dep_type': 'cipd', - }, - - '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.1.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.3.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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 and non_git_source', - 'dep_type': 'cipd', - }, - - '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.1.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.2.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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 and non_git_source', - 'dep_type': 'cipd', - }, - - '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 and non_git_source', - 'dep_type': 'cipd', - }, - - 'src/third_party/android_deps/cipd/libs/com_google_android_libraries_identity_googleid_googleid': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_android_libraries_identity_googleid_googleid', - 'version': 'version:2@1.1.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.13.0-alpha05.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.3.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.1.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - 'src/third_party/android_deps/cipd/libs/com_google_ar_impress': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_ar_impress', - 'version': 'version:2@0.0.2.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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 and non_git_source', - 'dep_type': 'cipd', - }, - - '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.11.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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 and non_git_source', - 'dep_type': 'cipd', - }, - - '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.8.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.52.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.30.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.2.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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@21.0.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - 'src/third_party/android_deps/cipd/libs/com_google_firebase_firebase_common_ktx': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_common_ktx', - 'version': 'version:2@21.0.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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@18.0.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - 'src/third_party/android_deps/cipd/libs/com_google_firebase_firebase_datatransport': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_datatransport', - 'version': 'version:2@19.0.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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@17.0.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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@18.0.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - 'src/third_party/android_deps/cipd/libs/com_google_firebase_firebase_encoders_proto': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_encoders_proto', - 'version': 'version:2@16.0.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.1.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.1.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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@17.2.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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@17.1.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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@20.0.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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@24.1.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.2.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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@33.3.1-jre.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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@33.3.1-android.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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@3.0.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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@4.28.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - 'src/third_party/android_deps/cipd/libs/com_google_testparameterinjector_test_parameter_injector': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/com_google_testparameterinjector_test_parameter_injector', - 'version': 'version:2@1.18.cr1', + 'version': 'version:2@0.0.3.cr1', }, ], 'condition': 'checkout_android and non_git_source', @@ -3872,83 +3294,6 @@ deps = { 'dep_type': 'cipd', }, - '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 and non_git_source', - 'dep_type': 'cipd', - }, - - '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 and non_git_source', - 'dep_type': 'cipd', - }, - - '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.9.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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@5.2.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - 'src/third_party/android_deps/cipd/libs/jakarta_inject_jakarta_inject_api': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api', - 'version': 'version:2@2.0.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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 and non_git_source', - 'dep_type': 'cipd', - }, - - '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 and non_git_source', - 'dep_type': 'cipd', - }, - 'src/third_party/android_deps/cipd/libs/net_bytebuddy_byte_buddy': { 'packages': [ { @@ -3971,17 +3316,6 @@ deps = { 'dep_type': 'cipd', }, - '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.78.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - 'src/third_party/android_deps/cipd/libs/org_ccil_cowan_tagsoup_tagsoup': { 'packages': [ { @@ -4004,50 +3338,6 @@ deps = { 'dep_type': 'cipd', }, - '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.43.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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 and non_git_source', - 'dep_type': 'cipd', - }, - - '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.17.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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 and non_git_source', - 'dep_type': 'cipd', - }, - 'src/third_party/android_deps/cipd/libs/org_jetbrains_kotlin_kotlin_android_extensions_runtime': { 'packages': [ { @@ -4081,28 +3371,6 @@ deps = { 'dep_type': 'cipd', }, - '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.8.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.10.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - 'src/third_party/android_deps/cipd/libs/org_jetbrains_kotlinx_kotlinx_coroutines_guava': { 'packages': [ { @@ -4114,39 +3382,6 @@ deps = { 'dep_type': 'cipd', }, - 'src/third_party/android_deps/cipd/libs/org_jetbrains_kotlinx_kotlinx_coroutines_play_services': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_play_services', - 'version': 'version:2@1.10.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - 'src/third_party/android_deps/cipd/libs/org_jetbrains_kotlinx_kotlinx_coroutines_test_jvm': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_test_jvm', - 'version': 'version:2@1.7.3.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - 'src/third_party/android_deps/cipd/libs/org_jetbrains_kotlinx_kotlinx_serialization_core_jvm': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_serialization_core_jvm', - 'version': 'version:2@1.7.2.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - 'src/third_party/android_deps/cipd/libs/org_jsoup_jsoup': { 'packages': [ { @@ -4158,17 +3393,6 @@ deps = { 'dep_type': 'cipd', }, - 'src/third_party/android_deps/cipd/libs/org_jspecify_jspecify': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_jspecify_jspecify', - 'version': 'version:2@1.0.0.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - 'src/third_party/android_deps/cipd/libs/org_mockito_mockito_android': { 'packages': [ { @@ -4213,215 +3437,6 @@ deps = { 'dep_type': 'cipd', }, - '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.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.14.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.14.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.14.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.16.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.14.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.14.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.14.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.14.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.14.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.14.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.14.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.14.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - '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.14.1.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - - 'src/third_party/android_deps/cipd/libs/org_yaml_snakeyaml': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/org_yaml_snakeyaml', - 'version': 'version:2@2.3.cr1', - }, - ], - 'condition': 'checkout_android and non_git_source', - 'dep_type': 'cipd', - }, - # === ANDROID_DEPS Generated Code End === 'src/tools/resultdb': { @@ -4438,7 +3453,7 @@ deps = { # Dependencies from src_internal 'src/chromeos/ash/resources/internal': { 'url': Var('chrome_git') + '/chrome/chromeos/ash/resources/internal.git' + '@' + - '79861294509d9038645cd39ca828edd93abaf37b', + 'b54bffc92a255946aa52795ae9b0f6858ebe5a47', 'condition': 'checkout_src_internal and checkout_chromeos', }, @@ -4472,19 +3487,19 @@ deps = { 'src/chrome/app/theme/default_100_percent/google_chrome': { 'url': Var('chrome_git') + '/chrome/theme/default_100_percent/google_chrome.git' + '@' + - 'ad19f22e72e15777d7b631683fd0e1241ac18f15', + 'e080feee1bd6b3ac5ccff65059ac093f7d46ad08', 'condition': 'checkout_src_internal', }, 'src/chrome/app/theme/default_200_percent/google_chrome': { 'url': Var('chrome_git') + '/chrome/theme/default_200_percent/google_chrome.git' + '@' + - 'a5391ccb5ac297551c1a7cd82ec66bb4d8887502', + '252c8851666cf517fa400ef87ff00d02eae3ee49', 'condition': 'checkout_src_internal', }, 'src/chrome/app/theme/google_chrome': { 'url': Var('chrome_git') + '/chrome/theme/google_chrome.git' + '@' + - '88a6504d9c1073afc1919ad1a929e63f8715e186', + '8ff03bae520c6e903303c736c4c92ed807ce746c', 'condition': 'checkout_src_internal', }, @@ -4496,13 +3511,13 @@ deps = { 'src/chrome/browser/glic/resources/internal': { 'url': Var('chrome_git') + '/chrome/browser/glic/resources/internal.git' + '@' + - '304dea378929869bb5d29dccc19febf41542a9f5', + '4bb714b15246ed0def1ab198f746637a926507ab', 'condition': 'checkout_src_internal', }, 'src/chrome/browser/glic/e2e_test/internal': { 'url': Var('chrome_git') + '/chrome/browser/glic/test/internal.git' + '@' + - '851d0f7cbbe4e97a8edc5b139756b305f509e43f', + 'f27c9a46ebb7c3a2e484de830a1094c033e4a781', 'condition': 'checkout_glic_e2e_tests', }, @@ -4526,13 +3541,13 @@ deps = { 'src/chrome/browser/nearby_sharing/internal': { 'url': Var('chrome_git') + '/chrome/browser/nearby_sharing/internal.git' + '@' + - 'd46f4456f93aa8d7cd84161ce9fa4663b8068c49', + '9b327befebb061148d36539b0ec17915dbb70f1d', 'condition': 'checkout_src_internal', }, 'src/chrome/browser/platform_experience/win': { 'url': Var('chrome_git') + '/chrome/browser/platform_experience/win.git' + '@' + - '1d09642924d28d2596cbe9a48ae590fc45ae624f', + 'e913d6144929b67b0123235efc020a1bb138c8ae', 'condition': 'checkout_src_internal', }, @@ -4548,6 +3563,12 @@ deps = { 'condition': 'checkout_src_internal', }, + 'src/chrome/browser/resources/webui_browser/internal': { + 'url': Var('chrome_git') + '/chrome/browser/resources/webui_browser/internal.git' + '@' + + '54ba496f51ce3792b7ef8161558985b192ac078b', + 'condition': 'checkout_src_internal', + }, + 'src/chrome/browser/spellchecker/internal': { 'url': Var('chrome_git') + '/chrome/spellchecker/internal.git' + '@' + 'a22002a5b3cf7c6b872b25712af97a5664a350e2', # from svn revision 24388 @@ -4565,17 +3586,6 @@ deps = { 'dep_type': 'cipd', }, - 'src/chrome/browser/resources/chromeos/seal/resources': { - 'packages' : [ - { - 'package': 'chromeos_internal/inputs/seal', - 'version': '11AdGL1RBEo2LflLT5Vc8Q3vBfjsHQAuH5jAhUBxL9QC' - } - ], - 'condition': 'checkout_chromeos and checkout_src_internal', - 'dep_type': 'cipd', - }, - 'src/chrome/common/request_header_integrity/internal': { 'url': Var('chrome_git') + '/chrome/browser/request_header_integrity/internal.git' + '@' + '1592aa7ba598a048f918f54735bcf056556532c3', @@ -4592,7 +3602,7 @@ deps = { # grepping. 'src/chrome/installer/mac/internal': { 'url': Var('chrome_git') + '/chrome/installer/mac/internal.git' + '@' + - '30e560343a03842393c5913997ba1de268bf83ef', + '4fe3a76d806edba77d8a7ad2eefbcd37aab5192d', 'condition': 'checkout_src_internal', }, @@ -4663,7 +3673,7 @@ deps = { 'src/components/autofill/core/browser/form_parsing/internal_resources': { 'url': Var('chrome_git') + '/chrome/components/autofill_regex_patterns.git' + '@' + - '103ef5ee6ebd7611908d3685faf5dc42d79b569d', + 'ed7f0491fbc53c40b38ce100a091e278161091af', 'condition': 'checkout_src_internal', }, @@ -4674,7 +3684,7 @@ deps = { 'src/components/metrics/internal': { 'url': Var('chrome_git') + '/chrome/components/metrics/internal.git' + '@' + - 'd74edd43ad58d28a67278699f6756e2482aa6cc1', + '6c5b0a009ec24624e40e58045cc107d1c47672c6', 'condition': 'checkout_src_internal', }, @@ -4686,7 +3696,7 @@ deps = { 'src/components/optimization_guide/internal': { 'url': Var('chrome_git') + '/chrome/components/optimization_guide.git' + '@' + - '4b39877398214042ef0e0bf31426ba3bcc51162c', + '64b5a77344ec61457e9cceb839bf321b15f62ae1', 'condition': 'checkout_src_internal', }, @@ -4698,19 +3708,19 @@ deps = { 'src/components/resources/default_100_percent/google_chrome': { 'url': Var('chrome_git') + '/chrome/components/default_100_percent/google_chrome.git' + '@' + - '4d5ab89719e23b96a1468e87c27e98f07daeb478', + '4dabaf9b4a44b5119cbd0faf57fa9817b490c1a7', 'condition': 'checkout_src_internal', }, 'src/components/resources/default_200_percent/google_chrome': { 'url': Var('chrome_git') + '/chrome/components/default_200_percent/google_chrome.git' + '@' + - '389fe308d5b5ee7a306726f258169b963797af7e', + '5cd384925e31476b42b7c547ec1abde0153da4b3', 'condition': 'checkout_src_internal', }, 'src/components/resources/default_300_percent/google_chrome': { 'url': Var('chrome_git') + '/chrome/components/default_300_percent/google_chrome.git' + '@' + - 'a047858983ced9b274ccf3a85597774c5b7e041e', + '0ec8b9207d4a8df4d1475ba75b6ea10a39c730d6', 'condition': 'checkout_src_internal', }, @@ -4722,7 +3732,7 @@ deps = { 'src/components/test/data/autofill/heuristics-json/internal': { 'url': Var('chrome_git') + '/chrome/test/autofill/structured_forms.git' + '@' + - 'adc0282015eb4a9fa58b09adb2e1dcd75a522b7f', + '58d69fdc487903ff0e57a56bd3bbdffd37e6f658', 'condition': 'checkout_chromium_autofill_test_dependencies', }, @@ -4752,7 +3762,7 @@ deps = { 'src/ios_internal': { 'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' + - 'b99b1a6e42f75e6e1adef8e9e5f74bd59852f258', + 'e9c94631ae7b5f50ff1d7ef43a40778f0f34f322', 'condition': 'checkout_ios and checkout_src_internal', }, @@ -4764,7 +3774,7 @@ deps = { 'src/remoting/internal': { 'url': Var('chrome_git') + '/chrome/remoting/internal.git' + '@' + - 'e2527eef826745f968d1e26247d7ba5d5b289012', + '163d23002136b8aac8a46ea4045f0f9c41058c87', 'condition': 'checkout_src_internal', }, @@ -4780,15 +3790,21 @@ deps = { 'condition': 'checkout_src_internal', }, + 'src/services/shape_detection/internal': { + 'url': Var('chrome_git') + '/chrome/services/shape_detection.git' + '@' + + 'b048cee6b7831af7bca5d25a74419f59a29f691f', + 'condition': 'checkout_src_internal', + }, + 'src/signing_keys': { 'url': Var('chrome_git') + '/clank/apptestkey.git' + '@' + '5138e684915721cbccbb487ec0764ed05650fcd0', 'condition': 'checkout_android and checkout_google_internal and checkout_src_internal', }, - 'src/skia/tools/clusterfuzz-data':{ + 'src/clusterfuzz-data':{ 'url': Var('chrome_git') + '/chrome/tools/clusterfuzz-data.git' + '@' + - 'fa1fc4acacddd8d655cfca0bcadef5f7e2259bed', + Var('clusterfuzz_data_revision'), 'condition': 'checkout_clusterfuzz_data and checkout_src_internal', }, @@ -4923,7 +3939,7 @@ deps = { 'src/third_party/widevine/scripts': { 'url': Var('chrome_git') + '/chrome/deps/widevine/scripts.git' + '@' + - '6ae793a606aeed0d0f1c6f688117653710137744', + 'c96f53fde16f37b1a6cc2b6c468af3c4a364f426', 'condition': 'checkout_src_internal', }, @@ -4999,6 +4015,7 @@ include_rules = [ '+library_loaders', '+testing', + '+third_party/jni_zero', '+third_party/google_benchmark/src/include/benchmark/benchmark.h', '+third_party/icu/source/common/unicode', '+third_party/icu/source/i18n/unicode', @@ -5037,7 +4054,6 @@ include_rules = [ # checkdeps.py shouldn't check include paths for files in these dirs: skip_child_includes = [ - 'native_client_sdk', 'out', 'skia', 'testing', @@ -5639,6 +4655,17 @@ hooks = [ '--gs-url-base=chromium-optimization-profiles/pgo_profiles', ], }, + { + 'name': 'Fetch PGO profiles for android-desktop-x64', + 'pattern': '.', + 'condition': 'checkout_pgo_profiles and checkout_android', + 'action': [ 'python3', + 'src/tools/update_pgo_profiles.py', + '--target=android-desktop-x64', + 'update', + '--gs-url-base=chromium-optimization-profiles/pgo_profiles', + ], + }, { 'name': 'Fetch PGO profiles for V8 builtins', 'pattern': '.', diff --git a/naiveproxy/src/base/BUILD.gn b/naiveproxy/src/base/BUILD.gn index 3aecc99483..562ed812a4 100644 --- a/naiveproxy/src/base/BUILD.gn +++ b/naiveproxy/src/base/BUILD.gn @@ -208,6 +208,7 @@ component("base") { "bit_cast.h", "bits.h", "build_time.h", + "byte_count.h", "callback_list.cc", "callback_list.h", "cancelable_callback.h", @@ -415,6 +416,13 @@ component("base") { "memory/weak_ptr.h", "memory/writable_shared_memory_region.cc", "memory/writable_shared_memory_region.h", + "memory_coordinator/async_memory_consumer_registration.cc", + "memory_coordinator/async_memory_consumer_registration.h", + "memory_coordinator/memory_consumer.cc", + "memory_coordinator/memory_consumer.h", + "memory_coordinator/memory_consumer_registry.cc", + "memory_coordinator/memory_consumer_registry.h", + "memory_coordinator/traits.h", "message_loop/io_watcher.cc", "message_loop/io_watcher.h", "message_loop/message_pump.cc", @@ -1125,7 +1133,13 @@ component("base") { "android/build_info_stub.cc", "android/content_uri_utils.h", "android/content_uri_utils_stub.cc", + "android/virtual_document_path.cc", + "android/virtual_document_path.h", + "android/yield_to_looper_checker.cc", + "android/yield_to_looper_checker.h", "debug/stack_trace_android.cc", + "files/file_android.cc", + "files/file_android.h", "files/file_util_android.cc", "files/scoped_file_android.cc", "message_loop/message_pump_android.cc", @@ -1203,11 +1217,12 @@ component("base") { } if (is_robolectric) { sources += [ - "android/base_jni_onload.cc", - "android/base_jni_onload.h", + "android/base_jni_init.cc", + "android/base_jni_init.h", "android/callback_android.cc", "android/callback_android.h", "android/command_line_android.cc", + "android/command_line_android.h", "android/int_string_callback.cc", "android/int_string_callback.h", "android/java_exception_reporter.cc", @@ -1248,20 +1263,9 @@ component("base") { ] } if (is_android || is_robolectric) { - public_deps += [ "//third_party/jni_zero:jni_zero" ] + public_deps += [ "//third_party/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 += [ @@ -1598,6 +1602,8 @@ component("base") { "allocator/partition_alloc_features.h", "allocator/partition_alloc_support.cc", "allocator/partition_alloc_support.h", + "allocator/scheduler_loop_quarantine_config.cc", + "allocator/scheduler_loop_quarantine_config.h", ] } if (use_allocator_shim) { @@ -2080,10 +2086,16 @@ component("base") { ] } - # We include launch_mac on simulator builds so unittests can fork. But, - # platforms like tvOS continue to use launch_ios since they do not support - # multi-processes. - if (target_environment == "simulator" && target_platform == "iphoneos") { + # We include launch_mac on simulator builds so unit and browser tests can + # fork. + # iOS-based platforms like tvOS need special treatment in launch_mac.cc + # due to some symbols being marked unavailable despite being present, + # which is why this condition is restricted to specific `target_platform` + # values. + # In all cases, this is restricted to simulator builds because App Store + # restrictions forbid the use of multiple processes in applications. + if (target_environment == "simulator" && + (target_platform == "iphoneos" || target_platform == "tvos")) { sources += [ "process/kill_mac.cc", "process/launch_mac.cc", @@ -2216,6 +2228,11 @@ component("base") { # TODO(b/167763382) Find an alternate solution for Chromecast devices, since # adding the icui18n and icuuc deps significantly increases the binary size. + # This dependency was added to deal with Y2038 problem where time_t is + # represented via int32. However, Android builds specifically have time64 + # headers which allows representing time as int64, which makes this entire + # problem moot. Hence, why `!is_cronet_build` flag has been added. + # See crbug.com/431972096#comment10 for more information. if (false) { sources += [ "time/time_exploded_icu.cc" ] diff --git a/naiveproxy/src/base/allocator/OWNERS b/naiveproxy/src/base/allocator/OWNERS index d6c29b23c1..13917faf90 100644 --- a/naiveproxy/src/base/allocator/OWNERS +++ b/naiveproxy/src/base/allocator/OWNERS @@ -4,3 +4,4 @@ wfh@chromium.org per-file allocator.gni=file://base/allocator/partition_allocator/OWNERS per-file partition_alloc*=file://base/allocator/partition_allocator/OWNERS per-file BUILD.gn=file://base/allocator/partition_allocator/OWNERS +per-file scheduler_loop_quarantine_config*=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 59e41bda88..3c7aa03436 100644 --- a/naiveproxy/src/base/allocator/allocator_check.cc +++ b/naiveproxy/src/base/allocator/allocator_check.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "base/allocator/allocator_check.h" #include "build/build_config.h" diff --git a/naiveproxy/src/base/allocator/allocator_check.h b/naiveproxy/src/base/allocator/allocator_check.h index 58add8b9a6..ff93a3273f 100644 --- a/naiveproxy/src/base/allocator/allocator_check.h +++ b/naiveproxy/src/base/allocator/allocator_check.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef BASE_ALLOCATOR_ALLOCATOR_CHECK_H_ #define BASE_ALLOCATOR_ALLOCATOR_CHECK_H_ diff --git a/naiveproxy/src/base/allocator/dispatcher/configuration.h b/naiveproxy/src/base/allocator/dispatcher/configuration.h index 4488cf8045..5f892aa49e 100644 --- a/naiveproxy/src/base/allocator/dispatcher/configuration.h +++ b/naiveproxy/src/base/allocator/dispatcher/configuration.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef BASE_ALLOCATOR_DISPATCHER_CONFIGURATION_H_ #define BASE_ALLOCATOR_DISPATCHER_CONFIGURATION_H_ diff --git a/naiveproxy/src/base/allocator/dispatcher/dispatcher.cc b/naiveproxy/src/base/allocator/dispatcher/dispatcher.cc index f680f63cff..4b6c0b3057 100644 --- a/naiveproxy/src/base/allocator/dispatcher/dispatcher.cc +++ b/naiveproxy/src/base/allocator/dispatcher/dispatcher.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "base/allocator/dispatcher/dispatcher.h" #include "base/allocator/dispatcher/internal/dispatch_data.h" diff --git a/naiveproxy/src/base/allocator/dispatcher/dispatcher.h b/naiveproxy/src/base/allocator/dispatcher/dispatcher.h index ef46c79030..af25707bf6 100644 --- a/naiveproxy/src/base/allocator/dispatcher/dispatcher.h +++ b/naiveproxy/src/base/allocator/dispatcher/dispatcher.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef BASE_ALLOCATOR_DISPATCHER_DISPATCHER_H_ #define BASE_ALLOCATOR_DISPATCHER_DISPATCHER_H_ diff --git a/naiveproxy/src/base/allocator/dispatcher/initializer.h b/naiveproxy/src/base/allocator/dispatcher/initializer.h index a01646cd2a..744647eaa7 100644 --- a/naiveproxy/src/base/allocator/dispatcher/initializer.h +++ b/naiveproxy/src/base/allocator/dispatcher/initializer.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef BASE_ALLOCATOR_DISPATCHER_INITIALIZER_H_ #define BASE_ALLOCATOR_DISPATCHER_INITIALIZER_H_ diff --git a/naiveproxy/src/base/allocator/dispatcher/internal/dispatch_data.cc b/naiveproxy/src/base/allocator/dispatcher/internal/dispatch_data.cc index c27ca912de..ff2f602cdb 100644 --- a/naiveproxy/src/base/allocator/dispatcher/internal/dispatch_data.cc +++ b/naiveproxy/src/base/allocator/dispatcher/internal/dispatch_data.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "base/allocator/dispatcher/internal/dispatch_data.h" #include "partition_alloc/buildflags.h" diff --git a/naiveproxy/src/base/allocator/dispatcher/internal/dispatch_data.h b/naiveproxy/src/base/allocator/dispatcher/internal/dispatch_data.h index 9953111746..60a210afab 100644 --- a/naiveproxy/src/base/allocator/dispatcher/internal/dispatch_data.h +++ b/naiveproxy/src/base/allocator/dispatcher/internal/dispatch_data.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef BASE_ALLOCATOR_DISPATCHER_INTERNAL_DISPATCH_DATA_H_ #define BASE_ALLOCATOR_DISPATCHER_INTERNAL_DISPATCH_DATA_H_ diff --git a/naiveproxy/src/base/allocator/dispatcher/internal/dispatcher_internal.h b/naiveproxy/src/base/allocator/dispatcher/internal/dispatcher_internal.h index 0321b1282e..1ae112be9b 100644 --- a/naiveproxy/src/base/allocator/dispatcher/internal/dispatcher_internal.h +++ b/naiveproxy/src/base/allocator/dispatcher/internal/dispatcher_internal.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef BASE_ALLOCATOR_DISPATCHER_INTERNAL_DISPATCHER_INTERNAL_H_ #define BASE_ALLOCATOR_DISPATCHER_INTERNAL_DISPATCHER_INTERNAL_H_ diff --git a/naiveproxy/src/base/allocator/dispatcher/internal/tools.h b/naiveproxy/src/base/allocator/dispatcher/internal/tools.h index 692232ef44..3c81549d99 100644 --- a/naiveproxy/src/base/allocator/dispatcher/internal/tools.h +++ b/naiveproxy/src/base/allocator/dispatcher/internal/tools.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef BASE_ALLOCATOR_DISPATCHER_INTERNAL_TOOLS_H_ #define BASE_ALLOCATOR_DISPATCHER_INTERNAL_TOOLS_H_ diff --git a/naiveproxy/src/base/allocator/dispatcher/memory_tagging.cc b/naiveproxy/src/base/allocator/dispatcher/memory_tagging.cc index 33a6c0ec06..240ad101f4 100644 --- a/naiveproxy/src/base/allocator/dispatcher/memory_tagging.cc +++ b/naiveproxy/src/base/allocator/dispatcher/memory_tagging.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "base/allocator/dispatcher/memory_tagging.h" namespace base::allocator::dispatcher { diff --git a/naiveproxy/src/base/allocator/dispatcher/memory_tagging.h b/naiveproxy/src/base/allocator/dispatcher/memory_tagging.h index ef1cb68634..769b18573e 100644 --- a/naiveproxy/src/base/allocator/dispatcher/memory_tagging.h +++ b/naiveproxy/src/base/allocator/dispatcher/memory_tagging.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef BASE_ALLOCATOR_DISPATCHER_MEMORY_TAGGING_H_ #define BASE_ALLOCATOR_DISPATCHER_MEMORY_TAGGING_H_ diff --git a/naiveproxy/src/base/allocator/dispatcher/notification_data.h b/naiveproxy/src/base/allocator/dispatcher/notification_data.h index 8aa715ea91..8826536f69 100644 --- a/naiveproxy/src/base/allocator/dispatcher/notification_data.h +++ b/naiveproxy/src/base/allocator/dispatcher/notification_data.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef BASE_ALLOCATOR_DISPATCHER_NOTIFICATION_DATA_H_ #define BASE_ALLOCATOR_DISPATCHER_NOTIFICATION_DATA_H_ diff --git a/naiveproxy/src/base/allocator/dispatcher/reentry_guard.cc b/naiveproxy/src/base/allocator/dispatcher/reentry_guard.cc index 890bcbffc2..988161c7c7 100644 --- a/naiveproxy/src/base/allocator/dispatcher/reentry_guard.cc +++ b/naiveproxy/src/base/allocator/dispatcher/reentry_guard.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "base/allocator/dispatcher/reentry_guard.h" #include "base/check.h" diff --git a/naiveproxy/src/base/allocator/dispatcher/reentry_guard.h b/naiveproxy/src/base/allocator/dispatcher/reentry_guard.h index 61cbc60f7e..de686c841e 100644 --- a/naiveproxy/src/base/allocator/dispatcher/reentry_guard.h +++ b/naiveproxy/src/base/allocator/dispatcher/reentry_guard.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef BASE_ALLOCATOR_DISPATCHER_REENTRY_GUARD_H_ #define BASE_ALLOCATOR_DISPATCHER_REENTRY_GUARD_H_ diff --git a/naiveproxy/src/base/allocator/dispatcher/subsystem.h b/naiveproxy/src/base/allocator/dispatcher/subsystem.h index f9500bd67d..d404d4a650 100644 --- a/naiveproxy/src/base/allocator/dispatcher/subsystem.h +++ b/naiveproxy/src/base/allocator/dispatcher/subsystem.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef BASE_ALLOCATOR_DISPATCHER_SUBSYSTEM_H_ #define BASE_ALLOCATOR_DISPATCHER_SUBSYSTEM_H_ diff --git a/naiveproxy/src/base/allocator/dispatcher/testing/dispatcher_test.h b/naiveproxy/src/base/allocator/dispatcher/testing/dispatcher_test.h index 9cc232ef27..0e97d21d9b 100644 --- a/naiveproxy/src/base/allocator/dispatcher/testing/dispatcher_test.h +++ b/naiveproxy/src/base/allocator/dispatcher/testing/dispatcher_test.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef BASE_ALLOCATOR_DISPATCHER_TESTING_DISPATCHER_TEST_H_ #define BASE_ALLOCATOR_DISPATCHER_TESTING_DISPATCHER_TEST_H_ diff --git a/naiveproxy/src/base/allocator/dispatcher/testing/observer_mock.h b/naiveproxy/src/base/allocator/dispatcher/testing/observer_mock.h index a29ea7d58f..03fab35227 100644 --- a/naiveproxy/src/base/allocator/dispatcher/testing/observer_mock.h +++ b/naiveproxy/src/base/allocator/dispatcher/testing/observer_mock.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef BASE_ALLOCATOR_DISPATCHER_TESTING_OBSERVER_MOCK_H_ #define BASE_ALLOCATOR_DISPATCHER_TESTING_OBSERVER_MOCK_H_ diff --git a/naiveproxy/src/base/allocator/dispatcher/testing/tools.h b/naiveproxy/src/base/allocator/dispatcher/testing/tools.h index a9b5fbdfc5..a8dd86e124 100644 --- a/naiveproxy/src/base/allocator/dispatcher/testing/tools.h +++ b/naiveproxy/src/base/allocator/dispatcher/testing/tools.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef BASE_ALLOCATOR_DISPATCHER_TESTING_TOOLS_H_ #define BASE_ALLOCATOR_DISPATCHER_TESTING_TOOLS_H_ diff --git a/naiveproxy/src/base/allocator/dispatcher/tls.cc b/naiveproxy/src/base/allocator/dispatcher/tls.cc index 18cdcaf271..0086878d3d 100644 --- a/naiveproxy/src/base/allocator/dispatcher/tls.cc +++ b/naiveproxy/src/base/allocator/dispatcher/tls.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "base/allocator/dispatcher/tls.h" #include diff --git a/naiveproxy/src/base/allocator/dispatcher/tls.h b/naiveproxy/src/base/allocator/dispatcher/tls.h index 483d4c5edc..ce725aea19 100644 --- a/naiveproxy/src/base/allocator/dispatcher/tls.h +++ b/naiveproxy/src/base/allocator/dispatcher/tls.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef BASE_ALLOCATOR_DISPATCHER_TLS_H_ #define BASE_ALLOCATOR_DISPATCHER_TLS_H_ diff --git a/naiveproxy/src/base/allocator/early_zone_registration_apple.cc b/naiveproxy/src/base/allocator/early_zone_registration_apple.cc index 32a9a002c0..a2938d49bb 100644 --- a/naiveproxy/src/base/allocator/early_zone_registration_apple.cc +++ b/naiveproxy/src/base/allocator/early_zone_registration_apple.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "base/allocator/early_zone_registration_apple.h" #include diff --git a/naiveproxy/src/base/allocator/early_zone_registration_apple.h b/naiveproxy/src/base/allocator/early_zone_registration_apple.h index 272a8727af..cc884f8db8 100644 --- a/naiveproxy/src/base/allocator/early_zone_registration_apple.h +++ b/naiveproxy/src/base/allocator/early_zone_registration_apple.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef BASE_ALLOCATOR_EARLY_ZONE_REGISTRATION_APPLE_H_ #define BASE_ALLOCATOR_EARLY_ZONE_REGISTRATION_APPLE_H_ diff --git a/naiveproxy/src/base/allocator/miracle_parameter.cc b/naiveproxy/src/base/allocator/miracle_parameter.cc index 7b30a3031a..22ac9df20c 100644 --- a/naiveproxy/src/base/allocator/miracle_parameter.cc +++ b/naiveproxy/src/base/allocator/miracle_parameter.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "base/allocator/miracle_parameter.h" #include "base/command_line.h" diff --git a/naiveproxy/src/base/allocator/miracle_parameter.h b/naiveproxy/src/base/allocator/miracle_parameter.h index 7a5d23b33f..8a9d1f6820 100644 --- a/naiveproxy/src/base/allocator/miracle_parameter.h +++ b/naiveproxy/src/base/allocator/miracle_parameter.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef BASE_ALLOCATOR_MIRACLE_PARAMETER_H_ #define BASE_ALLOCATOR_MIRACLE_PARAMETER_H_ diff --git a/naiveproxy/src/base/allocator/partition_alloc_features.cc b/naiveproxy/src/base/allocator/partition_alloc_features.cc index 240c8266a3..c09a910f8f 100644 --- a/naiveproxy/src/base/allocator/partition_alloc_features.cc +++ b/naiveproxy/src/base/allocator/partition_alloc_features.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "base/allocator/partition_alloc_features.h" #include "base/allocator/miracle_parameter.h" @@ -29,11 +34,6 @@ static constexpr char kBrowserAndRendererStr[] = "browser-and-renderer"; static constexpr char kNonRendererStr[] = "non-renderer"; static constexpr char kAllProcessesStr[] = "all-processes"; -#if PA_CONFIG(ENABLE_SHADOW_METADATA) -static constexpr char kRendererOnlyStr[] = "renderer-only"; -static constexpr char kAllChildProcessesStr[] = "all-child-processes"; -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) - } // namespace BASE_FEATURE(kPartitionAllocUnretainedDanglingPtr, @@ -139,22 +139,12 @@ constinit const FeatureParam BASE_FEATURE(kPartitionAllocSchedulerLoopQuarantine, "PartitionAllocSchedulerLoopQuarantine", FEATURE_DISABLED_BY_DEFAULT); -// Scheduler Loop Quarantine's per-branch capacity in bytes. +// Scheduler Loop Quarantine's config. // Note: Do not use the prepared macro as of no need for a local cache. -constinit const FeatureParam - kPartitionAllocSchedulerLoopQuarantineBranchCapacity{ +constinit const FeatureParam + kPartitionAllocSchedulerLoopQuarantineConfig{ &kPartitionAllocSchedulerLoopQuarantine, - "PartitionAllocSchedulerLoopQuarantineBranchCapacity", 0}; -// Scheduler Loop Quarantine's capacity for the UI thread in bytes. -BASE_FEATURE_PARAM(int, - kPartitionAllocSchedulerLoopQuarantineBrowserUICapacity, - &kPartitionAllocSchedulerLoopQuarantine, - "PartitionAllocSchedulerLoopQuarantineBrowserUICapacity", - 0); - -BASE_FEATURE(kPartitionAllocZappingByFreeFlags, - "PartitionAllocZappingByFreeFlags", - FEATURE_DISABLED_BY_DEFAULT); + "PartitionAllocSchedulerLoopQuarantineConfig", "{}"}; BASE_FEATURE(kPartitionAllocEventuallyZeroFreedMemory, "PartitionAllocEventuallyZeroFreedMemory", @@ -486,29 +476,6 @@ BASE_FEATURE(kPartitionAllocAdjustSizeWhenInForeground, FEATURE_DISABLED_BY_DEFAULT); #endif -#if PA_CONFIG(ENABLE_SHADOW_METADATA) -BASE_FEATURE(kPartitionAllocShadowMetadata, - "PartitionAllocShadowMetadata", -#if BUILDFLAG(IS_LINUX) - FEATURE_ENABLED_BY_DEFAULT); -#else - FEATURE_DISABLED_BY_DEFAULT); -#endif - -constexpr FeatureParam::Option - kShadowMetadataEnabledProcessesOptions[] = { - {ShadowMetadataEnabledProcesses::kRendererOnly, kRendererOnlyStr}, - {ShadowMetadataEnabledProcesses::kAllChildProcesses, - kAllChildProcessesStr}}; - -// Note: Do not use the prepared macro as of no need for a local cache. -constinit const FeatureParam - kShadowMetadataEnabledProcessesParam{ - &kPartitionAllocShadowMetadata, kPAFeatureEnabledProcessesStr, - ShadowMetadataEnabledProcesses::kRendererOnly, - &kShadowMetadataEnabledProcessesOptions}; -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) - #if PA_BUILDFLAG(ENABLE_PARTITION_LOCK_PRIORITY_INHERITANCE) BASE_FEATURE(kPartitionAllocUsePriorityInheritanceLocks, "PartitionAllocUsePriorityInheritanceLocks", diff --git a/naiveproxy/src/base/allocator/partition_alloc_features.h b/naiveproxy/src/base/allocator/partition_alloc_features.h index 78930c5adc..8b4827daa4 100644 --- a/naiveproxy/src/base/allocator/partition_alloc_features.h +++ b/naiveproxy/src/base/allocator/partition_alloc_features.h @@ -2,9 +2,16 @@ // 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_ALLOCATOR_PARTITION_ALLOC_FEATURES_H_ #define BASE_ALLOCATOR_PARTITION_ALLOC_FEATURES_H_ +#include + #include "base/base_export.h" #include "base/compiler_specific.h" #include "base/feature_list.h" @@ -34,15 +41,6 @@ enum class PAFeatureEnabledProcesses { kAllProcesses, }; -enum class SchedulerLoopQuarantineBranchType { - // The global quarantine branch, shared across threads. - kGlobal, - // Default configuration for thread-local branches on new threads. - kThreadLocalDefault, - // Specialized configuration for the main thread of a process. - kMain, -}; - } // namespace internal BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocUnretainedDanglingPtr); @@ -98,17 +96,10 @@ BASE_EXPORT BASE_DECLARE_FEATURE_PARAM( PartitionAllocWithAdvancedChecksEnabledProcesses, kPartitionAllocWithAdvancedChecksEnabledProcessesParam); BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocSchedulerLoopQuarantine); -// Scheduler Loop Quarantine's per-thread capacity in bytes. +// See "base/allocator/scheduler_loop_quarantine_config.h" for details. BASE_EXPORT BASE_DECLARE_FEATURE_PARAM( - int, - kPartitionAllocSchedulerLoopQuarantineBranchCapacity); -// Scheduler Loop Quarantine's capacity for the UI thread in bytes. -// TODO(https://crbug.com/387470567): Support more thread types. -BASE_EXPORT BASE_DECLARE_FEATURE_PARAM( - int, - kPartitionAllocSchedulerLoopQuarantineBrowserUICapacity); - -BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocZappingByFreeFlags); + std::string, + kPartitionAllocSchedulerLoopQuarantineConfig); // Eventually zero out most PartitionAlloc memory. This is not meant as a // security guarantee, but to increase the compression ratio of PartitionAlloc's @@ -235,14 +226,6 @@ BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocAdjustSizeWhenInForeground); // See also: https://crbug.com/333443437 BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocUseSmallSingleSlotSpans); -#if PA_CONFIG(ENABLE_SHADOW_METADATA) -using ShadowMetadataEnabledProcesses = internal::PAFeatureEnabledProcesses; - -BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocShadowMetadata); -BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(ShadowMetadataEnabledProcesses, - kShadowMetadataEnabledProcessesParam); -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) - #if PA_BUILDFLAG(ENABLE_PARTITION_LOCK_PRIORITY_INHERITANCE) BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocUsePriorityInheritanceLocks); #endif // PA_BUILDFLAG(ENABLE_PARTITION_LOCK_PRIORITY_INHERITANCE) diff --git a/naiveproxy/src/base/allocator/partition_alloc_support.cc b/naiveproxy/src/base/allocator/partition_alloc_support.cc index 69ecefe396..c46748333d 100644 --- a/naiveproxy/src/base/allocator/partition_alloc_support.cc +++ b/naiveproxy/src/base/allocator/partition_alloc_support.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "base/allocator/partition_alloc_support.h" #include @@ -14,6 +19,7 @@ #include #include "base/allocator/partition_alloc_features.h" +#include "base/allocator/scheduler_loop_quarantine_config.h" #include "base/at_exit.h" #include "base/check.h" #include "base/containers/span.h" @@ -45,6 +51,7 @@ #include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "partition_alloc/allocation_guard.h" +#include "partition_alloc/allocator_config.h" #include "partition_alloc/buildflags.h" #include "partition_alloc/dangling_raw_ptr_checks.h" #include "partition_alloc/in_slot_metadata.h" @@ -141,17 +148,6 @@ void RunThreadCachePeriodicPurge() { } // namespace -// When enabled, disable the memory reclaimer in background. -BASE_FEATURE(kDisableMemoryReclaimerInBackground, - "DisableMemoryReclaimerInBackground", - base::FEATURE_ENABLED_BY_DEFAULT); - -// When enabled, limit the time memory reclaimer may take, returning early when -// exceeded. -BASE_FEATURE(kPartitionAllocShortMemoryReclaim, - "PartitionAllocShortMemoryReclaim", - base::FEATURE_ENABLED_BY_DEFAULT); - // static MemoryReclaimerSupport& MemoryReclaimerSupport::Instance() { static base::NoDestructor instance; @@ -209,16 +205,7 @@ void MemoryReclaimerSupport::Run() { TRACE_EVENT0("base", "partition_alloc::MemoryReclaimer::Reclaim()"); has_pending_task_ = false; - { - // Micros, since memory reclaiming should typically take at most a few ms. - SCOPED_UMA_HISTOGRAM_TIMER_MICROS("Memory.PartitionAlloc.MemoryReclaim"); - if (base::FeatureList::IsEnabled(kPartitionAllocShortMemoryReclaim)) { - ::partition_alloc::MemoryReclaimer::Instance()->ReclaimFast(); - } else { - ::partition_alloc::MemoryReclaimer::Instance()->ReclaimNormal(); - } - } - + ::partition_alloc::MemoryReclaimer::Instance()->ReclaimFast(); MaybeScheduleTask(); } @@ -234,10 +221,7 @@ TimeDelta MemoryReclaimerSupport::GetInterval() { } void MemoryReclaimerSupport::MaybeScheduleTask(TimeDelta delay) { - if (has_pending_task_ || - (base::FeatureList::IsEnabled(kDisableMemoryReclaimerInBackground) && - !in_foreground_) || - !task_runner_) { + if (has_pending_task_ || !in_foreground_ || !task_runner_) { return; } @@ -330,6 +314,23 @@ std::map ProposeSyntheticFinchTrials() { } #endif // PA_BUILDFLAG(HAS_MEMORY_TAGGING) +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) && \ + PA_BUILDFLAG(ENABLE_MOVE_METADATA_OUT_OF_GIGACAGE_TRIAL) + switch (partition_alloc::GetExternalMetadataTrialGroup()) { + case partition_alloc::ExternalMetadataTrialGroup::kEnabled: + trials.emplace(partition_alloc::kExternalMetadataTrialName, + partition_alloc::kExternalMetadataTrialGroup_Enabled); + break; + case partition_alloc::ExternalMetadataTrialGroup::kDisabled: + trials.emplace(partition_alloc::kExternalMetadataTrialName, + partition_alloc::kExternalMetadataTrialGroup_Disabled); + break; + default: + break; + } +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) && + // PA_BUILDFLAG(ENABLE_MOVE_METADATA_OUT_OF_GIGACAGE_TRIAL) + return trials; } @@ -354,17 +355,6 @@ bool ShouldEnableFeatureOnProcess( } } -#if PA_CONFIG(ENABLE_SHADOW_METADATA) -bool ShouldEnableShadowMetadata(const std::string& process_type) { - if (!base::FeatureList::IsEnabled( - base::features::kPartitionAllocShadowMetadata)) { - return false; - } - return ShouldEnableFeatureOnProcess( - features::kShadowMetadataEnabledProcessesParam.Get(), process_type); -} -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) - } // namespace #if PA_BUILDFLAG(ENABLE_DANGLING_RAW_PTR_CHECKS) @@ -837,7 +827,6 @@ bool PartitionAllocSupport::ShouldEnableMemoryTagging( return false; } - DCHECK(base::FeatureList::GetInstance()); if (base::FeatureList::IsEnabled( base::features::kKillPartitionAllocMemoryTagging)) { return false; @@ -851,53 +840,6 @@ bool PartitionAllocSupport::ShouldEnableMemoryTaggingInRendererProcess() { return ShouldEnableMemoryTagging(switches::kRendererProcess); } -// static -::partition_alloc::internal::SchedulerLoopQuarantineConfig -PartitionAllocSupport::GetSchedulerLoopQuarantineConfiguration( - const std::string& process_type, - features::internal::SchedulerLoopQuarantineBranchType branch_type) { - ::partition_alloc::internal::SchedulerLoopQuarantineConfig config; - -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) - if (!base::FeatureList::IsEnabled( - base::features::kPartitionAllocSchedulerLoopQuarantine)) { - return config; - } - - config.enable_quarantine = true; - config.branch_capacity_in_bytes = static_cast( - base::features::kPartitionAllocSchedulerLoopQuarantineBranchCapacity - .Get()); - config.enable_zapping = base::FeatureList::IsEnabled( - base::features::kPartitionAllocZappingByFreeFlags); - - switch (branch_type) { - case features::internal::SchedulerLoopQuarantineBranchType::kGlobal: - config.leak_on_destruction = true; - break; - case features::internal::SchedulerLoopQuarantineBranchType:: - kThreadLocalDefault: - config.leak_on_destruction = false; - break; - case features::internal::SchedulerLoopQuarantineBranchType::kMain: - config.leak_on_destruction = false; - if (process_type == "") { - config.branch_capacity_in_bytes = static_cast( - base::features:: - kPartitionAllocSchedulerLoopQuarantineBrowserUICapacity.Get()); - } - break; - } -#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) - - if (config.branch_capacity_in_bytes == 0) { - config.enable_quarantine = false; - config.enable_zapping = false; - } - - return config; -} - // static bool PartitionAllocSupport::ShouldEnablePartitionAllocWithAdvancedChecks( const std::string& process_type) { @@ -918,9 +860,6 @@ bool PartitionAllocSupport::ShouldEnablePartitionAllocWithAdvancedChecks( // static PartitionAllocSupport::BrpConfiguration PartitionAllocSupport::GetBrpConfiguration(const std::string& process_type) { - // TODO(bartekn): Switch to DCHECK once confirmed there are no issues. - CHECK(base::FeatureList::GetInstance()); - #if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \ PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) && \ !PA_BUILDFLAG(FORCE_DISABLE_BACKUP_REF_PTR_FEATURE) @@ -1024,7 +963,15 @@ void PartitionAllocSupport::ReconfigureAfterZygoteFork( void PartitionAllocSupport::ReconfigureAfterFeatureListInit( const std::string& process_type, - bool configure_dangling_pointer_detector) { + bool configure_dangling_pointer_detector, + bool is_in_death_test_child) { + // In Death Tests, `FeatureList` is never initialized. Even in these cases + // we call this method to finalize the allocator configuration. + // TODO(https://crbug.com/432019338): Remove this param once fixed. + if (!is_in_death_test_child) { + CHECK(base::FeatureList::GetInstance()); + } + if (configure_dangling_pointer_detector) { base::allocator::InstallDanglingRawPtrChecks(); } @@ -1106,12 +1053,10 @@ void PartitionAllocSupport::ReconfigureAfterFeatureListInit( const auto scheduler_loop_quarantine_global_config = GetSchedulerLoopQuarantineConfiguration( - process_type, - features::internal::SchedulerLoopQuarantineBranchType::kGlobal); + process_type, SchedulerLoopQuarantineBranchType::kGlobal); const auto scheduler_loop_quarantine_thread_local_config = GetSchedulerLoopQuarantineConfiguration( - process_type, features::internal::SchedulerLoopQuarantineBranchType:: - kThreadLocalDefault); + process_type, SchedulerLoopQuarantineBranchType::kThreadLocalDefault); const bool eventually_zero_freed_memory = base::FeatureList::IsEnabled( base::features::kPartitionAllocEventuallyZeroFreedMemory); @@ -1241,8 +1186,7 @@ void PartitionAllocSupport::ReconfigureAfterFeatureListInit( // `ReconfigureAfterTaskRunnerInit()` is called on the Main thread. partition_alloc::internal::SchedulerLoopQuarantineConfig quarantine_config = GetSchedulerLoopQuarantineConfiguration( - process_type, - features::internal::SchedulerLoopQuarantineBranchType::kMain); + process_type, SchedulerLoopQuarantineBranchType::kMain); allocator_shim::internal::PartitionAllocMalloc::Allocator() ->ReconfigureSchedulerLoopQuarantineForCurrentThread(quarantine_config); } @@ -1367,15 +1311,6 @@ void PartitionAllocSupport::ReconfigureAfterTaskRunnerInit( partition_alloc::PartitionRoot::SetSortActiveSlotSpansEnabled( base::FeatureList::IsEnabled( base::features::kPartitionAllocSortActiveSlotSpans)); - -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - if (ShouldEnableShadowMetadata(process_type)) { - partition_alloc::PartitionRoot::EnableShadowMetadata( - partition_alloc::internal::PoolHandleMask::kRegular | - partition_alloc::internal::PoolHandleMask::kBRP | - partition_alloc::internal::PoolHandleMask::kConfigurable); - } -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) } void PartitionAllocSupport::OnForegrounded(bool has_main_frame) { diff --git a/naiveproxy/src/base/allocator/partition_alloc_support.h b/naiveproxy/src/base/allocator/partition_alloc_support.h index 6ad4a3246a..81ad56f151 100644 --- a/naiveproxy/src/base/allocator/partition_alloc_support.h +++ b/naiveproxy/src/base/allocator/partition_alloc_support.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef BASE_ALLOCATOR_PARTITION_ALLOC_SUPPORT_H_ #define BASE_ALLOCATOR_PARTITION_ALLOC_SUPPORT_H_ @@ -86,7 +91,8 @@ class BASE_EXPORT PartitionAllocSupport { void ReconfigureAfterZygoteFork(const std::string& process_type); void ReconfigureAfterFeatureListInit( const std::string& process_type, - bool configure_dangling_pointer_detector = true); + bool configure_dangling_pointer_detector = true, + bool is_in_death_test_child = false); void ReconfigureAfterTaskRunnerInit(const std::string& process_type); // |has_main_frame| tells us if the renderer contains a main frame. @@ -116,12 +122,6 @@ class BASE_EXPORT PartitionAllocSupport { static bool ShouldEnablePartitionAllocWithAdvancedChecks( const std::string& process_type); - // Returns quarantine configuration for `process_name` and `branch_type`. - static ::partition_alloc::internal::SchedulerLoopQuarantineConfig - GetSchedulerLoopQuarantineConfiguration( - const std::string& process_type, - features::internal::SchedulerLoopQuarantineBranchType branch_type); - private: PartitionAllocSupport(); @@ -140,8 +140,6 @@ class BASE_EXPORT PartitionAllocSupport { #endif }; -BASE_EXPORT BASE_DECLARE_FEATURE(kDisableMemoryReclaimerInBackground); - // Visible in header for testing. class BASE_EXPORT MemoryReclaimerSupport { public: @@ -180,6 +178,7 @@ BASE_EXPORT void CheckHeapIntegrity(const void* ptr); // to the function, and it may use that for debugging purpose. BASE_EXPORT void SetDoubleFreeOrCorruptionDetectedFn(void (*fn)(uintptr_t)); +using partition_alloc::SchedulerLoopQuarantineScanPolicyUpdater; using partition_alloc::ScopedSchedulerLoopQuarantineExclusion; } // namespace base::allocator diff --git a/naiveproxy/src/base/allocator/partition_allocator/BUILD.gn b/naiveproxy/src/base/allocator/partition_allocator/BUILD.gn index 8e45674c06..22c177deb9 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/BUILD.gn +++ b/naiveproxy/src/base/allocator/partition_allocator/BUILD.gn @@ -13,7 +13,7 @@ group("buildflags") { if (use_partition_alloc && is_clang_or_gcc) { group("partition_alloc") { - public_deps = [ "src/partition_alloc:partition_alloc" ] + public_deps = [ "src/partition_alloc" ] } } diff --git a/naiveproxy/src/base/allocator/partition_allocator/gn/BUILDCONFIG.gn b/naiveproxy/src/base/allocator/partition_allocator/gn/BUILDCONFIG.gn index 13120e247b..93649ab54a 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/gn/BUILDCONFIG.gn +++ b/naiveproxy/src/base/allocator/partition_allocator/gn/BUILDCONFIG.gn @@ -10,6 +10,7 @@ build_with_chromium = false is_asan = false +is_hwasan = false # It's best to keep the names and defaults of is_foo flags consistent with: # - Chrome diff --git a/naiveproxy/src/base/allocator/partition_allocator/pa_check.md b/naiveproxy/src/base/allocator/partition_allocator/pa_check.md new file mode 100644 index 0000000000..ac62182498 --- /dev/null +++ b/naiveproxy/src/base/allocator/partition_allocator/pa_check.md @@ -0,0 +1,77 @@ +# PA_CHECK() + +PartitionAlloc is not re-entrant. This means that when a crash happens inside PartitionAllocator, PA_CHECK() is intended not to be symbolized, because memory allocation is required to symbolize addresses. Inside PartitionAllocator, it is not allowed to use the same PartitionRoot for another memory operation, e.g. malloc() and free(). If malloc() is replaced with PartitionAllocator and the malloc() hits PA_CHECK() failure, the symbolization will also use the same PartitionRoot for malloc() and will cause another crash or hang. + +## Symbolize unsymbolized addresses + +To symbolize addresses, we can use `//tools/valgrind/asan/asan_symbolizer.py`. However we should be careful about the order of addresses, because the addresses are not sorted, e.g. + +``` +#0 (module1.so + address1) +#2 (module1.so + address2) +#3 (module1.so + address3) +#1 (module2.so + address4) +``` + +PA_CHECK() makes addresses relative addresses inside each module, but it does the following on linux (or Android): + +- open /proc/self/maps. +- parse each line and get a module name and its address space. +- check whether the given addresses are in the address space or not. If in the address space, output the relative addresses with the module name. e.g. `base_unittests + 0x0023f8` + +To avoid memory allocation, the code does not remember module names with their address spaces. Instead, it outputs the relative addresses as soon as modules, which contain the addresses, are found. On the other hand, `asan_symbolize.py` doesn’t keep `#[0-9]+`. E.g. `asan_symbolize.py` generates the following: + +``` +#0 module1.cc:line_number1 +#1 module1.cc:line_number2 (was #2) +#2 module1.cc:line_number3 (was #3) +#3 module2.cc:line_number4 (was #1) +``` + +c.f. `//tools/valgrind/asan/third_party/asan_symbolize.py` sets `frame_no = 0` at `frameno_str == ‘0’` and increments `frame_no` by 1 + +If we want to symbolize the addresses manually, we can use `//third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer`. + +E.g. +``` +llvm-symbolizer -e module1.so -f -C -i address1 address2 address3 +``` + +If the module is very large, it takes much time to symbolize. It is better to provide multiple addresses for a symbolizer at once. + +Instead of `llvm-symbolizer`, `addr2line` also works for the symbolization. However `addr2line` is much slower than `llvm-symbolizer`. + +Regarding MacOS, we can use `atos` for symbolization. + +E.g. if we have: +``` +#0 (base_unittests+address1) +``` +we will try: +``` +atos -offset -inlineFrames -arch x86_64 -o base_unittests address1 +``` + +If we have a minidump (e.g. `base_unittests`'s `mindump.dmp`), lldb is also useful for symbolization. + +``` +lldb -c minidump.dmp -f base_unittests +(lldb) bt +``` + +## Symbolize unsymbolized addresses shown in cq or try-bots + +(googler-only) Regarding cq or tri, we can get binaries from `cas input`. We will open the “swarming task page” and follow the “Download inputs files into directory foo:” steps in the “Reproducing the task locally”. + +## PA_NOTREACHED hit + +Since PA_NOTREACHED() causes immediate crash and no stack frames are shown, the following makes it easier to debug PA_NOTREACHED(): + +`//base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/check.cc` +``` +void RawCheckFailure(const char* message) { + //RawLog(LOGGING_FATAL, message); + //PA_IMMEDIATE_CRASH(); + PA_CHECK(false) << message; +} +``` diff --git a/naiveproxy/src/base/allocator/partition_allocator/partition_alloc.gni b/naiveproxy/src/base/allocator/partition_allocator/partition_alloc.gni index 5f7e7155e5..4b758e7279 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/partition_alloc.gni +++ b/naiveproxy/src/base/allocator/partition_allocator/partition_alloc.gni @@ -343,11 +343,21 @@ declare_args() { } declare_args() { - # Shadow metadata is still under development and only supports Linux - # for now. - enable_shadow_metadata = is_linux && has_64_bit_pointers + # Because of address space issue, this feature cannot be enabled on + # 32bit OS and iOS, i.e. has_64_bit_pointers && !is_ios + move_metadata_outside_gigacage = false && has_64_bit_pointers && !is_ios } +declare_args() { + enable_move_metadata_outside_gigacage_trial = + false && move_metadata_outside_gigacage +} + +assert(!enable_move_metadata_outside_gigacage_trial || + move_metadata_outside_gigacage, + "Can't enable PartitionAllocExternalMetadata synthetic trial " + + "without move_metadata_outside_gigacage=true.") + declare_args() { # Use full MTE protection available by changing the feature flag default # values. So sync mode on all processes. Also disables permissive MTE. 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 13ffc912e3..df7b1d00a1 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 @@ -155,7 +155,8 @@ pa_buildflag_header("buildflags") { "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", + "MOVE_METADATA_OUT_OF_GIGACAGE_FOR_64_BITS_POINTERS=$move_metadata_outside_gigacage", + "ENABLE_MOVE_METADATA_OUT_OF_GIGACAGE_TRIAL=$enable_move_metadata_outside_gigacage_trial", "ENABLE_THREAD_ISOLATION=$enable_pkeys", "EXPENSIVE_DCHECKS_ARE_ON=$enable_expensive_dchecks", "FORCE_DISABLE_BACKUP_REF_PTR_FEATURE=$force_disable_backup_ref_ptr_feature", @@ -400,6 +401,8 @@ if (is_clang_or_gcc) { "address_space_stats.h", "allocation_guard.cc", "allocation_guard.h", + "allocator_config.cc", + "allocator_config.h", "bucket_lookup.h", "compressed_pointer.cc", "compressed_pointer.h", @@ -452,7 +455,6 @@ if (is_clang_or_gcc) { "partition_page_constants.h", "partition_root.cc", "partition_root.h", - "partition_shared_mutex.h", "partition_stats.cc", "partition_stats.h", "partition_superpage_extent_entry.h", @@ -545,7 +547,7 @@ if (is_clang_or_gcc) { if (use_partition_alloc_as_malloc_on_win_component_build) { # We need to add explicit libc++ dependency here because of # no_default_deps=true. - deps += [ "//buildtools/third_party/libc++:libc++" ] + deps += [ "//buildtools/third_party/libc++" ] } public_configs = [] @@ -587,8 +589,18 @@ if (is_clang_or_gcc) { if (enable_pkeys && partition_alloc_is_debug) { configs += [ ":no_stack_protector" ] - # -fno-stack-protector is incompatible with libc++ modules. - use_libcxx_modules = false + if (defined(is_debug) && is_debug) { + # Chromium debug build uses -fstack-protector for libc++ modules and the + # flag is not compatible with "no_stack_protector" config. + # + # Note that `is_debug`, `libcxx_modules` and `use_clang_modules` + # arguments are not part of partition_alloc. They are part of Chromium. + # They may be undefined or unused respectively. + use_libcxx_modules = false + if (!defined(use_clang_modules)) { + not_needed([ "use_libcxx_modules" ]) + } + } } } @@ -616,6 +628,7 @@ if (is_clang_or_gcc) { "partition_alloc_base/containers/flat_tree.h", "partition_alloc_base/cpu.cc", "partition_alloc_base/cpu.h", + "partition_alloc_base/cxx20_identity.h", "partition_alloc_base/cxx20_is_constant_evaluated.h", "partition_alloc_base/cxx_wrapper/algorithm.h", "partition_alloc_base/cxx_wrapper/optional.h", @@ -799,7 +812,7 @@ if (is_clang_or_gcc) { if (use_partition_alloc_as_malloc_on_win_component_build) { # We need to add explicit libc++ dependency here because of # no_default_deps=true. - deps += [ "//buildtools/third_party/libc++:libc++" ] + deps += [ "//buildtools/third_party/libc++" ] } if (is_fuchsia) { public_deps += [ "//third_party/fuchsia-sdk/sdk/pkg/fit" ] @@ -1061,8 +1074,18 @@ if (build_with_chromium) { # the test. configs += [ ":no_stack_protector" ] - # -fno-stack-protector is incompatible with libc++ modules. - use_libcxx_modules = false + if (defined(is_debug) && is_debug) { + # Chromium debug build uses -fstack-protector for libc++ modules and the + # flag is not compatible with "no_stack_protector" config. + # + # Note that `is_debug`, `libcxx_modules` and `use_clang_modules` + # arguments are not part of partition_alloc. They are part of Chromium. + # They may be undefined or unused respectively. + use_libcxx_modules = false + if (!defined(use_clang_modules)) { + not_needed([ "use_libcxx_modules" ]) + } + } } frameworks = [] @@ -1082,6 +1105,10 @@ if (build_with_chromium) { configs -= partition_alloc_remove_configs configs += partition_alloc_add_configs + + # TODO(crbug.com/40031409): Fix code that adds exit-time destructors and + # enable the diagnostic by removing this line. + configs += [ "//build/config/compiler:no_exit_time_destructors" ] } } 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 fdae122d4a..d7e107477f 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_AARCH64_SUPPORT_H_ #define PARTITION_ALLOC_AARCH64_SUPPORT_H_ 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 1d8245f31e..67a38cb8a3 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/address_pool_manager.h" #include 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 ebc5bf502c..05f9637779 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_ADDRESS_POOL_MANAGER_H_ #define PARTITION_ALLOC_ADDRESS_POOL_MANAGER_H_ 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 c0aedbcde9..268fd72b00 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/address_pool_manager_bitmap.h" #include "partition_alloc/buildflags.h" 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 8befb272e8..303963cbaf 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_ADDRESS_POOL_MANAGER_BITMAP_H_ #define PARTITION_ALLOC_ADDRESS_POOL_MANAGER_BITMAP_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager_types.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager_types.h index 4503c51230..05d0f63a4b 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager_types.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager_types.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_ADDRESS_POOL_MANAGER_TYPES_H_ #define PARTITION_ALLOC_ADDRESS_POOL_MANAGER_TYPES_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 a24b5523ee..6dfa9a1401 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/address_space_randomization.h" #include "partition_alloc/build_config.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 3059af1822..597bce14f2 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_ADDRESS_SPACE_RANDOMIZATION_H_ #define PARTITION_ALLOC_ADDRESS_SPACE_RANDOMIZATION_H_ 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 4fa4f82e3e..1da5989683 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_ADDRESS_SPACE_STATS_H_ #define PARTITION_ALLOC_ADDRESS_SPACE_STATS_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/allocation_guard.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/allocation_guard.cc index dda4730c8d..b28fd86b30 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/allocation_guard.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/allocation_guard.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/allocation_guard.h" #include "partition_alloc/partition_alloc_base/immediate_crash.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/allocation_guard.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/allocation_guard.h index 27bb76f76e..0c902589e2 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/allocation_guard.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/allocation_guard.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_ALLOCATION_GUARD_H_ #define PARTITION_ALLOC_ALLOCATION_GUARD_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/allocator_config.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/allocator_config.cc new file mode 100644 index 0000000000..ce5aafec9e --- /dev/null +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/allocator_config.cc @@ -0,0 +1,60 @@ +// Copyright 2025 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/allocator_config.h" + +#include + +#include "partition_alloc/random.h" + +namespace partition_alloc { + +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) && \ + PA_BUILDFLAG(ENABLE_MOVE_METADATA_OUT_OF_GIGACAGE_TRIAL) +namespace { + +enum ExternalMetadataTrialGroupPercentage { + kEnabled = 10, // 10% + kDisabled = 10, // 10% +}; + +ExternalMetadataTrialGroup s_externalMetadataJoinedGroup = + ExternalMetadataTrialGroup::kUndefined; + +void SetExternalMetadataTrialGroup(ExternalMetadataTrialGroup group) { + s_externalMetadataJoinedGroup = group; +} + +} // namespace + +namespace internal { + +ExternalMetadataTrialGroup SelectExternalMetadataTrialGroup() { + uint32_t random = internal::RandomValue() / + static_cast(std::numeric_limits::max()) * + 100.0; + + ExternalMetadataTrialGroup group; + if (random < ExternalMetadataTrialGroupPercentage::kEnabled) { + group = ExternalMetadataTrialGroup::kEnabled; + } else if (random < ExternalMetadataTrialGroupPercentage::kEnabled + + ExternalMetadataTrialGroupPercentage::kDisabled) { + group = ExternalMetadataTrialGroup::kDisabled; + } else { + group = ExternalMetadataTrialGroup::kDefault; + } + SetExternalMetadataTrialGroup(group); + return group; +} + +} // namespace internal + +ExternalMetadataTrialGroup GetExternalMetadataTrialGroup() { + return s_externalMetadataJoinedGroup; +} + +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) && + // PA_BUILDFLAG(ENABLE_MOVE_METADATA_OUT_OF_GIGACAGE_TRIAL) + +} // namespace partition_alloc diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/allocator_config.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/allocator_config.h new file mode 100644 index 0000000000..cf9e31f776 --- /dev/null +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/allocator_config.h @@ -0,0 +1,47 @@ +// Copyright 2025 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_ALLOCATOR_CONFIG_H_ +#define PARTITION_ALLOC_ALLOCATOR_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_config.h" + +namespace partition_alloc { + +// partition_alloc_support.cc will see the configuration and invoke +// RegisterSyntheticTrialGroup(). +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) && \ + PA_BUILDFLAG(ENABLE_MOVE_METADATA_OUT_OF_GIGACAGE_TRIAL) + +inline constexpr const char kExternalMetadataTrialName[] = + "PartitionAllocExternalMetadata"; +inline constexpr const char kExternalMetadataTrialGroup_Enabled[] = "Enabled"; +inline constexpr const char kExternalMetadataTrialGroup_Disabled[] = "Disabled"; + +// For synthetic field trial: PartitionAllocExternalMetadata +enum ExternalMetadataTrialGroup { + kUndefined = 0, + kDefault, + kDisabled, + kEnabled, +}; + +PA_COMPONENT_EXPORT(PARTITION_ALLOC) +ExternalMetadataTrialGroup GetExternalMetadataTrialGroup(); + +namespace internal { + +ExternalMetadataTrialGroup SelectExternalMetadataTrialGroup(); + +} // namespace internal + +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) && + // PA_BUILDFLAG(ENABLE_MOVE_METADATA_OUT_OF_GIGACAGE_TRIAL) + +} // namespace partition_alloc + +#endif // PARTITION_ALLOC_ALLOCATOR_CONFIG_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/arm_bti_test_functions.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/arm_bti_test_functions.h index ddfaa358a0..1472230ae5 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/arm_bti_test_functions.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/arm_bti_test_functions.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_ARM_BTI_TEST_FUNCTIONS_H_ #define PARTITION_ALLOC_ARM_BTI_TEST_FUNCTIONS_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/bucket_lookup.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/bucket_lookup.h index 671c58dfac..7f05e54cbc 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/bucket_lookup.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/bucket_lookup.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_BUCKET_LOOKUP_H_ #define PARTITION_ALLOC_BUCKET_LOOKUP_H_ 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 12f5648eb6..ff0580ea25 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 @@ -1,6 +1,11 @@ // 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. + +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif #ifndef PARTITION_ALLOC_BUILD_CONFIG_H_ #define PARTITION_ALLOC_BUILD_CONFIG_H_ @@ -17,7 +22,7 @@ // // Operating system: // IS_IOS / IS_AIX / IS_ASMJS / IS_FREEBSD / IS_FUCHSIA / IS_LINUX / IS_MAC / -// IS_NACL / IS_NETBSD / IS_OPENBSD / IS_QNX / IS_SOLARIS / IS_WIN +// IS_NETBSD / IS_OPENBSD / IS_QNX / IS_SOLARIS / IS_WIN // // Operating system family: // IS_APPLE / IS_BSD / IS_POSIX @@ -55,10 +60,7 @@ // IWYU pragma: always_keep // A set of macros to use for platform detection. -#if defined(__native_client__) -// __native_client__ must be first, so that other IS_ defines are not set. -#define PA_IS_NACL -#elif PA_BUILDFLAG(IS_ANDROID) +#if PA_BUILDFLAG(IS_ANDROID) // The IS_ANDROID PA_BUILDFLAG macro is defined in buildflags.h. // // PartitionAlloc's embedders (Chromium, Dawn, Pdfium, Skia) define different @@ -119,10 +121,10 @@ #define PA_IS_BSD #endif -#if defined(PA_IS_AIX) || defined(PA_IS_ASMJS) || defined(PA_IS_FREEBSD) || \ - defined(PA_IS_IOS) || defined(PA_IS_LINUX) || defined(PA_IS_CHROMEOS) || \ - defined(PA_IS_MAC) || defined(PA_IS_NACL) || defined(PA_IS_NETBSD) || \ - defined(PA_IS_OPENBSD) || defined(PA_IS_QNX) || defined(PA_IS_SOLARIS) || \ +#if defined(PA_IS_AIX) || defined(PA_IS_ASMJS) || defined(PA_IS_FREEBSD) || \ + defined(PA_IS_IOS) || defined(PA_IS_LINUX) || defined(PA_IS_CHROMEOS) || \ + defined(PA_IS_MAC) || defined(PA_IS_NETBSD) || defined(PA_IS_OPENBSD) || \ + defined(PA_IS_QNX) || defined(PA_IS_SOLARIS) || \ PA_BUILDFLAG(IS_ANDROID) || PA_BUILDFLAG(IS_CHROMEOS) #define PA_IS_POSIX #endif @@ -179,7 +181,7 @@ #define PA_ARCH_CPU_ARM64 #define PA_ARCH_CPU_64_BITS #define PA_ARCH_CPU_LITTLE_ENDIAN -#elif defined(__pnacl__) || defined(__asmjs__) || defined(__wasm__) +#elif defined(__asmjs__) || defined(__wasm__) #define PA_ARCH_CPU_32_BITS #define PA_ARCH_CPU_LITTLE_ENDIAN #elif defined(__MIPSEL__) @@ -449,13 +451,6 @@ #endif #undef PA_IS_MAC -#if defined(PA_IS_NACL) -#define PA_BUILDFLAG_INTERNAL_IS_NACL() (1) -#else -#define PA_BUILDFLAG_INTERNAL_IS_NACL() (0) -#endif -#undef PA_IS_NACL - #if defined(PA_IS_NETBSD) #define PA_BUILDFLAG_INTERNAL_IS_NETBSD() (1) #else diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/buildflag.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/buildflag.h index 6201d7bb44..30d6db6e40 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/buildflag.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/buildflag.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_BUILDFLAG_H_ #define PARTITION_ALLOC_BUILDFLAG_H_ 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 6a62a27c9b..263a2c5499 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/compressed_pointer.h" #include "partition_alloc/buildflags.h" 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 57d40ee42c..04d4c2ced4 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_COMPRESSED_POINTER_H_ #define PARTITION_ALLOC_COMPRESSED_POINTER_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/dangling_raw_ptr_checks.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/dangling_raw_ptr_checks.cc index b2d5632c9d..e0b21bedc1 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/dangling_raw_ptr_checks.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/dangling_raw_ptr_checks.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/dangling_raw_ptr_checks.h" #include "partition_alloc/partition_alloc_base/component_export.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/dangling_raw_ptr_checks.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/dangling_raw_ptr_checks.h index dfe31732bc..fa8ea3bcec 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/dangling_raw_ptr_checks.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/dangling_raw_ptr_checks.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_DANGLING_RAW_PTR_CHECKS_H_ #define PARTITION_ALLOC_DANGLING_RAW_PTR_CHECKS_H_ 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 92b8f4115b..7ccd24adc3 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_ENCODED_NEXT_FREELIST_H_ #define PARTITION_ALLOC_ENCODED_NEXT_FREELIST_H_ 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 61f08cda4d..9914e308cd 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/extended_api.h" #include "partition_alloc/buildflags.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 0b4be9a029..2b8b9de1b0 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_EXTENDED_API_H_ #define PARTITION_ALLOC_EXTENDED_API_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/flags.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/flags.h index 6f85c57c86..75e19090c9 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/flags.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/flags.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // This header provides a type-safe way of storing OR-combinations of enum // values. // 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 b85010098c..4c34510bed 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/gwp_asan_support.h" #if PA_BUILDFLAG(ENABLE_GWP_ASAN_SUPPORT) @@ -90,7 +95,7 @@ void* GwpAsanSupport::MapRegion(size_t slot_count, for (uintptr_t super_page = super_page_span_start; super_page < super_page_span_end; super_page += kSuperPageSize) { auto* page_metadata = - internal::PartitionSuperPageToMetadataArea(super_page); + internal::PartitionSuperPageToMetadataArea(super_page, root); // Index 0 is invalid because it is the super page extent metadata. for (size_t partition_page_idx = 1; @@ -99,10 +104,9 @@ void* GwpAsanSupport::MapRegion(size_t slot_count, partition_page_idx += bucket->get_pages_per_slot_span()) { auto* slot_span_metadata = &page_metadata[partition_page_idx].slot_span_metadata; - bucket->InitializeSlotSpanForGwpAsan(slot_span_metadata, root); - auto slot_span_start = - internal::SlotSpanMetadata:: - ToSlotSpanStart(slot_span_metadata); + bucket->InitializeSlotSpanForGwpAsan(slot_span_metadata); + auto slot_span_start = internal::SlotSpanMetadata::ToSlotSpanStart( + slot_span_metadata, root); for (uintptr_t slot_idx = 0; slot_idx < kSlotsPerSlotSpan; ++slot_idx) { auto slot_start = slot_span_start + slot_idx * kSlotSize; @@ -140,8 +144,7 @@ bool GwpAsanSupport::CanReuse(uintptr_t slot_start) { // static void GwpAsanSupport::DestructForTesting() { static PartitionRoot* root = RootInstance(); - internal::ScopedGuard locker{internal::PartitionRootLock(root)}; - root->DestructForTesting(); // IN-TEST + root->ResetForTesting(true); // IN-TEST } } // namespace partition_alloc 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 71ea678d5c..9b28390dae 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_GWP_ASAN_SUPPORT_H_ #define PARTITION_ALLOC_GWP_ASAN_SUPPORT_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/in_slot_metadata.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/in_slot_metadata.cc index 85dad663ad..f301496260 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/in_slot_metadata.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/in_slot_metadata.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/in_slot_metadata.h" #include @@ -23,7 +28,7 @@ namespace { // If double-free, the freed `slot` will be a freelist entry. bool IsInFreelist(uintptr_t slot_start, - SlotSpanMetadata* slot_span, + SlotSpanMetadata* slot_span, size_t& position) { size_t slot_size = slot_span->bucket->slot_size; @@ -98,10 +103,9 @@ PA_NOINLINE PA_NOT_TAIL_CALLED void CorruptionDetected() { [[noreturn]] #endif // !PA_BUILDFLAG(IS_IOS) PA_NOINLINE PA_NOT_TAIL_CALLED void -InSlotMetadata::DoubleFreeOrCorruptionDetected( - InSlotMetadata::CountType count, - uintptr_t slot_start, - SlotSpanMetadata* slot_span) { +InSlotMetadata::DoubleFreeOrCorruptionDetected(InSlotMetadata::CountType count, + uintptr_t slot_start, + SlotSpanMetadata* slot_span) { // Lock the PartitionRoot here, because to travserse SlotSpanMetadata's // freelist, we need PartitionRootLock(). PartitionRoot* root = PartitionRoot::FromSlotSpanMetadata(slot_span); 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 c9d446ec72..b97bbdefb9 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_IN_SLOT_METADATA_H_ #define PARTITION_ALLOC_IN_SLOT_METADATA_H_ @@ -243,9 +248,8 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) InSlotMetadata { // Returns true if the allocation should be reclaimed. // This function should be called by the allocator during Free(). - PA_ALWAYS_INLINE bool ReleaseFromAllocator( - uintptr_t slot_start, - SlotSpanMetadata* slot_span) { + PA_ALWAYS_INLINE bool ReleaseFromAllocator(uintptr_t slot_start, + SlotSpanMetadata* slot_span) { CheckCookieIfSupported(); CountType old_count = @@ -296,9 +300,8 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) InSlotMetadata { } // Assertion to allocation which ought to be alive. - PA_ALWAYS_INLINE void EnsureAlive( - uintptr_t slot_start, - SlotSpanMetadata* slot_span) { + PA_ALWAYS_INLINE void EnsureAlive(uintptr_t slot_start, + SlotSpanMetadata* slot_span) { CountType count = count_.load(std::memory_order_relaxed); if (!(count & kMemoryHeldByAllocatorBit)) { DoubleFreeOrCorruptionDetected(count, slot_start, slot_span); @@ -448,7 +451,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) InSlotMetadata { PA_NOINLINE PA_NOT_TAIL_CALLED static void DoubleFreeOrCorruptionDetected( CountType count, uintptr_t slot_start, - SlotSpanMetadata*); + SlotSpanMetadata*); // Note that in free slots, this is overwritten by encoded freelist // pointer(s). The way the pointers are encoded on 64-bit little-endian diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/internal_allocator.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/internal_allocator.cc index 65c5076773..a5ddd65416 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/internal_allocator.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/internal_allocator.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/internal_allocator.h" namespace partition_alloc::internal { 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 4e6ed30024..21e4929e5a 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_INTERNAL_ALLOCATOR_H_ #define PARTITION_ALLOC_INTERNAL_ALLOCATOR_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/internal_allocator_forward.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/internal_allocator_forward.h index 759668c1fa..77d415ff36 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/internal_allocator_forward.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/internal_allocator_forward.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_INTERNAL_ALLOCATOR_FORWARD_H_ #define PARTITION_ALLOC_INTERNAL_ALLOCATOR_FORWARD_H_ 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 a13f20b073..e13bee6e32 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/memory_reclaimer.h" #include "partition_alloc/buildflags.h" @@ -42,12 +47,6 @@ void MemoryReclaimer::ReclaimAll() { Reclaim(kFlags); } -void MemoryReclaimer::ReclaimNormal() { - constexpr int kFlags = PurgeFlags::kDecommitEmptySlotSpans | - PurgeFlags::kDiscardUnusedSystemPages; - Reclaim(kFlags); -} - void MemoryReclaimer::ReclaimFast() { constexpr int kFlags = PurgeFlags::kDecommitEmptySlotSpans | PurgeFlags::kDiscardUnusedSystemPages | @@ -55,6 +54,12 @@ void MemoryReclaimer::ReclaimFast() { Reclaim(kFlags); } +void MemoryReclaimer::ReclaimForTesting() { + constexpr int kFlags = PurgeFlags::kDecommitEmptySlotSpans | + PurgeFlags::kDiscardUnusedSystemPages; + Reclaim(kFlags); +} + void MemoryReclaimer::Reclaim(int flags) { internal::ScopedGuard lock( lock_); // Has to protect from concurrent (Un)Register calls. diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/memory_reclaimer.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/memory_reclaimer.h index fc2635da35..c2c66938b3 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/memory_reclaimer.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/memory_reclaimer.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_MEMORY_RECLAIMER_H_ #define PARTITION_ALLOC_MEMORY_RECLAIMER_H_ @@ -33,16 +38,10 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) MemoryReclaimer { // Internal. Do not use. // Registers a partition to be tracked by the reclaimer. - void RegisterPartition(PartitionRoot* partition); + void RegisterPartition(PartitionRoot* partition) PA_LOCKS_EXCLUDED(lock_); // Internal. Do not use. // Unregisters a partition to be tracked by the reclaimer. - void UnregisterPartition(PartitionRoot* partition); - - // Triggers an explicit reclaim now to reclaim as much free memory as - // possible. The API callers need to invoke this method periodically - // if they want to use memory reclaimer. - // See also GetRecommendedReclaimIntervalInMicroseconds()'s comment. - void ReclaimNormal(); + void UnregisterPartition(PartitionRoot* partition) PA_LOCKS_EXCLUDED(lock_); // Returns a recommended interval to invoke ReclaimNormal. int64_t GetRecommendedReclaimIntervalInMicroseconds() { @@ -50,16 +49,18 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) MemoryReclaimer { } // Triggers an explicit reclaim now reclaiming all free memory - void ReclaimAll(); + void ReclaimAll() PA_LOCKS_EXCLUDED(lock_); // Same as ReclaimNormal(), but return early if reclaim takes too long. - void ReclaimFast(); + void ReclaimFast() PA_LOCKS_EXCLUDED(lock_); + // Same as above, but does not limit reclaim time to avoid test flakiness. + void ReclaimForTesting() PA_LOCKS_EXCLUDED(lock_); private: MemoryReclaimer(); ~MemoryReclaimer(); // |flags| is an OR of base::PartitionPurgeFlags - void Reclaim(int flags); - void ResetForTesting(); + void Reclaim(int flags) PA_LOCKS_EXCLUDED(lock_); + void ResetForTesting() PA_LOCKS_EXCLUDED(lock_); internal::Lock lock_; std::set partitions_ PA_GUARDED_BY(lock_); diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/oom.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/oom.cc index 037e908181..6073acca79 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/oom.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/oom.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/oom.h" #include "partition_alloc/build_config.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/oom.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/oom.h index 85123a1e94..a577a49372 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/oom.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/oom.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_OOM_H_ #define PARTITION_ALLOC_OOM_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/oom_callback.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/oom_callback.cc index 0db8407182..afd87d11b4 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/oom_callback.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/oom_callback.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/oom_callback.h" #include "partition_alloc/partition_alloc_check.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/oom_callback.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/oom_callback.h index 3a4d32bcb1..ef703fd9af 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/oom_callback.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/oom_callback.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_OOM_CALLBACK_H_ #define PARTITION_ALLOC_OOM_CALLBACK_H_ 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 f07ec59f7c..6a9cc2494b 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/page_allocator.h" #include 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 b1a906b52c..7003ca5374 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PAGE_ALLOCATOR_H_ #define PARTITION_ALLOC_PAGE_ALLOCATOR_H_ 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 4f38bdd015..cbb3c78f51 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PAGE_ALLOCATOR_CONSTANTS_H_ #define PARTITION_ALLOC_PAGE_ALLOCATOR_CONSTANTS_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internal.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internal.h index d02f4548a6..1433a585dd 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internal.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internal.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PAGE_ALLOCATOR_INTERNAL_H_ #define PARTITION_ALLOC_PAGE_ALLOCATOR_INTERNAL_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_fuchsia.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_fuchsia.h index 53ce771c97..e8c15fb35a 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_fuchsia.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_fuchsia.h @@ -1,6 +1,11 @@ // Copyright 2019 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 // // This file implements memory allocation primitives for PageAllocator using // Fuchsia's VMOs (Virtual Memory Objects). VMO API is documented in 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 51d0c9d80e..f3d809b6d9 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 @@ -1,6 +1,11 @@ // 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. + +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif #include #include 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 9f8d09eebd..4d3c9b2222 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PAGE_ALLOCATOR_INTERNALS_POSIX_H_ #define PARTITION_ALLOC_PAGE_ALLOCATOR_INTERNALS_POSIX_H_ 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 70ba396ffa..9492afd205 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PAGE_ALLOCATOR_INTERNALS_WIN_H_ #define PARTITION_ALLOC_PAGE_ALLOCATOR_INTERNALS_WIN_H_ 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 48f9b67baa..9133e5f582 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_address_space.h" #include @@ -12,6 +17,7 @@ #include #include "partition_alloc/address_pool_manager.h" +#include "partition_alloc/allocator_config.h" #include "partition_alloc/build_config.h" #include "partition_alloc/buildflags.h" #include "partition_alloc/compressed_pointer.h" @@ -33,7 +39,7 @@ #include #endif // PA_BUILDFLAG(IS_WIN) -#if PA_CONFIG(ENABLE_SHADOW_METADATA) || PA_BUILDFLAG(ENABLE_THREAD_ISOLATION) +#if PA_BUILDFLAG(ENABLE_THREAD_ISOLATION) #include #endif @@ -80,26 +86,37 @@ PA_NOINLINE void HandlePoolAllocFailure() { } } +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) +PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR size_t +MetadataInnerOffset(pool_handle pool) { + PA_DCHECK(kRegularPoolHandle <= pool && pool < kMaxPoolHandle); + // Each metadata needs 2 SystemPage, i.e. 1 SystemPage for Guardian + // and another SystemPage for actual metadata. + // To make the first SystemPage a guardian, need `+ 1`. + return SystemPageSize() * (2 * (pool - kRegularPoolHandle) + 1); +} +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + } // namespace PA_CONSTINIT PartitionAddressSpace::PoolSetup PartitionAddressSpace::setup_; -#if PA_CONFIG(ENABLE_SHADOW_METADATA) -std::ptrdiff_t PartitionAddressSpace::regular_pool_shadow_offset_ = 0; -std::ptrdiff_t PartitionAddressSpace::brp_pool_shadow_offset_ = 0; -std::ptrdiff_t PartitionAddressSpace::configurable_pool_shadow_offset_ = 0; +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) +PA_CONSTINIT std::array + PartitionAddressSpace::offsets_to_metadata_ = { + 0, 0, 0, 0, +#if PA_BUILDFLAG(ENABLE_THREAD_ISOLATION) + 0, +#endif // PA_BUILDFLAG(ENABLE_THREAD_ISOLATION) +}; -// File descriptors for shared mappings. -base::PlatformFile PartitionAddressSpace::regular_pool_fd_ = - base::kInvalidPlatformFile; -base::PlatformFile PartitionAddressSpace::brp_pool_fd_ = - base::kInvalidPlatformFile; -base::PlatformFile PartitionAddressSpace::configurable_pool_fd_ = - base::kInvalidPlatformFile; - -uintptr_t PartitionAddressSpace::pool_shadow_address_ = +uintptr_t PartitionAddressSpace::metadata_region_start_ = PartitionAddressSpace::kUninitializedPoolBaseAddress; -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) + +#if PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) +size_t PartitionAddressSpace::metadata_region_size_ = 0; +#endif // PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) #if PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) #if !PA_BUILDFLAG(IS_IOS) @@ -139,16 +156,6 @@ bool PartitionAddressSpace::IsIOSTestProcess() { } #endif // PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) -#if PA_CONFIG(ENABLE_SHADOW_METADATA) -size_t PartitionAddressSpace::CorePoolShadowSize() { - return CorePoolSize(); -} - -size_t PartitionAddressSpace::ConfigurablePoolShadowSize() { - return kConfigurablePoolMaxSize; -} -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) - void PartitionAddressSpace::Init() { if (IsInitialized()) { return; @@ -224,6 +231,10 @@ void PartitionAddressSpace::Init() { #if PA_BUILDFLAG(ENABLE_POINTER_COMPRESSION) CompressedPointerBaseGlobal::SetBase(setup_.regular_pool_base_address_); #endif // PA_BUILDFLAG(ENABLE_POINTER_COMPRESSION) + +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + InitMetadataRegionAndOffsets(); +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) } void PartitionAddressSpace::InitConfigurablePool(uintptr_t pool_base, @@ -258,6 +269,21 @@ void PartitionAddressSpace::InitConfigurablePool(uintptr_t pool_base, WriteProtectThreadIsolatedGlobals(setup_.thread_isolation_); } #endif + +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + // Initialize metadata for configurable pool without PartitionAlloc enabled. + // This will happen when there exists a test which uses configurable pool + // and a sanitizer is enabled. + if (metadata_region_start_ != kUninitializedPoolBaseAddress) { + // Set offset from ConfigurablePool to MetadataRegion. + offsets_to_metadata_[kConfigurablePoolHandle] = + metadata_region_start_ - ConfigurablePoolBase() + + MetadataInnerOffset(kConfigurablePoolHandle); + } else { + // If no metadata region is available, use `SystemPageSize()`. + offsets_to_metadata_[kConfigurablePoolHandle] = SystemPageSize(); + } +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) } #if PA_BUILDFLAG(ENABLE_THREAD_ISOLATION) @@ -293,7 +319,11 @@ void PartitionAddressSpace::InitThreadIsolatedPool( PA_DCHECK(!IsInThreadIsolatedPool(setup_.thread_isolated_pool_base_address_ + pool_size)); - // TODO(crbug.com/40238514): support PA_ENABLE_SHADOW_METADATA +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + offsets_to_metadata_[kThreadIsolatedPoolHandle] = + metadata_region_start_ - setup_.thread_isolated_pool_base_address_ + + MetadataInnerOffset(kThreadIsolatedPoolHandle); +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) } #endif // PA_BUILDFLAG(ENABLE_THREAD_ISOLATION) @@ -314,6 +344,17 @@ void PartitionAddressSpace::UninitForTesting() { #if PA_BUILDFLAG(ENABLE_POINTER_COMPRESSION) CompressedPointerBaseGlobal::ResetBaseForTesting(); #endif // PA_BUILDFLAG(ENABLE_POINTER_COMPRESSION) + +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + FreePages(metadata_region_start_, MetadataRegionSize()); + metadata_region_start_ = kUninitializedPoolBaseAddress; +#if PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) + metadata_region_size_ = 0; +#endif // PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) + for (size_t i = 0; i < kMaxPoolHandle; ++i) { + offsets_to_metadata_[i] = SystemPageSize(); + } +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) } void PartitionAddressSpace::UninitConfigurablePoolForTesting() { @@ -334,6 +375,9 @@ void PartitionAddressSpace::UninitConfigurablePoolForTesting() { WriteProtectThreadIsolatedGlobals(setup_.thread_isolation_); } #endif +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + offsets_to_metadata_[kConfigurablePoolHandle] = SystemPageSize(); +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) } #if PA_BUILDFLAG(ENABLE_THREAD_ISOLATION) @@ -353,194 +397,55 @@ void PartitionAddressSpace::UninitThreadIsolatedPoolForTesting() { } #endif -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - -namespace { - -base::PlatformFile CreateAnonymousFileForMapping( - [[maybe_unused]] const char* name, - [[maybe_unused]] size_t size) { - base::PlatformFile fd = base::kInvalidPlatformFile; -#if PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS) - // TODO(crbug.com/40238514): if memfd_secret() is available, try - // memfd_secret() first. - fd = memfd_create(name, MFD_CLOEXEC); - PA_CHECK(0 == ftruncate(fd, size)); -#else - // Not implemented yet. - PA_NOTREACHED(); -#endif // PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS) - return fd; -} - -} // namespace - -void PartitionAddressSpace::InitShadowMetadata(PoolHandleMask mask) { +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) +// Allocate virtual address space of metadata and initialize metadata offsets +// of regular, brp and configurable pools. +void PartitionAddressSpace::InitMetadataRegionAndOffsets() { // Set up an address space only once. - if (pool_shadow_address_ == kUninitializedPoolBaseAddress) { - // Reserve 1 address space for all pools. - const size_t shadow_pool_size = - std::max(ConfigurablePoolShadowSize(), CorePoolShadowSize()); - - // Reserve virtual address space for the shadow pool. - uintptr_t pool_shadow_address = - AllocPages(shadow_pool_size, PageAllocationGranularity(), - PageAccessibilityConfiguration( - PageAccessibilityConfiguration::kInaccessible), - PageTag::kPartitionAlloc); - if (!pool_shadow_address) { - HandlePoolAllocFailure(); - } - - pool_shadow_address_ = pool_shadow_address; + if (metadata_region_start_ != kUninitializedPoolBaseAddress) { + return; } - // Set up a memory file for the given pool, and init |offset|. - if (ContainsFlags(mask, PoolHandleMask::kConfigurable)) { - if (configurable_pool_fd_ == base::kInvalidPlatformFile) { - PA_DCHECK(pool_shadow_address_); - PA_DCHECK(configurable_pool_shadow_offset_ == 0); - configurable_pool_fd_ = CreateAnonymousFileForMapping( - "configurable_pool_shadow", ConfigurablePoolShadowSize()); - configurable_pool_shadow_offset_ = - pool_shadow_address_ - ConfigurablePoolBase() + - SystemPageSize() * kSystemPageOffsetOfConfigurablePoolShadow; - } - } - if (ContainsFlags(mask, PoolHandleMask::kBRP)) { - if (brp_pool_fd_ == base::kInvalidPlatformFile) { - PA_DCHECK(pool_shadow_address_); - PA_DCHECK(brp_pool_shadow_offset_ == 0); - brp_pool_fd_ = CreateAnonymousFileForMapping("brp_pool_shadow", - CorePoolShadowSize()); - brp_pool_shadow_offset_ = - pool_shadow_address_ - BRPPoolBase() + - SystemPageSize() * kSystemPageOffsetOfBRPPoolShadow; - } - } - if (ContainsFlags(mask, PoolHandleMask::kRegular)) { - if (regular_pool_fd_ == base::kInvalidPlatformFile) { - PA_DCHECK(pool_shadow_address_); - PA_DCHECK(regular_pool_shadow_offset_ == 0); - regular_pool_fd_ = CreateAnonymousFileForMapping("regular_pool_shadow", - CorePoolShadowSize()); - regular_pool_shadow_offset_ = - pool_shadow_address_ - RegularPoolBase() + - SystemPageSize() * kSystemPageOffsetOfRegularPoolShadow; - } - } -} - -// Share a read-only metadata inside the given SuperPage with its writable -// metadata. -void PartitionAddressSpace::MapMetadata(uintptr_t super_page, - bool copy_metadata) { - PA_DCHECK(pool_shadow_address_); - PA_DCHECK(0u == (super_page & kSuperPageOffsetMask)); - std::ptrdiff_t offset; - base::PlatformFile pool_fd = base::kInvalidPlatformFile; - uintptr_t base_address; - - if (IsInRegularPool(super_page)) { - pool_fd = regular_pool_fd_; - offset = regular_pool_shadow_offset_; - base_address = RegularPoolBase(); - } else if (IsInBRPPool(super_page)) { - offset = brp_pool_shadow_offset_; - pool_fd = brp_pool_fd_; - base_address = BRPPoolBase(); - } else if (IsInConfigurablePool(super_page)) { - offset = configurable_pool_shadow_offset_; - pool_fd = configurable_pool_fd_; - base_address = ConfigurablePoolBase(); - } else { - PA_NOTREACHED(); - } - - uintptr_t metadata = super_page + SystemPageSize(); - size_t file_offset = (super_page - base_address) >> kSuperPageShift - << SystemPageShift(); - -#if PA_BUILDFLAG(IS_POSIX) - uintptr_t writable_metadata = metadata + offset; - void* ptr = mmap(reinterpret_cast(writable_metadata), SystemPageSize(), - PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, pool_fd, - file_offset); - PA_CHECK(ptr != MAP_FAILED); - PA_CHECK(ptr == reinterpret_cast(writable_metadata)); - - if (copy_metadata) [[unlikely]] { - // Copy the metadata from the private and copy-on-write page to - // the shared page. (=update the memory file) - memcpy(reinterpret_cast(writable_metadata), - reinterpret_cast(metadata), SystemPageSize()); - } - - ptr = mmap(reinterpret_cast(metadata), SystemPageSize(), PROT_READ, - MAP_FIXED | MAP_SHARED, pool_fd, file_offset); - PA_CHECK(ptr != MAP_FAILED); - PA_CHECK(ptr == reinterpret_cast(metadata)); -#else - // Not implemneted yet. - PA_NOTREACHED(); -#endif // PA_BUILDFLAG(IS_POSIX) -} - -// Regarding normal buckets, metadata will not be decommitted. However, -// regarding direct-mapped, metadata will be decommitted (see UnmapNow()). -// So shadow metadata must be also decommitted (including zero-initialization). -void PartitionAddressSpace::UnmapShadowMetadata(uintptr_t super_page, - pool_handle pool) { - PA_DCHECK(0u == (super_page & kSuperPageOffsetMask)); - std::ptrdiff_t offset; - - switch (pool) { - case kRegularPoolHandle: - PA_DCHECK(RegularPoolBase() <= super_page); - PA_DCHECK((super_page - RegularPoolBase()) < CorePoolSize()); - PA_DCHECK(IsShadowMetadataEnabled(kRegularPoolHandle)); - offset = regular_pool_shadow_offset_; - break; - case kBRPPoolHandle: - PA_DCHECK(BRPPoolBase() <= super_page); - PA_DCHECK((super_page - BRPPoolBase()) < CorePoolSize()); - PA_DCHECK(IsShadowMetadataEnabled(kBRPPoolHandle)); - offset = brp_pool_shadow_offset_; - break; - case kConfigurablePoolHandle: - PA_DCHECK(IsShadowMetadataEnabled(kConfigurablePoolHandle)); - offset = configurable_pool_shadow_offset_; - break; - default: +#if PA_BUILDFLAG(ENABLE_MOVE_METADATA_OUT_OF_GIGACAGE_TRIAL) + if (ExternalMetadataTrialGroup::kUndefined == + GetExternalMetadataTrialGroup()) { + if (SelectExternalMetadataTrialGroup() != + ExternalMetadataTrialGroup::kEnabled) { + for (size_t i = 0; i < kMaxPoolHandle; ++i) { + offsets_to_metadata_[i] = SystemPageSize(); + } return; + } + } +#endif // PA_BUILDFLAG(ENABLE_MOVE_METADATA_OUT_OF_GIGACAGE_TRIAL) + +#if PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) + metadata_region_size_ = std::max(kConfigurablePoolMaxSize, CorePoolSize()); +#endif // PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) + + uintptr_t address = + AllocPages(MetadataRegionSize(), PageAllocationGranularity(), + PageAccessibilityConfiguration( + PageAccessibilityConfiguration::kInaccessible), + PageTag::kPartitionAlloc); + if (!address) { + HandlePoolAllocFailure(); } - uintptr_t writable_metadata = super_page + SystemPageSize() + offset; + metadata_region_start_ = address; - void* ptr = reinterpret_cast(writable_metadata); + PA_DCHECK(RegularPoolBase() != kUninitializedPoolBaseAddress); + PA_DCHECK(BRPPoolBase() != kUninitializedPoolBaseAddress); - // When mapping the page again, we will use mmap() with MAP_FIXED | - // MAP_SHARED. Not with MAP_ANONYMOUS. If we don't clear the page here, the - // page will have the same content when re-mapped. - // TODO(crbug.com/40238514): Make PartitionAlloc not depend on that metadata - // pages have been already initialized to be zero. i.e. remove memset() below - // and make the constructors of SlotSpanMetadata, PartitionPageMetadata (and - // more struct/class if needed) initialize their members. Add test to check - // if the initialization is correctly done. - memset(ptr, 0, SystemPageSize()); + offsets_to_metadata_[kRegularPoolHandle] = + address - RegularPoolBase() + MetadataInnerOffset(kRegularPoolHandle); + offsets_to_metadata_[kBRPPoolHandle] = + address - BRPPoolBase() + MetadataInnerOffset(kBRPPoolHandle); -#if PA_BUILDFLAG(IS_POSIX) - void* ret = mmap(ptr, SystemPageSize(), PROT_NONE, - MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - PA_CHECK(ret != MAP_FAILED); - PA_CHECK(ret == ptr); -#else - // Not implemented yet. - PA_NOTREACHED(); -#endif // PA_BUILDFLAG(IS_POSIX) + // ConfigurablePool has not been initialized yet at this time. + offsets_to_metadata_[kConfigurablePoolHandle] = SystemPageSize(); } - -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) #if defined(PARTITION_ALLOCATOR_CONSTANTS_POSIX_NONCONST_PAGE_SIZE) 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 32d733ce97..b9b4d59b69 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ADDRESS_SPACE_H_ #define PARTITION_ALLOC_PARTITION_ADDRESS_SPACE_H_ @@ -15,7 +20,6 @@ #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/files/platform_file.h" #include "partition_alloc/partition_alloc_base/notreached.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/partition_alloc_config.h" @@ -50,7 +54,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) PoolOffsetLookup { // Similar to `GetOffset()`, but with MTE tag left in the top bits. PA_ALWAYS_INLINE uintptr_t GetTaggedOffset(void* ptr) const { const uintptr_t address = reinterpret_cast(ptr); - PA_DCHECK((address & base_mask_) == base_address_); + PA_DCHECK(Includes(address)); return address & (kPtrTagMask | ~base_mask_); } @@ -233,11 +237,11 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionAddressSpace { return (address & brp_pool_base_mask) == setup_.brp_pool_base_address_; } -#if PA_CONFIG(ENABLE_SHADOW_METADATA) +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) PA_ALWAYS_INLINE static uintptr_t BRPPoolBase() { return RegularPoolBase() + CorePoolSize(); } -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) // Checks whether the address belongs to either regular or BRP pool. // Returns false for nullptr. @@ -286,108 +290,69 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionAddressSpace { } #endif -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - PA_ALWAYS_INLINE static bool IsShadowMetadataEnabledOnRegularPool() { - return regular_pool_fd_ != base::kInvalidPlatformFile; +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + // The MetadataRegionSize() returns the size of address space of metadata. + // The address space contains all metadata for all pools (i.e. regular, brp, + // and configurable pools). +#if PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) + PA_ALWAYS_INLINE static size_t MetadataRegionSize() { + return metadata_region_size_; + } +#else + PA_ALWAYS_INLINE static constexpr size_t MetadataRegionSize() { + return std::max(kConfigurablePoolMaxSize, CorePoolSize()); + } +#endif + + // Returns a metadata offset. SuperPage address plus the offset contains + // the metadata for the SuperPage. + PA_ALWAYS_INLINE static std::ptrdiff_t MetadataOffset(pool_handle pool) { + return offsets_to_metadata_[pool]; } - PA_ALWAYS_INLINE static bool IsShadowMetadataEnabledOnBRPPool() { - return brp_pool_fd_ != base::kInvalidPlatformFile; - } - - PA_ALWAYS_INLINE static bool IsShadowMetadataEnabledOnConfigurablePool() { - return configurable_pool_fd_ != base::kInvalidPlatformFile; - } - - PA_ALWAYS_INLINE static bool IsShadowMetadataEnabled(pool_handle pool) { - switch (pool) { - case kRegularPoolHandle: - return IsShadowMetadataEnabledOnRegularPool(); - case kBRPPoolHandle: - return IsShadowMetadataEnabledOnBRPPool(); - case kConfigurablePoolHandle: - return IsShadowMetadataEnabledOnConfigurablePool(); - default: - return false; - } - } - - // To reduce the cost of address conversion (metadata address inside Regular - // Pool to its shadow metadata address), we will make the size of the address - // space of shadow metadata the same as `max(regular pool size, brp - // pool size, configurable pool size)` (only 1 shadow address space. Not 3) - // So we need to use different offset for metadata of the regular pool's - // SuperPages and for the brp pool's SuperPages. - // i.e. |kSystemPageOffsetOfRegularPoolShadow| and - // |kSystemPageOffsetOfBRPPoolShadow|. - // - // i: the index of SystemPage for metadata inside the regular pool's - // SuperPage. - // (currently, the index is 1.) - // - // i-th - // +------------+ - // | SystemPage | (regular pool) - // +------------+ - // \ - // \ mapping - // \ - // (i+kSystemPageOffsetOfRegularPoolShadow)-th - // +------------+ - // | SystemPage | (shadow) - // +------------+ - // - // (i + kSystemPageOffsetOfRegularPoolShadow)-th SystemPage inside the matched - // SuperPage inside the shadow pool is used for the metadata. - static constexpr size_t kSystemPageOffsetOfRegularPoolShadow = 0u; - static constexpr size_t kSystemPageOffsetOfBRPPoolShadow = 2u; - static constexpr size_t kSystemPageOffsetOfConfigurablePoolShadow = 4u; - - static size_t CorePoolShadowSize(); - static size_t ConfigurablePoolShadowSize(); - - PA_ALWAYS_INLINE static std::ptrdiff_t RegularPoolShadowOffset() { - return regular_pool_shadow_offset_; - } - - PA_ALWAYS_INLINE static std::ptrdiff_t BRPPoolShadowOffset() { - return brp_pool_shadow_offset_; - } - - PA_ALWAYS_INLINE static std::ptrdiff_t ConfigurablePoolShadowOffset() { - return configurable_pool_shadow_offset_; + PA_ALWAYS_INLINE static std::ptrdiff_t MetadataOffsetFromAddr( + uintptr_t address) { + return MetadataOffset(GetPoolHandle(address)); } // TODO(crbug.com/40238514): Confirm we can use kConfigurablePoolMaxSize/4 - // for iOS and confirm iOS EarlyGrey tests pass when the shadow metadata + // for iOS and confirm iOS EarlyGrey tests pass when the external metadata // is enabled, since IIRC iOS limits virtual address space too. static_assert( !PA_BUILDFLAG(IS_IOS), "kConfigurablePoolMaxSize is too large to run iOS EarlyGrey tests, " "because the test process cannot use an extended virtual address space. " - "Temporarily disable ShadowMetadata feature on iOS"); + "Temporarily disable ExternalMetadata feature on iOS"); #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 - // space for the shadow. We only use 2 SystemPageSize() / kSuperPageSize(%) - // of the space. - // - // TODO(crbug.com/40238514) This is an unused function. Start using it in - // tests and/or in production code. - PA_ALWAYS_INLINE static bool IsInPoolShadow(const void* ptr) { - uintptr_t ptr_as_uintptr = reinterpret_cast(ptr); - return (pool_shadow_address_ <= ptr_as_uintptr && - (ptr_as_uintptr < pool_shadow_address_ + CorePoolSize() || - ptr_as_uintptr < pool_shadow_address_ + kConfigurablePoolMaxSize)); + PA_ALWAYS_INLINE static bool IsInMetadataRegion(uintptr_t address) { + return metadata_region_start_ <= address && + address < metadata_region_start_ + MetadataRegionSize(); } #endif // PA_BUILDFLAG(DCHECKS_ARE_ON) - static void InitShadowMetadata(PoolHandleMask pool); - static void MapMetadata(uintptr_t super_page, bool copy_metadata); - static void UnmapShadowMetadata(uintptr_t super_page, pool_handle pool); -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) + PA_ALWAYS_INLINE static pool_handle GetPoolHandle(uintptr_t address) { +#if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) + if (IsInBRPPool(address)) [[likely]] { + return kBRPPoolHandle; + } +#endif + if (IsInRegularPool(address)) [[likely]] { + return kRegularPoolHandle; + } + if (IsInConfigurablePool(address)) { + return kConfigurablePoolHandle; + } +#if PA_BUILDFLAG(ENABLE_THREAD_ISOLATION) + if (IsInThreadIsolatedPool(address)) { + return kThreadIsolatedPoolHandle; + } +#endif + return kNullPoolHandle; + } + + static void InitMetadataRegionAndOffsets(); +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) // PartitionAddressSpace is static_only class. PartitionAddressSpace() = delete; @@ -525,15 +490,13 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionAddressSpace { // alignment and padding. PA_CONSTINIT static PoolSetup setup_; -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - static std::ptrdiff_t regular_pool_shadow_offset_; - static std::ptrdiff_t brp_pool_shadow_offset_; - static std::ptrdiff_t configurable_pool_shadow_offset_; - static base::PlatformFile regular_pool_fd_; - static base::PlatformFile brp_pool_fd_; - static base::PlatformFile configurable_pool_fd_; - static uintptr_t pool_shadow_address_; -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + static std::array offsets_to_metadata_; + static uintptr_t metadata_region_start_; +#if PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) + static size_t metadata_region_size_; +#endif // PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) #if PA_BUILDFLAG(ENABLE_THREAD_ISOLATION) // If we use thread isolation, we need to write-protect its metadata. 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 050d696525..cbc327c49e 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_INL_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_INL_H_ @@ -89,6 +94,41 @@ PA_ALWAYS_INLINE uintptr_t SlotStartPtr2Addr(const void* slot_start) { return UntagPtr(slot_start); } +// In order to resolve circular dependencies, define template method: +// GetMetadataOffset() here and SlotSpanMetadata::FromAddr(), +// SuperPageExtentEntry's SuperPageBeginFromExtent() ... use it. +template +std::ptrdiff_t GetMetadataOffset([[maybe_unused]] const T* root) { +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) + PA_DCHECK(root); +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) + return static_cast(root->MetadataOffset()); +#else + return static_cast(SystemPageSize()); +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) +} + +PA_ALWAYS_INLINE uintptr_t +PartitionSuperPageToMetadataPage(uintptr_t super_page, + [[maybe_unused]] std::ptrdiff_t offset) { +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + return super_page + static_cast(offset); +#else + return super_page + SystemPageSize(); +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) +} + +PA_ALWAYS_INLINE uintptr_t +PartitionMetadataPageToSuperPage(uintptr_t metadata_page, + [[maybe_unused]] std::ptrdiff_t offset) { +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + return metadata_page - static_cast(offset); +#else + return metadata_page - SystemPageSize(); +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) +} + } // namespace partition_alloc::internal #endif // PARTITION_ALLOC_PARTITION_ALLOC_INL_H_ 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 c0013141da..8196440e0d 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc.h" #include @@ -46,12 +51,7 @@ void PartitionAllocGlobalInit(OomFunction on_out_of_memory) { (internal::PartitionPageSize() & internal::SystemPageOffsetMask()) == 0, "ok partition page multiple"); static_assert( - sizeof( - internal::PartitionPageMetadata) <= - internal::kPageMetadataSize && - sizeof(internal::PartitionPageMetadata< - internal::MetadataKind::kWritable>) <= - internal::kPageMetadataSize, + sizeof(internal::PartitionPageMetadata) <= internal::kPageMetadataSize, "PartitionPage should not be too big"); STATIC_ASSERT_OR_PA_CHECK( internal::kPageMetadataSize * internal::NumPartitionPagesPerSuperPage() <= diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc.h index db88b67286..cce9eec2b3 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_H_ 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 e0fd180113..8281971842 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_ALLOCATION_DATA_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_ALLOCATION_DATA_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/foundation_util.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/foundation_util.h index 663863de0a..38ca8b5053 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/foundation_util.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/foundation_util.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_APPLE_FOUNDATION_UTIL_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_APPLE_FOUNDATION_UTIL_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/foundation_util.mm b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/foundation_util.mm index 4cf23ddedc..f32b897585 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/foundation_util.mm +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/foundation_util.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/apple/foundation_util.h" #include "partition_alloc/partition_alloc_base/check.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/mach_logging.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/mach_logging.cc index 759fb1539c..76f21f2251 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/mach_logging.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/mach_logging.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/apple/mach_logging.h" #include 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 719e4c0677..f8527c9bc6 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_APPLE_MACH_LOGGING_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_APPLE_MACH_LOGGING_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/scoped_cftyperef.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/scoped_cftyperef.h index ffa00c209d..02678a3287 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/scoped_cftyperef.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/scoped_cftyperef.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_APPLE_SCOPED_CFTYPEREF_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_APPLE_SCOPED_CFTYPEREF_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/scoped_typeref.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/scoped_typeref.h index 729fdf9bbf..dbe09c7a26 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/scoped_typeref.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/scoped_typeref.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_APPLE_SCOPED_TYPEREF_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_APPLE_SCOPED_TYPEREF_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/atomic_ref_count.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/atomic_ref_count.h index d34edfc10d..b894e26166 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/atomic_ref_count.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/atomic_ref_count.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // This is a low level implementation of atomic semantics for reference // counting. Please use base/memory/ref_counted.h directly instead. diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/augmentations/compiler_specific.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/augmentations/compiler_specific.h index 95769a8663..a73948f554 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/augmentations/compiler_specific.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/augmentations/compiler_specific.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_AUGMENTATIONS_COMPILER_SPECIFIC_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_AUGMENTATIONS_COMPILER_SPECIFIC_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/bit_cast.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/bit_cast.h index 3c625a5ba8..20edba5e80 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/bit_cast.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/bit_cast.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_BIT_CAST_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_BIT_CAST_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 a99b3ff306..0f0f6f99e1 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // This file defines some bit utilities. #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_BITS_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/check.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/check.cc index 957d662e52..584f7d585d 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/check.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/check.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/check.h" #include "partition_alloc/partition_alloc_base/logging.h" 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 2358e80046..22244bfbb8 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_CHECK_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_CHECK_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/compiler_specific.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/compiler_specific.h index b3275b135c..38a6d906ec 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/compiler_specific.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/compiler_specific.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_COMPILER_SPECIFIC_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_COMPILER_SPECIFIC_H_ @@ -480,4 +485,32 @@ inline constexpr bool AnalyzerAssumeTrue(bool arg) { #define PA_NOPROFILE #endif +// Annotates a function or class data member indicating it can lead to +// out-of-bounds accesses (OOB) if given incorrect inputs. +#if PA_HAS_CPP_ATTRIBUTE(clang::unsafe_buffer_usage) +#define PA_UNSAFE_BUFFER_USAGE [[clang::unsafe_buffer_usage]] +#else +#define PA_UNSAFE_BUFFER_USAGE +#endif + +// Annotates code indicating that it should be permanently exempted from +// `-Wunsafe-buffer-usage`. For temporary cases such as migrating callers to +// safer patterns, use `UNSAFE_TODO()` instead; +#if defined(__clang__) +// Disabling `clang-format` allows each `_Pragma` to be on its own line, as +// recommended by https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html. +// clang-format off +#define PA_UNSAFE_BUFFERS(...) \ + _Pragma("clang unsafe_buffer_usage begin") \ + __VA_ARGS__ \ + _Pragma("clang unsafe_buffer_usage end") +// clang-format on +#else +#define PA_UNSAFE_BUFFERS(...) __VA_ARGS__ +#endif + +// Annotates code indicating that it should be temporarily exempted from +// `-Wunsafe-buffer-usage`. +#define PA_UNSAFE_TODO(...) PA_UNSAFE_BUFFERS(__VA_ARGS__) + #endif // PARTITION_ALLOC_PARTITION_ALLOC_BASE_COMPILER_SPECIFIC_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/component_export.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/component_export.h index 94a565b834..4d16758c85 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/component_export.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/component_export.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_COMPONENT_EXPORT_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_COMPONENT_EXPORT_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/containers/flat_map.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/containers/flat_map.h index 250d2adddd..180c73a2ae 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/containers/flat_map.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/containers/flat_map.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_CONTAINERS_FLAT_MAP_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_CONTAINERS_FLAT_MAP_H_ @@ -13,6 +18,7 @@ #include "partition_alloc/partition_alloc_base/check.h" #include "partition_alloc/partition_alloc_base/containers/flat_tree.h" +#include "partition_alloc/partition_alloc_base/cxx20_identity.h" #include "partition_alloc/partition_alloc_base/template_util.h" namespace partition_alloc::internal::base { @@ -374,7 +380,7 @@ template , class Container = std::vector>, class InputContainer, - class Projection = std::identity> + class Projection = base::identity> constexpr flat_map MakeFlatMap( const InputContainer& unprojected_elements, const KeyCompare& comp = KeyCompare(), diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/containers/flat_tree.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/containers/flat_tree.h index 9ed51a8ebe..6f8624628f 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/containers/flat_tree.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/containers/flat_tree.h @@ -2,12 +2,16 @@ // 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 PARTITION_ALLOC_PARTITION_ALLOC_BASE_CONTAINERS_FLAT_TREE_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_CONTAINERS_FLAT_TREE_H_ #include #include -#include #include #include #include @@ -365,8 +369,24 @@ class flat_tree { return lhs.body_ == rhs.body_; } - friend auto operator<=>(const flat_tree& lhs, const flat_tree& rhs) { - return lhs.body_ <=> rhs.body_; + friend bool operator<(const flat_tree& lhs, const flat_tree& rhs) { + return lhs.body_ < rhs.body_; + } + + friend bool operator!=(const flat_tree& lhs, const flat_tree& rhs) { + return !(lhs == rhs); + } + + friend bool operator>(const flat_tree& lhs, const flat_tree& rhs) { + return rhs < lhs; + } + + friend bool operator<=(const flat_tree& lhs, const flat_tree& rhs) { + return !(rhs < lhs); + } + + friend bool operator>=(const flat_tree& lhs, const flat_tree& rhs) { + return !(lhs < rhs); } friend void swap(flat_tree& lhs, flat_tree& rhs) noexcept { lhs.swap(rhs); } @@ -766,7 +786,7 @@ void flat_tree::insert( // Dispatch to single element insert if the input range contains a single // element. - if (std::forward_iterator && std::next(first) == last) { + if (is_multipass::value && std::next(first) == last) { insert(end(), *first); return; } diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cpu.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cpu.cc index 382cb7faa4..0837dc7e7a 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cpu.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cpu.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/cpu.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cpu.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cpu.h index 27f2ea2fd8..7f6ada7c59 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cpu.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cpu.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_CPU_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_CPU_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cxx20_identity.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cxx20_identity.h new file mode 100644 index 0000000000..e4b679ca74 --- /dev/null +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cxx20_identity.h @@ -0,0 +1,32 @@ +// Copyright 2025 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 +#ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_CXX20_IDENTITY_H_ +#define PARTITION_ALLOC_PARTITION_ALLOC_BASE_CXX20_IDENTITY_H_ + +#include +#include + +// An implementation of C++20 `std::identity` functor object. +// +// https://en.cppreference.com/w/cpp/utility/functional/identity.html + +namespace partition_alloc::internal::base { + +struct identity { + template + constexpr T&& operator()(T&& t) const noexcept { + return std::forward(t); + } + + using is_transparent = void; +}; + +} // namespace partition_alloc::internal::base + +#endif // PARTITION_ALLOC_PARTITION_ALLOC_BASE_CXX20_IDENTITY_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cxx20_is_constant_evaluated.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cxx20_is_constant_evaluated.h index cdacb7ffb7..84cc320562 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cxx20_is_constant_evaluated.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cxx20_is_constant_evaluated.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_CXX20_IS_CONSTANT_EVALUATED_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_CXX20_IS_CONSTANT_EVALUATED_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cxx_wrapper/algorithm.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cxx_wrapper/algorithm.h index 3df94f07e6..8476e98361 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cxx_wrapper/algorithm.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cxx_wrapper/algorithm.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // This is a header which wraps algorithm to avoid missing // libcpp_verbose_abort(). diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cxx_wrapper/optional.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cxx_wrapper/optional.h index 597b613189..61516e7983 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cxx_wrapper/optional.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cxx_wrapper/optional.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // This is a header which wraps optional to avoid missing // libcpp_verbose_abort(). diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/alias.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/alias.cc index 842266a880..2ded933823 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/alias.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/alias.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/debug/alias.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/alias.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/alias.h index ab7410b657..ebf2d7a821 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/alias.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/alias.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_DEBUG_ALIAS_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_DEBUG_ALIAS_H_ 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 index d5875b3795..6b7832fae5 100644 --- 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 @@ -2,6 +2,10 @@ // 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" 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 index e8e6ccc2cd..ac6c0a4fdc 100644 --- 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_DEBUG_PROC_MAPS_LINUX_H_ #define 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 76e3c1a99c..3f228c70ad 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/debug/stack_trace.h" #include 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 287765d494..9e946d7e1f 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_DEBUG_STACK_TRACE_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_DEBUG_STACK_TRACE_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_android.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_android.cc index 42fd3b0e0f..9061734574 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_android.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_android.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/debug/stack_trace.h" #include 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 f2bfb20711..d37cd439e6 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/debug/stack_trace.h" #include "partition_alloc/build_config.h" 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 74a17d2c5d..acc2c95827 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/debug/stack_trace.h" #include "partition_alloc/build_config.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_posix.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_posix.cc index 8b4a734026..1745f2ca26 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_posix.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_posix.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/debug/stack_trace.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_win.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_win.cc index 8c3ef6a8bd..00a4ac2741 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_win.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/debug/stack_trace.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/export_template.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/export_template.h index 14dd5dde9a..0965e2c226 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/export_template.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/export_template.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_EXPORT_TEMPLATE_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_EXPORT_TEMPLATE_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/file_path.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/file_path.cc index 539b5992d5..c6bc239e34 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/file_path.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/file_path.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/files/file_path.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/file_path.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/file_path.h index 204e2969cf..bfcd12d328 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/file_path.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/file_path.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // FilePath is a container for pathnames stored in a platform's native string // type, providing containers for manipulation in according with the // platform's conventions for pathnames. It supports the following path diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/file_util.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/file_util.h index ce21e327bc..86ffccdbde 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/file_util.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/file_util.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // This file contains utility functions for dealing with the local // filesystem. diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/file_util_posix.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/file_util_posix.cc index bf0dbfc4af..3359e7d1e4 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/file_util_posix.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/file_util_posix.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/files/file_util.h" #include "partition_alloc/partition_alloc_base/posix/eintr_wrapper.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/platform_file.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/platform_file.h index cd7c1617e7..a589226e97 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/platform_file.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/platform_file.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_FILES_PLATFORM_FILE_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_FILES_PLATFORM_FILE_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/fuchsia/fuchsia_logging.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/fuchsia/fuchsia_logging.cc index 3c9e10e91f..21c4784e8a 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/fuchsia/fuchsia_logging.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/fuchsia/fuchsia_logging.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/fuchsia/fuchsia_logging.h" #include 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 cbddde331d..f818edd714 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_FUCHSIA_FUCHSIA_LOGGING_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_FUCHSIA_FUCHSIA_LOGGING_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/immediate_crash.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/immediate_crash.h index e0ee3ec059..649ee1b38e 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/immediate_crash.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/immediate_crash.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_IMMEDIATE_CRASH_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_IMMEDIATE_CRASH_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ios/ios_util.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ios/ios_util.h index b389022b59..4e041b7e43 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ios/ios_util.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ios/ios_util.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_IOS_IOS_UTIL_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_IOS_IOS_UTIL_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ios/ios_util.mm b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ios/ios_util.mm index bd89dc2ad8..a9ec3a1208 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ios/ios_util.mm +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ios/ios_util.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/ios/ios_util.h" #include 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 d61be9bed8..3ffbac56bd 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/log_message.h" // TODO(crbug.com/40158212): After finishing copying //base files to PA library, 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 46b233d674..465cf3c096 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_LOG_MESSAGE_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_LOG_MESSAGE_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/logging.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/logging.cc index da8003f8db..dc0d990b09 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/logging.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/logging.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/logging.h" // TODO(crbug.com/40158212): After finishing copying //base files to PA library, 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 3f4ed8b3f2..3e799f369f 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_LOGGING_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_LOGGING_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/mac/mac_util.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/mac/mac_util.h index d692294e9c..4d8e5496a8 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/mac/mac_util.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/mac/mac_util.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_MAC_MAC_UTIL_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_MAC_MAC_UTIL_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/mac/mac_util.mm b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/mac/mac_util.mm index 9bf9f1ddc4..0f34a7c22b 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/mac/mac_util.mm +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/mac/mac_util.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/mac/mac_util.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/page_size.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/page_size.h index 7180f034f1..b2f7a793aa 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/page_size.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/page_size.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_MEMORY_PAGE_SIZE_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_MEMORY_PAGE_SIZE_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/page_size_posix.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/page_size_posix.cc index 245bc5898c..e05be9f904 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/page_size_posix.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/page_size_posix.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/memory/page_size.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/page_size_win.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/page_size_win.cc index e5bfb76e77..efc39cf241 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/page_size_win.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/page_size_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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/memory/page_size.h" namespace partition_alloc::internal::base { 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 f952f31893..29d7308493 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/memory/ref_counted.h" #include 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 2b8b87ba11..ce52e9a62a 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_MEMORY_REF_COUNTED_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_MEMORY_REF_COUNTED_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/scoped_policy.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/scoped_policy.h index e8e9a200ff..32f88bc218 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/scoped_policy.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/scoped_policy.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_MEMORY_SCOPED_POLICY_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_MEMORY_SCOPED_POLICY_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/scoped_refptr.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/scoped_refptr.h index 872c16db18..29f34714d3 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/scoped_refptr.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/scoped_refptr.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_MEMORY_SCOPED_REFPTR_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_MEMORY_SCOPED_REFPTR_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/native_library.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/native_library.cc index 23ab7a3068..a21a8fa498 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/native_library.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/native_library.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/native_library.h" namespace partition_alloc::internal::base { diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/native_library.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/native_library.h index 0801af04e9..033bb7e969 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/native_library.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/native_library.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_NATIVE_LIBRARY_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_NATIVE_LIBRARY_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/native_library_posix.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/native_library_posix.cc index cddd47eb6e..fdc18de9ff 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/native_library_posix.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/native_library_posix.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/native_library.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/no_destructor.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/no_destructor.h index 2daa62ceef..eb4e196530 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/no_destructor.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/no_destructor.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_NO_DESTRUCTOR_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_NO_DESTRUCTOR_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/notreached.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/notreached.h index 57086c20ef..4c26985e80 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/notreached.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/notreached.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_NOTREACHED_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_NOTREACHED_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/checked_math.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/checked_math.h index 739a5e9f64..89d6c5fde8 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/checked_math.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/checked_math.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_CHECKED_MATH_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_CHECKED_MATH_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/checked_math_impl.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/checked_math_impl.h index ea92dba29a..8e78e8e69c 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/checked_math_impl.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/checked_math_impl.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_CHECKED_MATH_IMPL_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_CHECKED_MATH_IMPL_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/clamped_math.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/clamped_math.h index e579ced1ad..235c3c2d4d 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/clamped_math.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/clamped_math.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_CLAMPED_MATH_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_CLAMPED_MATH_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/clamped_math_impl.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/clamped_math_impl.h index b18d1d628a..329bf361fc 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/clamped_math_impl.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/clamped_math_impl.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_CLAMPED_MATH_IMPL_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_CLAMPED_MATH_IMPL_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_conversions.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_conversions.h index 6ab5e0272a..cf582ec71f 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_conversions.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_conversions.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_SAFE_CONVERSIONS_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_SAFE_CONVERSIONS_H_ @@ -12,7 +17,7 @@ #include "partition_alloc/partition_alloc_base/numerics/safe_conversions_impl.h" -#if defined(__ARMEL__) && !defined(__native_client__) +#if defined(__ARMEL__) #include "partition_alloc/partition_alloc_base/numerics/safe_conversions_arm_impl.h" #define PA_BASE_HAS_OPTIMIZED_SAFE_CONVERSIONS (1) #else diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_conversions_arm_impl.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_conversions_arm_impl.h index 354d53e11a..73abf2d5a6 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_conversions_arm_impl.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_conversions_arm_impl.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_SAFE_CONVERSIONS_ARM_IMPL_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_SAFE_CONVERSIONS_ARM_IMPL_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_conversions_impl.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_conversions_impl.h index 4c5ab0f0bd..f5099cd54e 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_conversions_impl.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_conversions_impl.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_math.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_math.h index fcf72d34ea..197bf72679 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_math.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_math.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_SAFE_MATH_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_SAFE_MATH_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_math_arm_impl.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_math_arm_impl.h index a352d71e2c..51acb69674 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_math_arm_impl.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_math_arm_impl.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_SAFE_MATH_ARM_IMPL_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_SAFE_MATH_ARM_IMPL_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_math_clang_gcc_impl.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_math_clang_gcc_impl.h index 4bea84739a..07c08bd921 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_math_clang_gcc_impl.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_math_clang_gcc_impl.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_SAFE_MATH_CLANG_GCC_IMPL_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_SAFE_MATH_CLANG_GCC_IMPL_H_ @@ -11,7 +16,7 @@ #include "partition_alloc/partition_alloc_base/numerics/safe_conversions.h" -#if !defined(__native_client__) && (defined(__ARMEL__) || defined(__arch64__)) +#if defined(__ARMEL__) || defined(__arch64__) #include "partition_alloc/partition_alloc_base/numerics/safe_math_arm_impl.h" #define PA_BASE_HAS_ASSEMBLER_SAFE_MATH (1) #else diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_math_shared_impl.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_math_shared_impl.h index 316c977472..907d3a999d 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_math_shared_impl.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/numerics/safe_math_shared_impl.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_SAFE_MATH_SHARED_IMPL_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_NUMERICS_SAFE_MATH_SHARED_IMPL_H_ @@ -21,11 +26,10 @@ // Optimized safe math instructions are incompatible with asmjs. #define PA_BASE_HAS_OPTIMIZED_SAFE_MATH (0) // Where available use builtin math overflow support on Clang and GCC. -#elif !defined(__native_client__) && \ - ((defined(__clang__) && \ - ((__clang_major__ > 3) || \ - (__clang_major__ == 3 && __clang_minor__ >= 4))) || \ - (defined(__GNUC__) && __GNUC__ >= 5)) +#elif (defined(__clang__) && \ + ((__clang_major__ > 3) || \ + (__clang_major__ == 3 && __clang_minor__ >= 4))) || \ + (defined(__GNUC__) && __GNUC__ >= 5) #include "partition_alloc/partition_alloc_base/numerics/safe_math_clang_gcc_impl.h" #define PA_BASE_HAS_OPTIMIZED_SAFE_MATH (1) #else diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/posix/eintr_wrapper.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/posix/eintr_wrapper.h index 35d4f45a91..fe8b5d0f96 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/posix/eintr_wrapper.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/posix/eintr_wrapper.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // This provides a wrapper around system calls which may be interrupted by a // signal and return EINTR. See man 7 signal. // To prevent long-lasting loops (which would likely be a bug, such as a signal diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/posix/safe_strerror.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/posix/safe_strerror.cc index a910431edb..e5b9630fe5 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/posix/safe_strerror.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/posix/safe_strerror.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/posix/safe_strerror.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/posix/safe_strerror.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/posix/safe_strerror.h index 1637536718..9fe685428f 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/posix/safe_strerror.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/posix/safe_strerror.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_POSIX_SAFE_STRERROR_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_POSIX_SAFE_STRERROR_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/process/process_handle.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/process/process_handle.h index f2961dd625..2e634e6268 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/process/process_handle.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/process/process_handle.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_PROCESS_PROCESS_HANDLE_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_PROCESS_PROCESS_HANDLE_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/process/process_handle_posix.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/process/process_handle_posix.cc index 8989883dea..8ce8c47de1 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/process/process_handle_posix.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/process/process_handle_posix.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/process/process_handle.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/process/process_handle_win.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/process/process_handle_win.cc index 9fcc80990f..2b9d68c02b 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/process/process_handle_win.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/process/process_handle_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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/process/process_handle.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util.cc index 84634564c4..765cd9ad27 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/rand_util.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util.h index 3682a342e1..df8cea737e 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_RAND_UTIL_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_RAND_UTIL_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util_fuchsia.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util_fuchsia.cc index e3e777396c..412ef2498e 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util_fuchsia.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util_fuchsia.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/rand_util.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util_posix.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util_posix.cc index db79a65284..d95e72c5ec 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util_posix.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util_posix.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/rand_util.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util_win.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util_win.cc index 1596bc2a31..428ac1e98f 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util_win.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util_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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/rand_util.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ranges/algorithm.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ranges/algorithm.h index c7e1d631ca..4560dd5a20 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ranges/algorithm.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ranges/algorithm.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_RANGES_ALGORITHM_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_RANGES_ALGORITHM_H_ @@ -14,6 +19,7 @@ #include "partition_alloc/partition_alloc_base/check.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" +#include "partition_alloc/partition_alloc_base/cxx20_identity.h" #include "partition_alloc/partition_alloc_base/cxx20_is_constant_evaluated.h" #include "partition_alloc/partition_alloc_base/ranges/functional.h" #include "partition_alloc/partition_alloc_base/ranges/ranges.h" @@ -51,8 +57,8 @@ constexpr auto ProjectedUnaryPredicate(Pred& pred, Proj& proj) noexcept { // // typename = // std::indirect_result_t, Proj1>, -// std::projected, Proj2>> +// base::projected, Proj1>, +// base::projected, Proj2>> // // Ensures that the return type of `invoke(pred, ...)` is convertible to bool. template @@ -167,7 +173,7 @@ namespace ranges { // https://wg21.link/alg.adjacent.find#:~:text=ranges::adjacent_find(I template > constexpr auto adjacent_find(ForwardIterator first, ForwardIterator last, @@ -207,7 +213,7 @@ constexpr auto adjacent_find(ForwardIterator first, // https://wg21.link/alg.adjacent.find#:~:text=ranges::adjacent_find(R template > constexpr auto adjacent_find(Range&& range, Pred pred = {}, Proj proj = {}) { return ranges::adjacent_find(ranges::begin(range), ranges::end(range), @@ -233,15 +239,21 @@ constexpr auto adjacent_find(Range&& range, Pred pred = {}, Proj proj = {}) { // Remarks: result may be equal to `first1`. // // Reference: https://wg21.link/alg.transform#:~:text=ranges::transform(I -template < - typename InputIterator, - typename OutputIterator, - typename UnaryOperation, - typename Proj = std::identity, - typename = internal::iterator_category_t, - typename = internal::iterator_category_t, - typename = std::indirect_result_t>> +template , + typename = internal::iterator_category_t +// This constraint ensures that the return type of `invoke(binary_op, ...)` +// is convertible to the type of `*result`. +// Unfortunately, we cannot fully express this constraint in C++17. +#if __cplusplus >= 202002L + , + typename = std::indirect_result_t> +#endif + > constexpr auto transform(InputIterator first1, InputIterator last1, OutputIterator result, @@ -273,11 +285,18 @@ template < typename Range, typename OutputIterator, typename UnaryOperation, - typename Proj = std::identity, + typename Proj = base::identity, typename = internal::range_category_t, - typename = internal::iterator_category_t, + typename = internal::iterator_category_t +// This constraint ensures that the return type of `invoke(binary_op, ...)` +// is convertible to the type of `*result`. +// Unfortunately, we cannot fully express this constraint in C++17. +#if __cplusplus >= 202002L + , typename = std::indirect_result_t, Proj>>> + std::projected, Proj>> +#endif + > constexpr auto transform(Range&& range, OutputIterator result, UnaryOperation op, @@ -310,14 +329,21 @@ template < typename ForwardIterator2, typename OutputIterator, typename BinaryOperation, - typename Proj1 = std::identity, - typename Proj2 = std::identity, + typename Proj1 = base::identity, + typename Proj2 = base::identity, typename = internal::iterator_category_t, typename = internal::iterator_category_t, - typename = internal::iterator_category_t, + typename = internal::iterator_category_t +// This constraint ensures that the return type of `invoke(binary_op, ...)` +// is convertible to the type of `*result`. +// Unfortunately, we cannot fully express this constraint in C++17. +#if __cplusplus >= 202002L + , typename = std::indirect_result_t, - std::projected>> + std::projected> +#endif + > constexpr auto transform(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, @@ -358,19 +384,26 @@ constexpr auto transform(ForwardIterator1 first1, // Remarks: `result` may be equal to `begin(range1)` or `begin(range2)`. // // Reference: https://wg21.link/alg.transform#:~:text=ranges::transform(R1 -template , - typename = internal::range_category_t, - typename = internal::iterator_category_t, - typename = - std::indirect_result_t, Proj1>, - std::projected, Proj2>>> +template < + typename Range1, + typename Range2, + typename OutputIterator, + typename BinaryOperation, + typename Proj1 = base::identity, + typename Proj2 = base::identity, + typename = internal::range_category_t, + typename = internal::range_category_t, + typename = internal::iterator_category_t +// This constraint ensures that the return type of `invoke(binary_op, ...)` +// is convertible to the type of `*result`. +// Unfortunately, we cannot fully express this constraint in C++17. +#if __cplusplus >= 202002L + , + typename = std::indirect_result_t, Proj1>, + std::projected, Proj2>> +#endif + > constexpr auto transform(Range1&& range1, Range2&& range2, OutputIterator result, @@ -398,7 +431,7 @@ constexpr auto transform(Range1&& range1, // Reference: https://wg21.link/alg.remove#:~:text=ranges::remove_if(I template > constexpr auto remove_if(ForwardIterator first, ForwardIterator last, @@ -422,7 +455,7 @@ constexpr auto remove_if(ForwardIterator first, // Reference: https://wg21.link/alg.remove#:~:text=ranges::remove_if(R template > constexpr auto remove_if(Range&& range, Predicate pred, Proj proj = {}) { return ranges::remove_if(ranges::begin(range), ranges::end(range), @@ -448,7 +481,7 @@ constexpr auto remove_if(Range&& range, Predicate pred, Proj proj = {}) { template > constexpr auto lower_bound(ForwardIterator first, ForwardIterator last, @@ -456,8 +489,8 @@ constexpr auto lower_bound(ForwardIterator first, Comp comp = {}, Proj proj = {}) { // The second arg is guaranteed to be `value`, so we'll simply apply the - // std::identity projection. - std::identity value_proj; + // base::identity projection. + base::identity value_proj; return std::lower_bound( first, last, value, internal::ProjectedBinaryPredicate(comp, proj, value_proj)); @@ -476,7 +509,7 @@ constexpr auto lower_bound(ForwardIterator first, template > constexpr auto lower_bound(Range&& range, const T& value, @@ -502,7 +535,7 @@ constexpr auto lower_bound(Range&& range, template > constexpr auto upper_bound(ForwardIterator first, ForwardIterator last, @@ -510,8 +543,8 @@ constexpr auto upper_bound(ForwardIterator first, Comp comp = {}, Proj proj = {}) { // The first arg is guaranteed to be `value`, so we'll simply apply the - // std::identity projection. - std::identity value_proj; + // base::identity projection. + base::identity value_proj; return std::upper_bound( first, last, value, internal::ProjectedBinaryPredicate(comp, value_proj, proj)); @@ -530,7 +563,7 @@ constexpr auto upper_bound(ForwardIterator first, template > constexpr auto upper_bound(Range&& range, const T& value, diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ranges/functional.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ranges/functional.h index f74dda358d..5346002a82 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ranges/functional.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ranges/functional.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_RANGES_FUNCTIONAL_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_RANGES_FUNCTIONAL_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ranges/ranges.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ranges/ranges.h index a3177b9fa0..e9722f455f 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ranges/ranges.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ranges/ranges.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // Since PartitionAlloc disallows c++20 ranges, use base::ranges instead. #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_RANGES_RANGES_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_RANGES_RANGES_H_ @@ -11,6 +16,7 @@ #include #include +#include "partition_alloc/partition_alloc_base/cxx20_identity.h" #include "partition_alloc/partition_alloc_base/template_util.h" namespace partition_alloc::internal::base { @@ -128,11 +134,15 @@ constexpr auto end(Range&& range) noexcept template using iterator_t = decltype(ranges::begin(std::declval())); +// Implementation of C++20's std::iter_value_t. +template +using iter_value_t = typename std::iterator_traits::value_type; + // Implementation of C++20's std::ranges::range_value_t. // // Reference: https://wg21.link/ranges.syn#:~:text=range_value_t template -using range_value_t = std::iter_value_t>; +using range_value_t = iter_value_t>; } // namespace ranges diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/scoped_clear_last_error.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/scoped_clear_last_error.h index d3460d907e..7cbfe824ea 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/scoped_clear_last_error.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/scoped_clear_last_error.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_SCOPED_CLEAR_LAST_ERROR_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_SCOPED_CLEAR_LAST_ERROR_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/scoped_clear_last_error_win.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/scoped_clear_last_error_win.cc index e6ebe6a7a4..bb5a964977 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/scoped_clear_last_error_win.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/scoped_clear_last_error_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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/scoped_clear_last_error.h" #include 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 e3d1060c6c..3539351911 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/strings/cstring_builder.h" #include "partition_alloc/build_config.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/cstring_builder.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/cstring_builder.h index e6987dabca..ecf54f520f 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/cstring_builder.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/cstring_builder.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_STRINGS_CSTRING_BUILDER_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_STRINGS_CSTRING_BUILDER_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/safe_sprintf.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/safe_sprintf.cc index 46453a8bb4..b3958451bb 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/safe_sprintf.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/safe_sprintf.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/strings/safe_sprintf.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/safe_sprintf.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/safe_sprintf.h index 8f4f949294..c846c45359 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/safe_sprintf.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/safe_sprintf.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_STRINGS_SAFE_SPRINTF_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_STRINGS_SAFE_SPRINTF_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/string_util.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/string_util.cc index ef124f379a..ad9f26dc40 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/string_util.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/string_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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/strings/string_util.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/string_util.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/string_util.h index 41e1b917ee..35b3b13efa 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/string_util.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/string_util.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_STRINGS_STRING_UTIL_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_STRINGS_STRING_UTIL_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/stringprintf.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/stringprintf.cc index a9be5a763e..df3e8f3f45 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/stringprintf.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/stringprintf.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/strings/stringprintf.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/stringprintf.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/stringprintf.h index b445669923..6927f006ef 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/stringprintf.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/stringprintf.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_STRINGS_STRINGPRINTF_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_STRINGS_STRINGPRINTF_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/system/sys_info.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/system/sys_info.h index b88a3d7f09..4f4737289b 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/system/sys_info.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/system/sys_info.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_SYSTEM_SYS_INFO_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_SYSTEM_SYS_INFO_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/system/sys_info_ios.mm b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/system/sys_info_ios.mm index 0082bcb13a..bd01f38bb2 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/system/sys_info_ios.mm +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/system/sys_info_ios.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/system/sys_info.h" #import diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/system/sys_info_mac.mm b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/system/sys_info_mac.mm index 20a4205860..14b9b71145 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/system/sys_info_mac.mm +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/system/sys_info_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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/system/sys_info.h" #import diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/template_util.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/template_util.h index dbc7a7a1d1..7854ecb56a 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/template_util.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/template_util.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_TEMPLATE_UTIL_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_TEMPLATE_UTIL_H_ 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 index 4b39dd1650..ed3ee5fbb7 100644 --- 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_TEST_GTEST_UTIL_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_TEST_GTEST_UTIL_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/test/move_only_int.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/test/move_only_int.h index 79c9141423..943592f96c 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/test/move_only_int.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/test/move_only_int.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_TEST_MOVE_ONLY_INT_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_TEST_MOVE_ONLY_INT_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 feb1d13ee9..cb7bb3eaed 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // This header file contains macro definitions for thread safety annotations // that allow developers to document the locking policies of multi-threaded // code. The annotations can also help program analysis tools to identify diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/thread_annotations_pa_nocompile.nc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/thread_annotations_pa_nocompile.nc index 3ba937a95b..118709bf8f 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/thread_annotations_pa_nocompile.nc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/thread_annotations_pa_nocompile.nc @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // This is a "No Compile Test" suite. // https://dev.chromium.org/developers/testing/no-compile-tests 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 27d2cff853..ff4871b93d 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/threading/platform_thread.h" namespace partition_alloc::internal::base { diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread.h index 0f63568f2e..b779ac57d9 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // WARNING: You should *NOT* be using this class directly. PlatformThread is // the low-level platform-specific abstraction to the OS's threading interface. // You should instead be using a message-loop driven Thread, see thread.h. @@ -11,6 +16,7 @@ #include #include +#include #include "partition_alloc/build_config.h" #include "partition_alloc/partition_alloc_base/component_export.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_android_for_testing.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_android_for_testing.cc index 0ee3fae4a5..4c1e80967d 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_android_for_testing.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_android_for_testing.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_apple_for_testing.mm b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_apple_for_testing.mm index 63f6a91528..19b5eecf01 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_apple_for_testing.mm +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_apple_for_testing.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #import #include #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_for_testing.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_for_testing.h index a99b483fe4..01c1e9c5ef 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_for_testing.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_for_testing.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // WARNING: You should *NOT* be using this class directly. PlatformThread is // the low-level platform-specific abstraction to the OS's threading interface. // You should instead be using a message-loop driven Thread, see thread.h. diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_fuchsia_for_testing.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_fuchsia_for_testing.cc index d0eb7ef8ac..e89b9a9350 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_fuchsia_for_testing.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_fuchsia_for_testing.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_internal_posix.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_internal_posix.h index aa217b8509..dea633756c 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_internal_posix.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_internal_posix.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_THREADING_PLATFORM_THREAD_INTERNAL_POSIX_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_THREADING_PLATFORM_THREAD_INTERNAL_POSIX_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_linux_for_testing.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_linux_for_testing.cc index 17a8334805..7e675065cb 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_linux_for_testing.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_linux_for_testing.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include #include 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 d41f5bac06..79ed2fca5e 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/threading/platform_thread.h" #include 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 bcb20dc18a..e127111729 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include #include #include @@ -12,6 +17,7 @@ #include #include #include +#include #include "partition_alloc/build_config.h" #include "partition_alloc/buildflags.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_ref.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_ref.h index 751f83ae49..d9fd321978 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_ref.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_ref.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // WARNING: *DO NOT* use this class directly. base::PlatformThreadRef is a // low-level platform-specific abstraction to the OS's threading interface. // Instead, consider using a message-loop driven base::Thread, see diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_win.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_win.cc index 82aa2e533e..5df1aaa87a 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_win.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/threading/platform_thread.h" #include 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 5648472d96..af3beb1698 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time.cc index 5e7e92eba1..a0476e7005 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/time/time.h" #include 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 374527555c..cbe7526a97 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // `Time` represents an absolute point in coordinated universal time (UTC), // internally represented as microseconds (s/1,000,000) since the Windows epoch // (1601-01-01 00:00:00 UTC). System-dependent clock interface routines are diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_apple.mm b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_apple.mm index 989adb8370..ee2c8de171 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_apple.mm +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_apple.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/time/time.h" #import diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_conversion_posix.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_conversion_posix.cc index 1039869ad0..38bed1da65 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_conversion_posix.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_conversion_posix.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_fuchsia.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_fuchsia.cc index 475b49d627..c32311ef1e 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_fuchsia.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_fuchsia.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/time/time.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_now_posix.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_now_posix.cc index 04d5b32460..eb0acc4fa1 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_now_posix.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_now_posix.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_override.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_override.cc index b1c4c925a3..5a4fc856e4 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_override.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_override.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_base/time/time_override.h" #include "partition_alloc/partition_alloc_base/check.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_override.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_override.h index adff6be6a7..f3777ceed1 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_override.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_override.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_TIME_TIME_OVERRIDE_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_TIME_TIME_OVERRIDE_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_win.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_win.cc index b68e825b23..8a896bc5b7 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_win.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time_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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // Windows Timer Primer // // A good article: http://www.ddj.com/windows/184416651 @@ -422,7 +427,8 @@ ThreadTicks ThreadTicks::GetForThread( ::GetThreadTimes(thread_handle.platform_handle(), &creation_time, &exit_time, &kernel_time, &user_time); - const int64_t us = FileTimeToMicroseconds(user_time); + const int64_t us = + FileTimeToMicroseconds(user_time) + FileTimeToMicroseconds(kernel_time); #else // Get the number of TSC ticks used by the current thread. ULONG64 thread_cycle_time = 0; diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/types/same_as_any.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/types/same_as_any.h index bed3cf34ce..4cc8b23b02 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/types/same_as_any.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/types/same_as_any.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_TYPES_SAME_AS_ANY_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_TYPES_SAME_AS_ANY_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/types/strong_alias.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/types/strong_alias.h index 68703b7881..7046f43bf9 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/types/strong_alias.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/types/strong_alias.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_TYPES_STRONG_ALIAS_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_TYPES_STRONG_ALIAS_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/win/win_handle_types.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/win/win_handle_types.h index 733aec162e..ca93f6ba96 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/win/win_handle_types.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/win/win_handle_types.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_WIN_WIN_HANDLE_TYPES_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_WIN_WIN_HANDLE_TYPES_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/win/win_handle_types_list.inc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/win/win_handle_types_list.inc index 8d730ff2ac..322ffc67cf 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/win/win_handle_types_list.inc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/win/win_handle_types_list.inc @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // This file intentionally does not have header guards, it's included // inside a macro to generate enum values. The following line silences a // presubmit and Tricium warning that would otherwise be triggered by this: diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/win/windows_handle_util.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/win/windows_handle_util.h index 0f87eb4973..d2eef4a204 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/win/windows_handle_util.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/win/windows_handle_util.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_WIN_WINDOWS_HANDLE_UTIL_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_WIN_WINDOWS_HANDLE_UTIL_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/win/windows_types.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/win/windows_types.h index 649a3b74e5..2d86cde458 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/win/windows_types.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/win/windows_types.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // This file contains defines and typedefs that allow popular Windows types to // be used without the overhead of including windows.h. 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 index 4225e0f273..f6f59debbe 100644 --- 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 @@ -1,6 +1,11 @@ // 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. + +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BUILDFLAGS_H_ #define 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 8156baca1b..3377e757f2 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_CHECK_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_CHECK_H_ 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 d5a316f64d..07565170b9 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_CONFIG_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_CONFIG_H_ @@ -166,24 +171,18 @@ constexpr bool kUseLazyCommit = false; (PA_BUILDFLAG(IS_APPLE) || PA_BUILDFLAG(IS_LINUX) || \ PA_BUILDFLAG(IS_CHROMEOS)) -// Enable shadow metadata. -// -// With this flag, shadow pools will be mapped, on which writable shadow -// metadatas are placed, and the real metadatas are set to read-only instead. -// This feature is only enabled with 64-bit environment because pools work -// differently with 32-bits pointers (see glossary). -#if PA_BUILDFLAG(ENABLE_SHADOW_METADATA_FOR_64_BITS_POINTERS) && \ +#if PA_BUILDFLAG(MOVE_METADATA_OUT_OF_GIGACAGE_FOR_64_BITS_POINTERS) && \ PA_BUILDFLAG(HAS_64_BIT_POINTERS) -#define PA_CONFIG_ENABLE_SHADOW_METADATA() 1 +#define PA_CONFIG_MOVE_METADATA_OUT_OF_GIGACAGE() 1 #else -#define PA_CONFIG_ENABLE_SHADOW_METADATA() 0 +#define PA_CONFIG_MOVE_METADATA_OUT_OF_GIGACAGE() 0 #endif // PartitionAlloc uses PartitionRootEnumerator to acquire all // PartitionRoots at BeforeFork and to release at AfterFork. -#if (PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \ - PA_CONFIG(HAS_ATFORK_HANDLER)) || \ - PA_CONFIG(ENABLE_SHADOW_METADATA) +#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \ + PA_CONFIG(HAS_ATFORK_HANDLER) || \ + PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) #define PA_CONFIG_USE_PARTITION_ROOT_ENUMERATOR() 1 #else #define PA_CONFIG_USE_PARTITION_ROOT_ENUMERATOR() 0 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 bd17e1e260..7f33bd5506 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_CONSTANTS_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_CONSTANTS_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_for_testing.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_for_testing.h index 49773244e2..fecc9f912f 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_for_testing.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_for_testing.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_FOR_TESTING_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_FOR_TESTING_H_ 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 6df970f966..e7d9b682ce 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_FORWARD_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_FORWARD_H_ @@ -58,17 +63,6 @@ template static constexpr bool is_offset_type = std::is_integral_v && sizeof(Z) <= sizeof(ptrdiff_t); -enum class MetadataKind { kWritable, kReadOnly }; - -template -struct MaybeConst { - using Type = std::conditional_t; -}; - -template -using MaybeConstT = typename MaybeConst::Type; - -template struct SlotSpanMetadata; } // namespace internal diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_hooks.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_hooks.cc index 209ac54729..8fbce59af7 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_hooks.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_hooks.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_alloc_hooks.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_hooks.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_hooks.h index 12176edf72..f7cbbc55c5 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_hooks.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_hooks.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ALLOC_HOOKS_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_HOOKS_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 80a353d27e..5850222b57 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_bucket.h" #include @@ -173,11 +178,10 @@ uintptr_t ReserveMemoryFromPool(pool_handle pool, return reserved_address; } -SlotSpanMetadata* PartitionDirectMap( - PartitionRoot* root, - AllocFlags flags, - size_t raw_size, - size_t slot_span_alignment) { +SlotSpanMetadata* PartitionDirectMap(PartitionRoot* root, + AllocFlags flags, + size_t raw_size, + size_t slot_span_alignment) { PA_DCHECK((slot_span_alignment >= PartitionPageSize()) && base::bits::HasSingleBit(slot_span_alignment)); @@ -215,24 +219,10 @@ SlotSpanMetadata* PartitionDirectMap( PartitionExcessiveAllocationSize(raw_size); } - PartitionDirectMapExtent* map_extent = nullptr; - PartitionDirectMapExtent* writable_map_extent = - nullptr; - PartitionPageMetadata* page_metadata = nullptr; + PartitionDirectMapExtent* map_extent = nullptr; + PartitionPageMetadata* page_metadata = nullptr; { -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - // Because of the performance reason, PartitionRoot's lock is unlocked - // here. However this causes multi-thread issue when running - // EnableShadowMetadata(). If some thread is running PartitionDirectMap() - // and unlock PartitionRoot lock and also another thread is running - // EnableShadowMetadata(), the metadata page's permission will be modified - // by both threads and chrome will crash. c.f. crbug.com/378809882 - // Be careful. This should not block PartitionDirectMap() in another thread. - internal::SharedLock shared_lock( - PartitionRoot::g_shadow_metadata_init_mutex_); -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) - // Getting memory for direct-mapped allocations doesn't interact with the // rest of the allocator, but takes a long time, as it involves several // system calls. Although no mmap() (or equivalent) calls are made on @@ -294,21 +284,14 @@ SlotSpanMetadata* PartitionDirectMap( const uintptr_t slot_start = reservation_start + PartitionPageSize() + padding_for_alignment; + uintptr_t metadata_start = PartitionSuperPageToMetadataPage( + reservation_start, root->MetadataOffset()); { ScopedSyscallTimer timer{root}; -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - if (PartitionAddressSpace::IsShadowMetadataEnabled(root->ChoosePool())) { - PartitionAddressSpace::MapMetadata(reservation_start, - /*copy_metadata=*/false); - } else -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) - { - RecommitSystemPages(reservation_start + SystemPageSize(), - SystemPageSize(), - root->PageAccessibilityWithThreadIsolationIfEnabled( - PageAccessibilityConfiguration::kReadWrite), - PageAccessibilityDisposition::kRequireUpdate); - } + RecommitSystemPages(metadata_start, SystemPageSize(), + root->PageAccessibilityWithThreadIsolationIfEnabled( + PageAccessibilityConfiguration::kReadWrite), + PageAccessibilityDisposition::kRequireUpdate); } if (pool == kBRPPoolHandle) { @@ -333,68 +316,54 @@ SlotSpanMetadata* PartitionDirectMap( root->GetReservationOffsetTable().SetDirectMapReservationStart( reservation_start, reservation_size); - auto* super_page_extent = PartitionSuperPageToExtent(reservation_start); - auto* writable_super_page_extent = super_page_extent->ToWritable(root); - writable_super_page_extent->root = root; + auto* super_page_extent = + PartitionSuperPageToExtent(reservation_start, root); + super_page_extent->root = root; // The new structures are all located inside a fresh system page so they // will all be zeroed out. These DCHECKs are for documentation and to assert // our expectations of the kernel. PA_DCHECK(!super_page_extent->number_of_consecutive_super_pages); PA_DCHECK(!super_page_extent->next); - PartitionPageMetadata* first_page_metadata = - reinterpret_cast*>( - writable_super_page_extent) + - 1; - page_metadata = - PartitionPageMetadata::FromAddr(slot_start); - PartitionPageMetadata* writable_page_metadata = - page_metadata->ToWritable(root); - // |first_page_metadata| and |writable_page_metadata| may be equal, if there - // is no alignment padding. - if (writable_page_metadata != first_page_metadata) { - PA_DCHECK(writable_page_metadata > first_page_metadata); - PA_DCHECK(writable_page_metadata - first_page_metadata <= - PartitionPageMetadata< - MetadataKind::kReadOnly>::kMaxSlotSpanMetadataOffset); + PartitionPageMetadata* first_page_metadata = + reinterpret_cast(super_page_extent) + 1; + page_metadata = PartitionPageMetadata::FromAddr(slot_start, root); + // |first_page_metadata| and |page_metadata| may be equal, if there is no + // alignment padding. + if (page_metadata != first_page_metadata) { + PA_DCHECK(page_metadata > first_page_metadata); + PA_DCHECK(page_metadata - first_page_metadata <= + PartitionPageMetadata::kMaxSlotSpanMetadataOffset); PA_CHECK(!first_page_metadata->is_valid); first_page_metadata->has_valid_span_after_this = true; first_page_metadata->slot_span_metadata_offset = - writable_page_metadata - first_page_metadata; + page_metadata - first_page_metadata; } auto* direct_map_metadata = - reinterpret_cast*>( - page_metadata); - auto* writable_direct_map_metadata = - reinterpret_cast*>( - writable_page_metadata); + reinterpret_cast(page_metadata); // Since direct map metadata is larger than PartitionPageMetadata, make sure // the first and the last bytes are on the same system page, i.e. within the // super page metadata region. PA_DCHECK( base::bits::AlignDown(reinterpret_cast(direct_map_metadata), SystemPageSize()) == - base::bits::AlignDown( - reinterpret_cast(direct_map_metadata) + - sizeof(PartitionDirectMapMetadata) - 1, - SystemPageSize())); - PA_DCHECK(writable_page_metadata == - &writable_direct_map_metadata->page_metadata); - writable_page_metadata->is_valid = true; - PA_DCHECK(!writable_page_metadata->has_valid_span_after_this); - PA_DCHECK(!writable_page_metadata->slot_span_metadata_offset); - PA_DCHECK(!writable_page_metadata->slot_span_metadata.next_slot_span); - PA_DCHECK(!writable_page_metadata->slot_span_metadata.marked_full); - PA_DCHECK(!writable_page_metadata->slot_span_metadata.num_allocated_slots); - PA_DCHECK( - !writable_page_metadata->slot_span_metadata.num_unprovisioned_slots); - PA_DCHECK(!writable_page_metadata->slot_span_metadata.in_empty_cache()); + base::bits::AlignDown(reinterpret_cast(direct_map_metadata) + + sizeof(PartitionDirectMapMetadata) - 1, + SystemPageSize())); + PA_DCHECK(page_metadata == &direct_map_metadata->page_metadata); + page_metadata->is_valid = true; + PA_DCHECK(!page_metadata->has_valid_span_after_this); + PA_DCHECK(!page_metadata->slot_span_metadata_offset); + PA_DCHECK(!page_metadata->slot_span_metadata.next_slot_span); + PA_DCHECK(!page_metadata->slot_span_metadata.marked_full); + PA_DCHECK(!page_metadata->slot_span_metadata.num_allocated_slots); + PA_DCHECK(!page_metadata->slot_span_metadata.num_unprovisioned_slots); + PA_DCHECK(!page_metadata->slot_span_metadata.in_empty_cache()); PA_DCHECK(!direct_map_metadata->second_page_metadata .subsequent_page_metadata.raw_size); // Raw size is set later, by the caller. - writable_direct_map_metadata->second_page_metadata - .slot_span_metadata_offset = 1; + direct_map_metadata->second_page_metadata.slot_span_metadata_offset = 1; PA_DCHECK(!direct_map_metadata->bucket.active_slot_spans_head); PA_DCHECK(!direct_map_metadata->bucket.empty_slot_spans_head); @@ -402,13 +371,11 @@ SlotSpanMetadata* PartitionDirectMap( PA_DCHECK(!direct_map_metadata->bucket.num_system_pages_per_slot_span); PA_DCHECK(!direct_map_metadata->bucket.num_full_slot_spans); - writable_direct_map_metadata->bucket.slot_size = slot_size; - writable_direct_map_metadata->bucket.can_store_raw_size = true; + direct_map_metadata->bucket.slot_size = slot_size; + direct_map_metadata->bucket.can_store_raw_size = true; - // SlotSpanMetadata must point to the bucket inside the giga cage. - new (&writable_page_metadata->slot_span_metadata) - SlotSpanMetadata( - const_cast(&direct_map_metadata->bucket)); + new (&page_metadata->slot_span_metadata) + SlotSpanMetadata(&direct_map_metadata->bucket); // It is typically possible to map a large range of inaccessible pages, and // this is leveraged in multiple places, including the pools. However, @@ -449,25 +416,22 @@ SlotSpanMetadata* PartitionDirectMap( auto* next_entry = FreelistEntry::EmplaceAndInitNull(slot_start); - writable_page_metadata->slot_span_metadata.SetFreelistHead(next_entry, - root); + page_metadata->slot_span_metadata.SetFreelistHead(next_entry); - writable_map_extent = &writable_direct_map_metadata->direct_map_extent; - writable_map_extent->reservation_size = reservation_size; - writable_map_extent->padding_for_alignment = padding_for_alignment; - // Point to read-only bucket. - writable_map_extent->bucket = &direct_map_metadata->bucket; map_extent = &direct_map_metadata->direct_map_extent; + map_extent->reservation_size = reservation_size; + map_extent->padding_for_alignment = padding_for_alignment; + map_extent->bucket = &direct_map_metadata->bucket; } PartitionRootLock(root).AssertAcquired(); // Maintain the doubly-linked list of all direct mappings. - writable_map_extent->next_extent = root->direct_map_list; + map_extent->next_extent = root->direct_map_list; if (map_extent->next_extent) { - map_extent->next_extent->ToWritable(root)->prev_extent = map_extent; + map_extent->next_extent->prev_extent = map_extent; } - writable_map_extent->prev_extent = nullptr; + map_extent->prev_extent = nullptr; root->direct_map_list = map_extent; return &page_metadata->slot_span_metadata; @@ -608,8 +572,7 @@ uint8_t ComputeSystemPagesPerSlotSpan(size_t slot_size, void PartitionBucket::Init(uint32_t new_slot_size) { slot_size = new_slot_size; slot_size_reciprocal = kReciprocalMask / new_slot_size + 1; - active_slot_spans_head = SlotSpanMetadata< - MetadataKind::kReadOnly>::get_sentinel_slot_span_non_const(); + active_slot_spans_head = SlotSpanMetadata::get_sentinel_slot_span_non_const(); empty_slot_spans_head = nullptr; decommitted_slot_spans_head = nullptr; num_full_slot_spans = 0; @@ -627,10 +590,10 @@ void PartitionBucket::Init(uint32_t new_slot_size) { InitCanStoreRawSize(); } -PA_ALWAYS_INLINE SlotSpanMetadata* -PartitionBucket::AllocNewSlotSpan(PartitionRoot* root, - AllocFlags flags, - size_t slot_span_alignment) { +PA_ALWAYS_INLINE SlotSpanMetadata* PartitionBucket::AllocNewSlotSpan( + PartitionRoot* root, + AllocFlags flags, + size_t slot_span_alignment) { PA_DCHECK(!(root->next_partition_page % PartitionPageSize())); PA_DCHECK(!(root->next_partition_page_end % PartitionPageSize())); @@ -664,12 +627,10 @@ PartitionBucket::AllocNewSlotSpan(PartitionRoot* root, } auto* gap_start_page = - PartitionPageMetadata::FromAddr( - root->next_partition_page); - auto* gap_end_page = PartitionPageMetadata::FromAddr( - adjusted_next_partition_page); - for (auto* page = gap_start_page->ToWritable(root); - page < gap_end_page->ToWritable(root); ++page) { + PartitionPageMetadata::FromAddr(root->next_partition_page, root); + auto* gap_end_page = + PartitionPageMetadata::FromAddr(adjusted_next_partition_page, root); + for (auto* page = gap_start_page; page < gap_end_page; ++page) { PA_DCHECK(!page->is_valid); page->has_valid_span_after_this = true; } @@ -678,12 +639,10 @@ PartitionBucket::AllocNewSlotSpan(PartitionRoot* root, uintptr_t slot_span_start = adjusted_next_partition_page; auto* slot_span = &gap_end_page->slot_span_metadata; - InitializeSlotSpan(slot_span, root); - + InitializeSlotSpan(slot_span); // Now that slot span is initialized, it's safe to call FromSlotStart. PA_DCHECK(slot_span == - SlotSpanMetadata::FromSlotStart( - slot_span_start)); + SlotSpanMetadata::FromSlotStart(slot_span_start, root)); // System pages in the super page come in a decommited state. Commit them // before vending them back. @@ -817,22 +776,17 @@ PartitionBucket::InitializeSuperPage(PartitionRoot* root, PA_DCHECK(payload == SuperPagePayloadBegin(super_page)); PA_DCHECK(root->next_partition_page_end == SuperPagePayloadEnd(super_page)); + uintptr_t metadata_start = + PartitionSuperPageToMetadataPage(super_page, root->MetadataOffset()); // Keep the first partition page in the super page inaccessible to serve as a // guard page, except an "island" in the middle where we put page metadata and // also a tiny amount of extent metadata. { ScopedSyscallTimer timer{root}; -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - if (PartitionAddressSpace::IsShadowMetadataEnabled(root->ChoosePool())) { - PartitionAddressSpace::MapMetadata(super_page, /*copy_metadata=*/false); - } else -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) - { - RecommitSystemPages(super_page + SystemPageSize(), SystemPageSize(), - root->PageAccessibilityWithThreadIsolationIfEnabled( - PageAccessibilityConfiguration::kReadWrite), - PageAccessibilityDisposition::kRequireUpdate); - } + RecommitSystemPages(metadata_start, SystemPageSize(), + root->PageAccessibilityWithThreadIsolationIfEnabled( + PageAccessibilityConfiguration::kReadWrite), + PageAccessibilityDisposition::kRequireUpdate); } #if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) @@ -862,27 +816,22 @@ PartitionBucket::InitializeSuperPage(PartitionRoot* root, // We allocated a new super page so update super page metadata. // First check if this is a new extent or not. - auto* latest_extent = PartitionSuperPageToExtent(super_page); - auto* writable_latest_extent = latest_extent->ToWritable(root); -#if PA_BUILDFLAG(DCHECKS_ARE_ON) - PA_DCHECK(writable_latest_extent->ToReadOnly(root) == latest_extent); -#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) + auto* latest_extent = + PartitionSuperPageToExtent(super_page, root->MetadataOffset()); // By storing the root in every extent metadata object, we have a fast way // to go from a pointer within the partition to the root object. - writable_latest_extent->root = root; + latest_extent->root = root; #if PA_BUILDFLAG(DCHECKS_ARE_ON) - PA_DCHECK(writable_latest_extent->root == root); PA_DCHECK(latest_extent->root == root); #endif // PA_BUILDFLAG(DCHECKS_ARE_ON) // Most new extents will be part of a larger extent, and these two fields // are unused, but we initialize them to 0 so that we get a clear signal // in case they are accidentally used. - writable_latest_extent->number_of_consecutive_super_pages = 0; - writable_latest_extent->next = nullptr; - writable_latest_extent->number_of_nonempty_slot_spans = 0; + latest_extent->number_of_consecutive_super_pages = 0; + latest_extent->next = nullptr; + latest_extent->number_of_nonempty_slot_spans = 0; - PartitionSuperPageExtentEntry* current_extent = - root->current_extent; + PartitionSuperPageExtentEntry* current_extent = root->current_extent; const bool is_new_extent = super_page != requested_address; if (is_new_extent) [[unlikely]] { if (!current_extent) [[unlikely]] { @@ -890,15 +839,15 @@ PartitionBucket::InitializeSuperPage(PartitionRoot* root, root->first_extent = latest_extent; } else { PA_DCHECK(current_extent->number_of_consecutive_super_pages); - current_extent->ToWritable(root)->next = latest_extent; + current_extent->next = latest_extent; } root->current_extent = latest_extent; - writable_latest_extent->number_of_consecutive_super_pages = 1; + latest_extent->number_of_consecutive_super_pages = 1; } else { // We allocated next to an existing extent so just nudge the size up a // little. PA_DCHECK(current_extent->number_of_consecutive_super_pages); - ++current_extent->ToWritable(root)->number_of_consecutive_super_pages; + ++current_extent->number_of_consecutive_super_pages; PA_DCHECK(payload > SuperPagesBeginFromExtent(current_extent) && payload < SuperPagesEndFromExtent(current_extent)); } @@ -907,36 +856,25 @@ PartitionBucket::InitializeSuperPage(PartitionRoot* root, } PA_ALWAYS_INLINE void PartitionBucket::InitializeSlotSpan( - SlotSpanMetadata* slot_span, - PartitionRoot* root) { - SlotSpanMetadata* writable_slot_span = - slot_span->ToWritable(root); - new (writable_slot_span) SlotSpanMetadata(this); + SlotSpanMetadata* slot_span) { + new (slot_span) SlotSpanMetadata(this); - writable_slot_span->Reset(); + slot_span->Reset(); uint16_t num_partition_pages = get_pages_per_slot_span(); - auto* page_metadata = - reinterpret_cast*>( - writable_slot_span); + auto* page_metadata = reinterpret_cast(slot_span); for (uint16_t i = 0; i < num_partition_pages; ++i, ++page_metadata) { - PA_DCHECK(i <= PartitionPageMetadata< - MetadataKind::kReadOnly>::kMaxSlotSpanMetadataOffset); + PA_DCHECK(i <= PartitionPageMetadata::kMaxSlotSpanMetadataOffset); page_metadata->slot_span_metadata_offset = i; page_metadata->is_valid = true; } -#if PA_CONFIG(ENABLE_SHADOW_METADATA) && PA_BUILDFLAG(DCHECKS_ARE_ON) - PA_DCHECK(slot_span->bucket == this); -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) && PA_BUILDFLAG(DCHECKS_ARE_ON) } -PA_ALWAYS_INLINE uintptr_t PartitionBucket::ProvisionMoreSlotsAndAllocOne( - PartitionRoot* root, - AllocFlags flags, - SlotSpanMetadata* slot_span) { - PA_DCHECK( - slot_span != - SlotSpanMetadata::get_sentinel_slot_span()); +PA_ALWAYS_INLINE uintptr_t +PartitionBucket::ProvisionMoreSlotsAndAllocOne(PartitionRoot* root, + AllocFlags flags, + SlotSpanMetadata* slot_span) { + PA_DCHECK(slot_span != SlotSpanMetadata::get_sentinel_slot_span()); size_t num_slots = slot_span->num_unprovisioned_slots; PA_DCHECK(num_slots); PA_DCHECK(num_slots <= get_slots_per_span()); @@ -949,7 +887,7 @@ PA_ALWAYS_INLINE uintptr_t PartitionBucket::ProvisionMoreSlotsAndAllocOne( PA_DCHECK(!slot_span->is_full()); uintptr_t slot_span_start = - SlotSpanMetadata::ToSlotSpanStart(slot_span); + SlotSpanMetadata::ToSlotSpanStart(slot_span, root); // If we got here, the first unallocated slot is either partially or fully on // an uncommitted page. If the latter, it must be at the start of that page. uintptr_t return_slot = @@ -983,14 +921,12 @@ PA_ALWAYS_INLINE uintptr_t PartitionBucket::ProvisionMoreSlotsAndAllocOne( } } - SlotSpanMetadata* writable_slot_span = - slot_span->ToWritable(root); // The slot being returned is considered allocated. - writable_slot_span->num_allocated_slots++; + slot_span->num_allocated_slots++; // Round down, because a slot that doesn't fully fit in the new page(s) isn't // provisioned. size_t slots_to_provision = (commit_end - return_slot) / slot_size; - writable_slot_span->num_unprovisioned_slots -= slots_to_provision; + slot_span->num_unprovisioned_slots -= slots_to_provision; PA_DCHECK(slot_span->num_allocated_slots + slot_span->num_unprovisioned_slots <= get_slots_per_span()); @@ -1029,7 +965,7 @@ PA_ALWAYS_INLINE uintptr_t PartitionBucket::ProvisionMoreSlotsAndAllocOne( if (!slot_span->get_freelist_head()) { PA_DCHECK(!prev_entry); PA_DCHECK(!free_list_entries_added); - writable_slot_span->SetFreelistHead(entry, root); + slot_span->SetFreelistHead(entry); } else { PA_DCHECK(free_list_entries_added); prev_entry->SetNext(entry); @@ -1055,19 +991,18 @@ PA_ALWAYS_INLINE uintptr_t PartitionBucket::ProvisionMoreSlotsAndAllocOne( #endif // We had no free slots, and created some (potentially 0) in sorted order. - writable_slot_span->set_freelist_sorted(); + slot_span->set_freelist_sorted(); return return_slot; } -bool PartitionBucket::SetNewActiveSlotSpan(PartitionRoot* root) { - SlotSpanMetadata* slot_span = active_slot_spans_head; - if (slot_span == - SlotSpanMetadata::get_sentinel_slot_span()) { +bool PartitionBucket::SetNewActiveSlotSpan() { + SlotSpanMetadata* slot_span = active_slot_spans_head; + if (slot_span == SlotSpanMetadata::get_sentinel_slot_span()) { return false; } - SlotSpanMetadata* next_slot_span; + SlotSpanMetadata* next_slot_span; // The goal here is to find a suitable slot span in the active list. Suitable // slot spans are |is_active()|, i.e. they either have (a) freelist entries, @@ -1099,8 +1034,8 @@ bool PartitionBucket::SetNewActiveSlotSpan(PartitionRoot* root) { // Note that in most cases, the whole list will not be walked and maintained // at this stage. - SlotSpanMetadata* to_provision_head = nullptr; - SlotSpanMetadata* to_provision_tail = nullptr; + SlotSpanMetadata* to_provision_head = nullptr; + SlotSpanMetadata* to_provision_tail = nullptr; for (; slot_span; slot_span = next_slot_span) { next_slot_span = slot_span->next_slot_span; @@ -1119,30 +1054,30 @@ bool PartitionBucket::SetNewActiveSlotSpan(PartitionRoot* root) { to_provision_head = slot_span; } if (to_provision_tail) { - to_provision_tail->ToWritable(root)->next_slot_span = slot_span; + to_provision_tail->next_slot_span = slot_span; } to_provision_tail = slot_span; - slot_span->ToWritable(root)->next_slot_span = nullptr; + slot_span->next_slot_span = nullptr; } } else if (slot_span->is_empty()) { - slot_span->ToWritable(root)->next_slot_span = empty_slot_spans_head; + slot_span->next_slot_span = empty_slot_spans_head; empty_slot_spans_head = slot_span; } else if (slot_span->is_decommitted()) [[likely]] { - slot_span->ToWritable(root)->next_slot_span = decommitted_slot_spans_head; + slot_span->next_slot_span = decommitted_slot_spans_head; decommitted_slot_spans_head = slot_span; } else { PA_DCHECK(slot_span->is_full()); // Move this slot span... nowhere, and also mark it as full. We need it // marked so that free'ing can tell, and move it back into the active // list. - slot_span->ToWritable(root)->marked_full = 1; + slot_span->marked_full = 1; ++num_full_slot_spans; // Overflow. Most likely a correctness issue in the code. It is in theory // possible that the number of full slot spans really reaches (1 << 24), // but this is very unlikely (and not possible with most pool settings). PA_CHECK(num_full_slot_spans); // Not necessary but might help stop accidents. - slot_span->ToWritable(root)->next_slot_span = nullptr; + slot_span->next_slot_span = nullptr; } } @@ -1154,8 +1089,8 @@ bool PartitionBucket::SetNewActiveSlotSpan(PartitionRoot* root) { // the active list, past the span with freelist entries. if (to_provision_head) { auto* next = slot_span->next_slot_span; - slot_span->ToWritable(root)->next_slot_span = to_provision_head; - to_provision_tail->ToWritable(root)->next_slot_span = next; + slot_span->next_slot_span = to_provision_head; + to_provision_tail->next_slot_span = next; } active_slot_spans_head = slot_span; } else if (to_provision_head) { @@ -1164,26 +1099,23 @@ bool PartitionBucket::SetNewActiveSlotSpan(PartitionRoot* root) { active_slot_spans_head = to_provision_head; } else { // Active list is now empty. - active_slot_spans_head = SlotSpanMetadata< - MetadataKind::kReadOnly>::get_sentinel_slot_span_non_const(); + active_slot_spans_head = + SlotSpanMetadata::get_sentinel_slot_span_non_const(); } return usable_active_list_head; } -void PartitionBucket::MaintainActiveList(PartitionRoot* root) { - SlotSpanMetadata* slot_span = active_slot_spans_head; - if (slot_span == - SlotSpanMetadata::get_sentinel_slot_span()) { +void PartitionBucket::MaintainActiveList() { + SlotSpanMetadata* slot_span = active_slot_spans_head; + if (slot_span == SlotSpanMetadata::get_sentinel_slot_span()) { return; } - SlotSpanMetadata* new_active_slot_spans_head = - nullptr; - SlotSpanMetadata* new_active_slot_spans_tail = - nullptr; + SlotSpanMetadata* new_active_slot_spans_head = nullptr; + SlotSpanMetadata* new_active_slot_spans_tail = nullptr; - SlotSpanMetadata* next_slot_span; + SlotSpanMetadata* next_slot_span; for (; slot_span; slot_span = next_slot_span) { next_slot_span = slot_span->next_slot_span; @@ -1193,46 +1125,38 @@ void PartitionBucket::MaintainActiveList(PartitionRoot* root) { new_active_slot_spans_head = slot_span; } if (new_active_slot_spans_tail) { - new_active_slot_spans_tail->ToWritable(root)->next_slot_span = - slot_span; + new_active_slot_spans_tail->next_slot_span = slot_span; } new_active_slot_spans_tail = slot_span; - slot_span->ToWritable(root)->next_slot_span = nullptr; + slot_span->next_slot_span = nullptr; } else if (slot_span->is_empty()) { // For the empty and decommitted lists, LIFO ordering makes sense (since // it would lead to reusing memory which has been touched relatively // recently, which only matters for committed spans though). - slot_span->ToWritable(root)->next_slot_span = empty_slot_spans_head; + slot_span->next_slot_span = empty_slot_spans_head; empty_slot_spans_head = slot_span; } else if (slot_span->is_decommitted()) { - slot_span->ToWritable(root)->next_slot_span = decommitted_slot_spans_head; + slot_span->next_slot_span = decommitted_slot_spans_head; decommitted_slot_spans_head = slot_span; } else { // Full slot spans are not tracked, just accounted for. PA_DCHECK(slot_span->is_full()); - slot_span->ToWritable(root)->marked_full = 1; + slot_span->marked_full = 1; ++num_full_slot_spans; PA_CHECK(num_full_slot_spans); // Overflow. - slot_span->ToWritable(root)->next_slot_span = nullptr; + slot_span->next_slot_span = nullptr; } } if (!new_active_slot_spans_head) { - new_active_slot_spans_head = SlotSpanMetadata< - MetadataKind::kReadOnly>::get_sentinel_slot_span_non_const(); + new_active_slot_spans_head = + SlotSpanMetadata::get_sentinel_slot_span_non_const(); } active_slot_spans_head = new_active_slot_spans_head; -#if PA_CONFIG(ENABLE_SHADOW_METADATA) && PA_BUILDFLAG(DCHECKS_ARE_ON) - // If ShadowMetadata is enabled, `active_slot_spans_heads` must not point - // to a writable SlotSpanMetadata. Instead, it points to a sentinel - // SlotSpanMetadata or a readonly SlotSpanMetadata (inside the gigacage). - PA_DCHECK( - !PartitionAddressSpace::IsShadowMetadataEnabled(root->ChoosePool()) || - !PartitionAddressSpace::IsInPoolShadow(active_slot_spans_head)); -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) && PA_BUILDFLAG(DCHECKS_ARE_ON) } -void PartitionBucket::SortSmallerSlotSpanFreeLists(PartitionRoot* root) { +void PartitionBucket::SortSmallerSlotSpanFreeLists( + [[maybe_unused]] const PartitionRoot* root) { for (auto* slot_span = active_slot_spans_head; slot_span; slot_span = slot_span->next_slot_span) { // No need to sort the freelist if it's already sorted. Note that if the @@ -1244,15 +1168,14 @@ void PartitionBucket::SortSmallerSlotSpanFreeLists(PartitionRoot* root) { // spans, which may required paging. if (slot_span->num_allocated_slots > 0 && !slot_span->freelist_is_sorted()) { - slot_span->ToWritable(root)->SortFreelist(root); + slot_span->SortFreelist(root); } } } PA_COMPONENT_EXPORT(PARTITION_ALLOC) -bool CompareSlotSpans(const SlotSpanMetadata* a, - const SlotSpanMetadata* b) { - auto criteria_tuple = [](SlotSpanMetadata const* a) { +bool CompareSlotSpans(const SlotSpanMetadata* a, const SlotSpanMetadata* b) { + auto criteria_tuple = [](SlotSpanMetadata const* a) { size_t freelist_length = a->GetFreelistLength(); // The criteria are, in order (hence the lexicographic comparison below): // 1. Prefer slot spans with freelist entries. The ones without freelist @@ -1279,17 +1202,16 @@ bool CompareSlotSpans(const SlotSpanMetadata* a, return criteria_tuple(a) < criteria_tuple(b); } -void PartitionBucket::SortActiveSlotSpans(PartitionRoot* root) { +void PartitionBucket::SortActiveSlotSpans() { // Sorting up to |kMaxSlotSpansToSort| slot spans. This is capped for two // reasons: // - Limiting execution time // - Current code cannot allocate. // // In practice though, it's rare to have that many active slot spans. - SlotSpanMetadata* - active_spans_array[kMaxSlotSpansToSort]; + SlotSpanMetadata* active_spans_array[kMaxSlotSpansToSort]; size_t index = 0; - SlotSpanMetadata* overflow_spans_start = nullptr; + SlotSpanMetadata* overflow_spans_start = nullptr; for (auto* slot_span = active_slot_spans_head; slot_span; slot_span = slot_span->next_slot_span) { @@ -1327,25 +1249,22 @@ void PartitionBucket::SortActiveSlotSpans(PartitionRoot* root) { // Reverse order, since we insert at the head of the list. for (int i = index - 1; i >= 0; i--) { - if (active_spans_array[i] == - SlotSpanMetadata::get_sentinel_slot_span()) { + if (active_spans_array[i] == SlotSpanMetadata::get_sentinel_slot_span()) { // The sentinel is const, don't try to write to it. PA_DCHECK(active_slot_spans_head == nullptr); } else { - active_spans_array[i]->ToWritable(root)->next_slot_span = - active_slot_spans_head; + active_spans_array[i]->next_slot_span = active_slot_spans_head; } active_slot_spans_head = active_spans_array[i]; } } -uintptr_t PartitionBucket::SlowPathAlloc( - PartitionRoot* root, - AllocFlags flags, - size_t raw_size, - size_t slot_span_alignment, - SlotSpanMetadata** slot_span, - bool* is_already_zeroed) { +uintptr_t PartitionBucket::SlowPathAlloc(PartitionRoot* root, + AllocFlags flags, + size_t raw_size, + size_t slot_span_alignment, + SlotSpanMetadata** slot_span, + bool* is_already_zeroed) { PA_DCHECK((slot_span_alignment >= PartitionPageSize()) && base::bits::HasSingleBit(slot_span_alignment)); @@ -1356,7 +1275,7 @@ uintptr_t PartitionBucket::SlowPathAlloc( PA_DCHECK(!active_slot_spans_head->get_freelist_head() || allocate_aligned_slot_span); - SlotSpanMetadata* new_slot_span = nullptr; + SlotSpanMetadata* new_slot_span = nullptr; // |new_slot_span->bucket| will always be |this|, except when |this| is the // sentinel bucket, which is used to signal a direct mapped allocation. In // this case |new_bucket| will be set properly later. This avoids a read for @@ -1376,9 +1295,8 @@ uintptr_t PartitionBucket::SlowPathAlloc( if (is_direct_mapped()) [[unlikely]] { PA_DCHECK(raw_size > BucketIndexLookup::kMaxBucketSize); PA_DCHECK(this == &root->sentinel_bucket); - PA_DCHECK( - active_slot_spans_head == - SlotSpanMetadata::get_sentinel_slot_span()); + PA_DCHECK(active_slot_spans_head == + SlotSpanMetadata::get_sentinel_slot_span()); // No fast path for direct-mapped allocations. if (ContainsFlags(flags, AllocFlags::kFastPathOrReturnNull)) { @@ -1388,27 +1306,11 @@ uintptr_t PartitionBucket::SlowPathAlloc( new_slot_span = PartitionDirectMap(root, flags, raw_size, slot_span_alignment); if (new_slot_span) { -#if !PA_CONFIG(ENABLE_SHADOW_METADATA) new_bucket = new_slot_span->bucket; -#else - // |new_slot_span| must be in the giga cage. - PA_DCHECK(IsManagedByPartitionAlloc( - reinterpret_cast(new_slot_span))); - // |new_slot_span->bucket| must point to a bucket inside the giga cage, - // because the new slotspan is in the giga cage. - PA_DCHECK(IsManagedByPartitionAlloc( - reinterpret_cast(new_slot_span->bucket))); - // To make the writable PartitionBucket, need to apply - // |root->ShadowPoolOffset()|. - new_bucket = reinterpret_cast( - reinterpret_cast(new_slot_span->bucket) + - root->ShadowPoolOffset()); -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) } // Memory from PageAllocator is always zeroed. *is_already_zeroed = true; - } else if (!allocate_aligned_slot_span && SetNewActiveSlotSpan(root)) - [[likely]] { + } else if (!allocate_aligned_slot_span && SetNewActiveSlotSpan()) [[likely]] { // First, did we find an active slot span in the active list? new_slot_span = active_slot_spans_head; PA_DCHECK(new_slot_span->is_active()); @@ -1424,9 +1326,8 @@ uintptr_t PartitionBucket::SlowPathAlloc( empty_slot_spans_head = new_slot_span->next_slot_span; // Accept the empty slot span unless it got decommitted. if (new_slot_span->get_freelist_head()) { - new_slot_span->ToWritable(root)->next_slot_span = nullptr; + new_slot_span->next_slot_span = nullptr; new_slot_span->ToSuperPageExtent() - ->ToWritable(root) ->IncrementNumberOfNonemptySlotSpans(); // Re-activating an empty slot span, update accounting. @@ -1438,8 +1339,7 @@ uintptr_t PartitionBucket::SlowPathAlloc( break; } PA_DCHECK(new_slot_span->is_decommitted()); - new_slot_span->ToWritable(root)->next_slot_span = - decommitted_slot_spans_head; + new_slot_span->next_slot_span = decommitted_slot_spans_head; decommitted_slot_spans_head = new_slot_span; } if (!new_slot_span) [[unlikely]] { @@ -1457,8 +1357,7 @@ uintptr_t PartitionBucket::SlowPathAlloc( // provisioning slots, in ProvisionMoreSlotsAndAllocOne(), not here. if (!kUseLazyCommit) { uintptr_t slot_span_start = - SlotSpanMetadata::ToSlotSpanStart( - new_slot_span); + SlotSpanMetadata::ToSlotSpanStart(new_slot_span, root); // Since lazy commit isn't used, we have a guarantee that all slot // span pages have been previously committed, and then decommitted // using PageAccessibilityDisposition::kAllowKeepForPerf, so use the @@ -1478,7 +1377,7 @@ uintptr_t PartitionBucket::SlowPathAlloc( } decommitted_slot_spans_head = new_slot_span->next_slot_span; - new_slot_span->ToWritable(root)->Reset(); + new_slot_span->Reset(); *is_already_zeroed = DecommittedMemoryIsAlwaysZeroed(); } PA_DCHECK(new_slot_span); @@ -1499,9 +1398,8 @@ uintptr_t PartitionBucket::SlowPathAlloc( // Bail if we had a memory allocation failure. if (!new_slot_span) [[unlikely]] { - PA_DCHECK( - active_slot_spans_head == - SlotSpanMetadata::get_sentinel_slot_span()); + PA_DCHECK(active_slot_spans_head == + SlotSpanMetadata::get_sentinel_slot_span()); if (ContainsFlags(flags, AllocFlags::kReturnNull)) { return 0; } @@ -1515,14 +1413,13 @@ uintptr_t PartitionBucket::SlowPathAlloc( PA_DCHECK(new_bucket != &root->sentinel_bucket); new_bucket->active_slot_spans_head = new_slot_span; if (new_slot_span->CanStoreRawSize()) { - new_slot_span->ToWritable(root)->SetRawSize(raw_size); + new_slot_span->SetRawSize(raw_size); } // If we found an active slot span with free slots, or an empty slot span, we // have a usable freelist head. if (new_slot_span->get_freelist_head() != nullptr) [[likely]] { - FreelistEntry* entry = - new_slot_span->ToWritable(root)->PopForAlloc(new_bucket->slot_size); + FreelistEntry* entry = new_slot_span->PopForAlloc(new_bucket->slot_size); // We may have set *is_already_zeroed to true above, make sure that the // freelist entry doesn't contain data. Either way, it wouldn't be a good @@ -1545,9 +1442,8 @@ uintptr_t PartitionBucket::AllocNewSuperPageSpanForGwpAsan( } void PartitionBucket::InitializeSlotSpanForGwpAsan( - SlotSpanMetadata* slot_span, - PartitionRoot* root) { - InitializeSlotSpan(slot_span, root); + SlotSpanMetadata* slot_span) { + InitializeSlotSpan(slot_span); } size_t PartitionBucket::SlotSpanCommittedSize(PartitionRoot* root) const { 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 6c3841dccb..e6c8f54f6c 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 @@ -1,6 +1,11 @@ // Copyright 2018 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 #ifndef PARTITION_ALLOC_PARTITION_BUCKET_H_ #define PARTITION_ALLOC_PARTITION_BUCKET_H_ @@ -26,16 +31,15 @@ uint8_t ComputeSystemPagesPerSlotSpan(size_t slot_size, // Visible for testing. PA_COMPONENT_EXPORT(PARTITION_ALLOC) -bool CompareSlotSpans(const SlotSpanMetadata* a, - const SlotSpanMetadata* b); +bool CompareSlotSpans(const SlotSpanMetadata* a, const SlotSpanMetadata* b); struct PartitionBucket { // Accessed most in hot path => goes first. Only nullptr for invalid buckets, // may be pointing to the sentinel. - SlotSpanMetadata* active_slot_spans_head; + SlotSpanMetadata* active_slot_spans_head; - SlotSpanMetadata* empty_slot_spans_head; - SlotSpanMetadata* decommitted_slot_spans_head; + SlotSpanMetadata* empty_slot_spans_head; + SlotSpanMetadata* decommitted_slot_spans_head; uint32_t slot_size; uint32_t num_system_pages_per_slot_span : kPartitionNumSystemPagesPerSlotSpanBits; @@ -81,7 +85,7 @@ struct PartitionBucket { AllocFlags flags, size_t raw_size, size_t slot_span_alignment, - SlotSpanMetadata** slot_span, + SlotSpanMetadata** slot_span, bool* is_already_zeroed) PA_EXCLUSIVE_LOCKS_REQUIRED(PartitionRootLock(root)); @@ -127,13 +131,12 @@ struct PartitionBucket { // decommitted list and full slot spans are unlinked from any list. // // This is where the guts of the bucket maintenance is done! - bool SetNewActiveSlotSpan(PartitionRoot* root); + bool SetNewActiveSlotSpan(); // Walks the entire active slot span list, and perform regular maintenance, // where empty, decommitted and full slot spans are moved to their // steady-state place. - PA_COMPONENT_EXPORT(PARTITION_ALLOC) - void MaintainActiveList(PartitionRoot* root); + PA_COMPONENT_EXPORT(PARTITION_ALLOC) void MaintainActiveList(); // 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 { @@ -156,10 +159,9 @@ struct PartitionBucket { } // Sort the freelists of all slot spans. - void SortSmallerSlotSpanFreeLists(PartitionRoot* root); + void SortSmallerSlotSpanFreeLists([[maybe_unused]] const PartitionRoot* root); // Sort the active slot span list in ascending freelist length. - PA_COMPONENT_EXPORT(PARTITION_ALLOC) - void SortActiveSlotSpans(PartitionRoot* root); + PA_COMPONENT_EXPORT(PARTITION_ALLOC) void SortActiveSlotSpans(); // We need `AllocNewSuperPageSpan` and `InitializeSlotSpan` to stay // PA_ALWAYS_INLINE for speed, but we also need to use them from a separate @@ -168,9 +170,7 @@ struct PartitionBucket { size_t super_page_count, AllocFlags flags) PA_EXCLUSIVE_LOCKS_REQUIRED(PartitionRootLock(root)); - void InitializeSlotSpanForGwpAsan( - SlotSpanMetadata* slot_span, - PartitionRoot* root); + void InitializeSlotSpanForGwpAsan(SlotSpanMetadata* slot_span); size_t SlotSpanCommittedSize(PartitionRoot* root) const; @@ -187,7 +187,7 @@ struct PartitionBucket { // Allocates a new slot span with size |num_partition_pages| from the // current extent. Metadata within this slot span will be initialized. // Returns nullptr on error. - PA_ALWAYS_INLINE SlotSpanMetadata* AllocNewSlotSpan( + PA_ALWAYS_INLINE SlotSpanMetadata* AllocNewSlotSpan( PartitionRoot* root, AllocFlags flags, size_t slot_span_alignment) @@ -207,9 +207,7 @@ struct PartitionBucket { // for the span (in PartitionPage::SlotSpanMetadata) and registers this bucket // as the owner of the span. It does NOT put the slots into the bucket's // freelist. - PA_ALWAYS_INLINE void InitializeSlotSpan( - SlotSpanMetadata* slot_span, - PartitionRoot* root); + PA_ALWAYS_INLINE void InitializeSlotSpan(SlotSpanMetadata* slot_span); // Initializes a super page. Returns the address of the super page's payload. PA_ALWAYS_INLINE uintptr_t InitializeSuperPage(PartitionRoot* root, @@ -224,10 +222,10 @@ struct PartitionBucket { // // If |slot_span| was freshly allocated, it must have been passed through // InitializeSlotSpan() first. - PA_ALWAYS_INLINE uintptr_t ProvisionMoreSlotsAndAllocOne( - PartitionRoot* root, - AllocFlags flags, - SlotSpanMetadata* slot_span) + PA_ALWAYS_INLINE uintptr_t + ProvisionMoreSlotsAndAllocOne(PartitionRoot* root, + AllocFlags flags, + SlotSpanMetadata* slot_span) PA_EXCLUSIVE_LOCKS_REQUIRED(PartitionRootLock(root)); }; diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_cookie.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_cookie.cc index 72851e3f70..85f74cf729 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_cookie.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_cookie.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_cookie.h" #include 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 686b2ab5c5..0a7be12487 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_COOKIE_H_ #define PARTITION_ALLOC_PARTITION_COOKIE_H_ 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 00f381767c..ea2dcfb5cf 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_dcheck_helper.h" #include @@ -10,38 +15,33 @@ #include "partition_alloc/partition_bucket.h" #include "partition_alloc/partition_page.h" #include "partition_alloc/partition_root.h" -#include "partition_alloc/partition_superpage_extent_entry.h" namespace partition_alloc::internal { #if PA_BUILDFLAG(DCHECKS_ARE_ON) -void DCheckIsValidShiftFromSlotStart( - const SlotSpanMetadata* slot_span, - uintptr_t shift_from_slot_start) { +void DCheckIsValidShiftFromSlotStart(const SlotSpanMetadata* slot_span, + uintptr_t shift_from_slot_start) { PartitionRoot* root = PartitionRoot::FromSlotSpanMetadata(slot_span); // Use <= to allow an address immediately past the object. PA_DCHECK(shift_from_slot_start <= root->GetSlotUsableSize(slot_span)); } -void DCheckIsValidObjectAddress( - const SlotSpanMetadata* slot_span, - uintptr_t object_addr) { +void DCheckIsValidObjectAddress(const SlotSpanMetadata* slot_span, + uintptr_t object_addr) { + PartitionRoot* root = PartitionRoot::FromSlotSpanMetadata(slot_span); uintptr_t slot_span_start = - SlotSpanMetadata::ToSlotSpanStart(slot_span); + SlotSpanMetadata::ToSlotSpanStart(slot_span, root->MetadataOffset()); PA_DCHECK((object_addr - slot_span_start) % slot_span->bucket->slot_size == 0); } void DCheckNumberOfPartitionPagesInSuperPagePayload( - PartitionSuperPageExtentEntry* entry, + const PartitionSuperPageExtentEntry* entry, const PartitionRoot* root, size_t number_of_nonempty_slot_spans) { - PartitionSuperPageExtentEntry* readonly_entry = - entry->ToReadOnly(root); - uintptr_t entry_address = reinterpret_cast(readonly_entry); - uintptr_t super_page = - base::bits::AlignDown(entry_address, kSuperPageAlignment); + uintptr_t super_page = base::bits::AlignDown( + reinterpret_cast(entry), kSuperPageAlignment); size_t number_of_partition_pages_in_superpage_payload = SuperPagePayloadSize(super_page) / PartitionPageSize(); PA_DCHECK(number_of_partition_pages_in_superpage_payload > @@ -54,7 +54,7 @@ void DCheckRootLockIsAcquired(PartitionRoot* root) { #endif // PA_BUILDFLAG(DCHECKS_ARE_ON) -bool DeducedRootIsValid(SlotSpanMetadata* slot_span) { +bool DeducedRootIsValid(const SlotSpanMetadata* slot_span) { PartitionRoot* root = PartitionRoot::FromSlotSpanMetadata(slot_span); return root->inverted_self == ~reinterpret_cast(root); } 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 d48bb87fb1..a59a38fbca 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_DCHECK_HELPER_H_ #define PARTITION_ALLOC_PARTITION_DCHECK_HELPER_H_ @@ -12,7 +17,6 @@ namespace partition_alloc::internal { -template struct PartitionSuperPageExtentEntry; #if PA_BUILDFLAG(DCHECKS_ARE_ON) @@ -36,20 +40,20 @@ struct PartitionSuperPageExtentEntry; PA_EXPORT_IF_DCHECK_IS_ON() void DCheckNumberOfPartitionPagesInSuperPagePayload( - PartitionSuperPageExtentEntry* entry, + const PartitionSuperPageExtentEntry* entry, const PartitionRoot* root, size_t number_of_nonempty_slot_spans) PA_EMPTY_BODY_IF_DCHECK_IS_OFF(); PA_EXPORT_IF_DCHECK_IS_ON() -void DCheckIsValidShiftFromSlotStart( - const SlotSpanMetadata* slot_span, - size_t shift_from_slot_start) PA_EMPTY_BODY_IF_DCHECK_IS_OFF(); +void DCheckIsValidShiftFromSlotStart(const SlotSpanMetadata* slot_span, + size_t shift_from_slot_start) + PA_EMPTY_BODY_IF_DCHECK_IS_OFF(); // Checks that the object is a multiple of slot size (i.e. at a slot start). PA_EXPORT_IF_DCHECK_IS_ON() -void DCheckIsValidObjectAddress( - const SlotSpanMetadata* slot_span, - uintptr_t object_addr) PA_EMPTY_BODY_IF_DCHECK_IS_OFF(); +void DCheckIsValidObjectAddress(const SlotSpanMetadata* slot_span, + uintptr_t object_addr) + PA_EMPTY_BODY_IF_DCHECK_IS_OFF(); PA_EXPORT_IF_DCHECK_IS_ON() void DCheckRootLockIsAcquired(PartitionRoot* root) @@ -60,7 +64,7 @@ void DCheckRootLockIsAcquired(PartitionRoot* root) // `partition_page.h`, and so can't be moved into the latter (layering // violation). PA_COMPONENT_EXPORT(PARTITION_ALLOC) -bool DeducedRootIsValid(SlotSpanMetadata* slot_span); +bool DeducedRootIsValid(const SlotSpanMetadata* slot_span); } // namespace partition_alloc::internal diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_direct_map_extent.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_direct_map_extent.h index d0215187eb..23fffeb1f0 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_direct_map_extent.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_direct_map_extent.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_DIRECT_MAP_EXTENT_H_ #define PARTITION_ALLOC_PARTITION_DIRECT_MAP_EXTENT_H_ @@ -12,242 +17,57 @@ namespace partition_alloc::internal { -template -struct PartitionDirectMapExtent; - -template -struct PartitionDirectMapExtentBase { - MaybeConstT*> - next_extent; - MaybeConstT*> - prev_extent; - MaybeConstT bucket; - +struct PartitionDirectMapExtent { + PartitionDirectMapExtent* next_extent; + PartitionDirectMapExtent* prev_extent; + PartitionBucket* bucket; // Size of the entire reservation, including guard pages, meta-data, // padding for alignment before allocation, and padding for granularity at the // end of the allocation. - MaybeConstT reservation_size; - + size_t reservation_size; // Padding between the first partition page (guard pages + meta-data) and // the allocation. - MaybeConstT padding_for_alignment; -}; + size_t padding_for_alignment; -template -struct PartitionDirectMapExtent; - -template <> -struct PartitionDirectMapExtent - : public PartitionDirectMapExtentBase { - PA_ALWAYS_INLINE static PartitionDirectMapExtent* - FromSlotSpanMetadata(SlotSpanMetadata* slot_span); - - PA_ALWAYS_INLINE PartitionDirectMapExtent* - ToWritable(const PartitionRoot* root); - -#if PA_BUILDFLAG(DCHECKS_ARE_ON) - PA_ALWAYS_INLINE PartitionDirectMapExtent* - ToReadOnly(); -#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) - - private: - // In order to resolve circular dependencies, i.e. ToWritable() needs - // PartitionRoot, define template method: ToWritableInternal() and - // ToWritable() uses it. - template - PartitionDirectMapExtent* ToWritableInternal( - [[maybe_unused]] T* root); -}; - -template <> -struct PartitionDirectMapExtent - : public PartitionDirectMapExtentBase { -#if PA_BUILDFLAG(DCHECKS_ARE_ON) - PA_ALWAYS_INLINE PartitionDirectMapExtent* - ToReadOnly(const PartitionRoot* root); - - private: - // In order to resolve circular dependencies, i.e. ToReadOnly() needs - // PartitionRoot, define template method: ToReadOnlyInternal() and - // ToReadOnly() uses it. - template - PartitionDirectMapExtent* ToReadOnlyInternal( - [[maybe_unused]] T* root); -#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) + PA_ALWAYS_INLINE static PartitionDirectMapExtent* FromSlotSpanMetadata( + SlotSpanMetadata* slot_span); }; // Metadata page for direct-mapped allocations. -template -struct PartitionDirectMapMetadataBase { +struct PartitionDirectMapMetadata { // |page_metadata| and |second_page_metadata| are needed to match the // layout of normal buckets (specifically, of single-slot slot spans), with // the caveat that only the first subsequent page is needed (for // SubsequentPageMetadata) and others aren't used for direct map. - PartitionPageMetadata page_metadata; - PartitionPageMetadata second_page_metadata; - + PartitionPageMetadata page_metadata; + PartitionPageMetadata second_page_metadata; // The following fields are metadata specific to direct map allocations. All // these fields will easily fit into the precalculated metadata region, // because a direct map allocation starts no further than half way through the // super page. - MaybeConstT bucket; + PartitionBucket bucket; + PartitionDirectMapExtent direct_map_extent; - PartitionDirectMapExtent direct_map_extent; + PA_ALWAYS_INLINE static PartitionDirectMapMetadata* FromSlotSpanMetadata( + SlotSpanMetadata* slot_span); }; -template -struct PartitionDirectMapMetadata; - -template <> -struct PartitionDirectMapMetadata - : public PartitionDirectMapMetadataBase { - PA_ALWAYS_INLINE static PartitionDirectMapMetadata* - FromSlotSpanMetadata(SlotSpanMetadata* slot_span); - - PA_ALWAYS_INLINE PartitionDirectMapMetadata* - ToWritable(const PartitionRoot* root); - -#if PA_BUILDFLAG(DCHECKS_ARE_ON) - PA_ALWAYS_INLINE PartitionDirectMapMetadata* - ToReadOnly(); -#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) - - private: - // In order to resolve circular dependencies, i.e. ToWritable() needs - // PartitionRoot, define template method: ToWritableInternal() and - // ToWritable() uses it. - template - PartitionDirectMapMetadata* ToWritableInternal( - [[maybe_unused]] T* root); -}; - -template <> -struct PartitionDirectMapMetadata - : public PartitionDirectMapMetadataBase { -#if PA_BUILDFLAG(DCHECKS_ARE_ON) - PA_ALWAYS_INLINE PartitionDirectMapMetadata* - ToReadOnly(const PartitionRoot* root); - - private: - // In order to resolve circular dependencies, i.e. ToReadOnly() needs - // PartitionRoot, define template method: ToReadOnlyInternal() and - // ToReadOnly() uses it. - template - PartitionDirectMapMetadata* ToReadOnlyInternal( - [[maybe_unused]] T* root); -#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) -}; - -PA_ALWAYS_INLINE PartitionDirectMapMetadata* -PartitionDirectMapMetadata::FromSlotSpanMetadata( - SlotSpanMetadata* slot_span) { +PA_ALWAYS_INLINE PartitionDirectMapMetadata* +PartitionDirectMapMetadata::FromSlotSpanMetadata(SlotSpanMetadata* slot_span) { PA_DCHECK(slot_span->bucket->is_direct_mapped()); // |*slot_span| is the first field of |PartitionDirectMapMetadata|, just cast. - auto* metadata = - reinterpret_cast*>( - slot_span); + auto* metadata = reinterpret_cast(slot_span); PA_DCHECK(&metadata->page_metadata.slot_span_metadata == slot_span); return metadata; } -PA_ALWAYS_INLINE PartitionDirectMapExtent* -PartitionDirectMapExtent::FromSlotSpanMetadata( - SlotSpanMetadata* slot_span) { +PA_ALWAYS_INLINE PartitionDirectMapExtent* +PartitionDirectMapExtent::FromSlotSpanMetadata(SlotSpanMetadata* slot_span) { PA_DCHECK(slot_span->bucket->is_direct_mapped()); - return &PartitionDirectMapMetadata< - MetadataKind::kReadOnly>::FromSlotSpanMetadata(slot_span) + return &PartitionDirectMapMetadata::FromSlotSpanMetadata(slot_span) ->direct_map_extent; } -PA_ALWAYS_INLINE PartitionDirectMapMetadata* -PartitionDirectMapMetadata::ToWritable( - const PartitionRoot* root) { - return ToWritableInternal(root); -} - -template -PartitionDirectMapMetadata* -PartitionDirectMapMetadata::ToWritableInternal( - [[maybe_unused]] T* root) { -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - return reinterpret_cast*>( - reinterpret_cast(this) + root->ShadowPoolOffset()); -#else - return reinterpret_cast*>( - this); -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) -} - -PA_ALWAYS_INLINE PartitionDirectMapExtent* -PartitionDirectMapExtent::ToWritable( - const PartitionRoot* root) { - return ToWritableInternal(root); -} - -template -PartitionDirectMapExtent* -PartitionDirectMapExtent::ToWritableInternal( - [[maybe_unused]] T* root) { -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - return reinterpret_cast*>( - reinterpret_cast(this) + root->ShadowPoolOffset()); -#else - return reinterpret_cast*>( - this); -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) -} - -#if PA_BUILDFLAG(DCHECKS_ARE_ON) -PA_ALWAYS_INLINE PartitionDirectMapMetadata* -PartitionDirectMapMetadata::ToReadOnly() { - return this; -} - -PA_ALWAYS_INLINE PartitionDirectMapMetadata* -PartitionDirectMapMetadata::ToReadOnly( - const PartitionRoot* root) { - return ToReadOnlyInternal(root); -} - -template -PartitionDirectMapMetadata* -PartitionDirectMapMetadata::ToReadOnlyInternal( - [[maybe_unused]] T* root) { -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - return reinterpret_cast*>( - reinterpret_cast(this) - root->ShadowPoolOffset()); -#else - // must be no-op. - return reinterpret_cast*>( - this); -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) -} - -PA_ALWAYS_INLINE PartitionDirectMapExtent* -PartitionDirectMapExtent::ToReadOnly() { - return this; -} - -PA_ALWAYS_INLINE PartitionDirectMapExtent* -PartitionDirectMapExtent::ToReadOnly( - const PartitionRoot* root) { - return ToReadOnlyInternal(root); -} - -template -PartitionDirectMapExtent* -PartitionDirectMapExtent::ToReadOnlyInternal( - [[maybe_unused]] T* root) { -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - return reinterpret_cast*>( - reinterpret_cast(this) - root->ShadowPoolOffset()); -#else - return reinterpret_cast*>( - this); -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) -} -#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) - } // namespace partition_alloc::internal #endif // PARTITION_ALLOC_PARTITION_DIRECT_MAP_EXTENT_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_freelist_entry.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_freelist_entry.cc index 10ab7c6858..d00a58e756 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_freelist_entry.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_freelist_entry.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_freelist_entry.h" #include "partition_alloc/partition_alloc_base/immediate_crash.h" 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 3b1a6c3a62..7d6df99d43 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_FREELIST_ENTRY_H_ #define PARTITION_ALLOC_PARTITION_FREELIST_ENTRY_H_ 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 0209ec6289..eb260cb47f 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_LOCK_H_ #define PARTITION_ALLOC_PARTITION_LOCK_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_oom.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_oom.cc index e56402d1cd..9e390fdb94 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_oom.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_oom.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_oom.h" #include "partition_alloc/build_config.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_oom.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_oom.h index 6145c6520a..345fdc8913 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_oom.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_oom.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // Holds functions for generating OOM errors from PartitionAlloc. This is // distinct from oom.h in that it is meant only for use in PartitionAlloc. 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 ce4caa07bd..d629b99e36 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_page.h" #include @@ -32,24 +37,21 @@ void UnmapNow(uintptr_t reservation_start, size_t reservation_size, PartitionRoot* root); -PA_ALWAYS_INLINE void PartitionDirectUnmap( - SlotSpanMetadata* slot_span) { +PA_ALWAYS_INLINE void PartitionDirectUnmap(SlotSpanMetadata* slot_span) { auto* root = PartitionRoot::FromSlotSpanMetadata(slot_span); PartitionRootLock(root).AssertAcquired(); - auto* extent = - PartitionDirectMapExtent::FromSlotSpanMetadata( - slot_span); + auto* extent = PartitionDirectMapExtent::FromSlotSpanMetadata(slot_span); // Maintain the doubly-linked list of all direct mappings. if (extent->prev_extent) { PA_DCHECK(extent->prev_extent->next_extent == extent); - extent->prev_extent->ToWritable(root)->next_extent = extent->next_extent; + extent->prev_extent->next_extent = extent->next_extent; } else { root->direct_map_list = extent->next_extent; } if (extent->next_extent) { PA_DCHECK(extent->next_extent->prev_extent == extent); - extent->next_extent->ToWritable(root)->prev_extent = extent->prev_extent; + extent->next_extent->prev_extent = extent->prev_extent; } // The actual decommit is deferred below after releasing the lock. @@ -61,7 +63,7 @@ PA_ALWAYS_INLINE void PartitionDirectUnmap( root->total_size_of_direct_mapped_pages -= reservation_size; uintptr_t reservation_start = - SlotSpanMetadata::ToSlotSpanStart(slot_span); + SlotSpanMetadata::ToSlotSpanStart(slot_span, root); // The mapping may start at an unspecified location within a super page, but // we always reserve memory aligned to super page size. reservation_start = base::bits::AlignDown(reservation_start, kSuperPageSize); @@ -83,15 +85,8 @@ PA_ALWAYS_INLINE void PartitionDirectUnmap( } // namespace -PA_ALWAYS_INLINE void -SlotSpanMetadata::RegisterEmpty() { - PA_DCHECK(is_empty_internal()); - // We can use FromSlotSpanMetadata() to get PartitionRoot from - // both SlotSpanMetadata and - // SlotSpanMetadata, because SuperPageExtentEntry and - // SlotSpanMetadata are in the same system page, and - // WritableSuperPageExtentEntry and SlotSpanMetadata - // are also in the same system page. +PA_ALWAYS_INLINE void SlotSpanMetadata::RegisterEmpty() { + PA_DCHECK(is_empty()); auto* root = PartitionRoot::FromSlotSpanMetadata(this); PartitionRootLock(root).AssertAcquired(); @@ -110,12 +105,12 @@ SlotSpanMetadata::RegisterEmpty() { PA_DCHECK(root->global_empty_slot_span_ring_index < root->global_empty_slot_span_ring_size); int16_t current_index = root->global_empty_slot_span_ring_index; - SlotSpanMetadata* slot_span_to_decommit = + SlotSpanMetadata* slot_span_to_decommit = root->global_empty_slot_span_ring[current_index]; // The slot span might well have been re-activated, filled up, etc. before we // get around to looking at it here. if (slot_span_to_decommit) { - slot_span_to_decommit->ToWritable(root)->DecommitIfPossible(root); + slot_span_to_decommit->DecommitIfPossible(root); } // There should not be a slot span in the buffer at the position this is @@ -126,7 +121,7 @@ SlotSpanMetadata::RegisterEmpty() { // empty", thus providing it a bit of breathing room to get re-used before we // really free it. This reduces the number of system calls. Otherwise any // free() from a single-slot slot span would lead to a syscall, for instance. - root->global_empty_slot_span_ring[current_index] = ToReadOnly(root); + root->global_empty_slot_span_ring[current_index] = this; empty_cache_index_ = current_index; in_empty_cache_ = 1; ++current_index; @@ -152,32 +147,31 @@ SlotSpanMetadata::RegisterEmpty() { } } // static -const SlotSpanMetadata - SlotSpanMetadata::sentinel_slot_span_; +const SlotSpanMetadata SlotSpanMetadata::sentinel_slot_span_; // static -const SlotSpanMetadata* -SlotSpanMetadata::get_sentinel_slot_span() { +const SlotSpanMetadata* SlotSpanMetadata::get_sentinel_slot_span() { return &sentinel_slot_span_; } // static -SlotSpanMetadata* -SlotSpanMetadata::get_sentinel_slot_span_non_const() { - return const_cast*>( - &sentinel_slot_span_); +SlotSpanMetadata* SlotSpanMetadata::get_sentinel_slot_span_non_const() { + return const_cast(&sentinel_slot_span_); } -void SlotSpanMetadata::FreeSlowPath( - size_t number_of_freed, - PartitionRoot* root) { -#if PA_BUILDFLAG(DCHECKS_ARE_ON) - DCheckRootLockIsAcquired(root); -#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) - SlotSpanMetadata* readonly_this = ToReadOnly(root); - PA_DCHECK( - readonly_this != - SlotSpanMetadata::get_sentinel_slot_span()); +SlotSpanMetadata::SlotSpanMetadata(PartitionBucket* bucket) + : bucket(bucket), + num_allocated_slots(0u), + num_unprovisioned_slots(0u), + marked_full(0u), + can_store_raw_size_(bucket->CanStoreRawSize()), + freelist_is_sorted_(1u), + in_empty_cache_(0u), + empty_cache_index_(0u) {} + +void SlotSpanMetadata::FreeSlowPath(size_t number_of_freed) { + DCheckRootLockIsAcquired(PartitionRoot::FromSlotSpanMetadata(this)); + PA_DCHECK(this != get_sentinel_slot_span()); // The caller has already modified |num_allocated_slots|. It is a // responsibility of this function to react to it, and update the state. We @@ -198,12 +192,10 @@ void SlotSpanMetadata::FreeSlowPath( // chances of it being filled up again. The old current slot span will be // the next slot span. PA_DCHECK(!next_slot_span); - if (bucket->active_slot_spans_head != - SlotSpanMetadata::get_sentinel_slot_span()) - [[likely]] { + if (bucket->active_slot_spans_head != get_sentinel_slot_span()) [[likely]] { next_slot_span = bucket->active_slot_spans_head; } - bucket->active_slot_spans_head = readonly_this; + bucket->active_slot_spans_head = this; PA_CHECK(bucket->num_full_slot_spans); // Underflow. --bucket->num_full_slot_spans; } @@ -211,7 +203,7 @@ void SlotSpanMetadata::FreeSlowPath( if (num_allocated_slots == 0) [[likely]] { // Slot span became fully unused. if (bucket->is_direct_mapped()) [[unlikely]] { - PartitionDirectUnmap(readonly_this); + PartitionDirectUnmap(this); return; } @@ -221,10 +213,10 @@ void SlotSpanMetadata::FreeSlowPath( // If it's the current active slot span, change it. We bounce the slot span // to the empty list as a force towards defragmentation. - if (readonly_this == bucket->active_slot_spans_head) [[likely]] { - bucket->SetNewActiveSlotSpan(root); + if (this == bucket->active_slot_spans_head) [[likely]] { + bucket->SetNewActiveSlotSpan(); } - PA_DCHECK(bucket->active_slot_spans_head != readonly_this); + PA_DCHECK(bucket->active_slot_spans_head != this); if (CanStoreRawSize()) { SetRawSize(0); @@ -234,13 +226,11 @@ void SlotSpanMetadata::FreeSlowPath( } } -void SlotSpanMetadata::Decommit(PartitionRoot* root) { +void SlotSpanMetadata::Decommit(PartitionRoot* root) { PartitionRootLock(root).AssertAcquired(); - PA_DCHECK(is_empty_internal()); + PA_DCHECK(is_empty()); PA_DCHECK(!bucket->is_direct_mapped()); - uintptr_t slot_span_start = - SlotSpanMetadata::ToSlotSpanStart( - ToReadOnly(root)); + uintptr_t slot_span_start = SlotSpanMetadata::ToSlotSpanStart(this, root); // If lazy commit is enabled, only provisioned slots are committed. size_t dirty_size = base::bits::AlignUp(GetProvisionedSize(), SystemPageSize()); @@ -261,32 +251,28 @@ void SlotSpanMetadata::Decommit(PartitionRoot* root) { // Pulling this trick enables us to use a singly-linked list for all // cases, which is critical in keeping the slot span metadata structure down // to 32 bytes in size. - SetFreelistHead(nullptr, root); + SetFreelistHead(nullptr); num_unprovisioned_slots = 0; - PA_DCHECK(is_decommitted_internal()); + PA_DCHECK(is_decommitted()); PA_DCHECK(bucket); } -void SlotSpanMetadata::DecommitIfPossible( - PartitionRoot* root) { +void SlotSpanMetadata::DecommitIfPossible(PartitionRoot* root) { PartitionRootLock(root).AssertAcquired(); PA_DCHECK(in_empty_cache_); PA_DCHECK(empty_cache_index_ < kMaxEmptySlotSpanRingSize); - PA_DCHECK(ToReadOnly(root) == - root->global_empty_slot_span_ring[empty_cache_index_]); + PA_DCHECK(this == root->global_empty_slot_span_ring[empty_cache_index_]); in_empty_cache_ = 0; - if (is_empty_internal()) { + if (is_empty()) { Decommit(root); } root->global_empty_slot_span_ring[empty_cache_index_] = nullptr; } -void SlotSpanMetadata::SortFreelist( - [[maybe_unused]] PartitionRoot* root) { +void SlotSpanMetadata::SortFreelist( + [[maybe_unused]] const PartitionRoot* root) { std::bitset free_slots; - uintptr_t slot_span_start = - SlotSpanMetadata::ToSlotSpanStart( - ToReadOnly(root)); + uintptr_t slot_span_start = ToSlotSpanStart(this, root); size_t num_provisioned_slots = bucket->get_slots_per_span() - num_unprovisioned_slots; @@ -324,19 +310,12 @@ void SlotSpanMetadata::SortFreelist( back = entry; } } - SetFreelistHead(head, root); + SetFreelistHead(head); } freelist_is_sorted_ = true; } -void SlotSpanMetadata< - MetadataKind::kWritable>::IncrementNumberOfNonemptySlotSpans() { - PartitionSuperPageExtentEntry* extent = - ToSuperPageExtent(); - extent->IncrementNumberOfNonemptySlotSpans(); -} - namespace { void UnmapNow(uintptr_t reservation_start, @@ -386,6 +365,18 @@ void UnmapNow(uintptr_t reservation_start, } #endif // PA_BUILDFLAG(DCHECKS_ARE_ON) +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + // Decommit metadata area inside metadata cage to avoid DCHECK() failure + // at next allocation. This must be done before + // `UnreserveAndDecommit(reservation_start, reservation_size)`. + if (root->MetadataOffset() & kSuperPageBaseMask) { + uintptr_t metadata_start = PartitionSuperPageToMetadataPage( + reservation_start, root->MetadataOffset()); + DecommitAndZeroSystemPages(metadata_start, SystemPageSize(), + PageTag::kPartitionAlloc); + } +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + // Reset the offset table entries for the given memory before unreserving // it. Since the memory is not unreserved and not available for other // threads, the table entries for the memory are not modified by other @@ -394,17 +385,6 @@ void UnmapNow(uintptr_t reservation_start, root->GetReservationOffsetTable().SetNotAllocatedTag(reservation_start, reservation_size); -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - // UnmapShadowMetadata must be done before unreserving memory, because - // Unreserved memory may be allocated by PartitionDirectMap() in another - // thread. In the case, MapShadowMetadata() and UnmapShadowMetadata() - // will be executed for the same system pages in wrong order. It causes - // memory access error. - if (internal::PartitionAddressSpace::IsShadowMetadataEnabled(pool)) { - PartitionAddressSpace::UnmapShadowMetadata(reservation_start, pool); - } -#endif - #if !PA_BUILDFLAG(HAS_64_BIT_POINTERS) AddressPoolManager::GetInstance().MarkUnused(pool, 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 48a8c5e014..ac78fd1685 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_PAGE_H_ #define PARTITION_ALLOC_PARTITION_PAGE_H_ @@ -12,6 +17,7 @@ #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/bits.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" @@ -33,9 +39,6 @@ namespace partition_alloc::internal { -template -struct SlotSpanMetadata; - // Metadata of the slot span. // // Some notes on slot span states. It can be in one of four major states: @@ -67,16 +70,14 @@ struct SlotSpanMetadata; // found, an empty or decommitted slot spans (if one exists) will be pulled // from the empty/decommitted list on to the active list. #pragma pack(push, 1) -template -struct SlotSpanMetadataBase { - protected: - MaybeConstT freelist_head = nullptr; +struct SlotSpanMetadata { + private: + FreelistEntry* freelist_head = nullptr; public: // TODO(lizeb): Make as many fields as possible private or const, to // encapsulate things more clearly. - MaybeConstT*> next_slot_span = - nullptr; + SlotSpanMetadata* next_slot_span = nullptr; PartitionBucket* const bucket = nullptr; // CHECK()ed in AllocNewSlotSpan(). @@ -86,32 +87,28 @@ struct SlotSpanMetadataBase { // |num_allocated_slots| is 0 for empty or decommitted slot spans, which can // be further differentiated by checking existence of the freelist. - MaybeConstT num_allocated_slots : kMaxSlotsPerSlotSpanBits = - 0u; - MaybeConstT num_unprovisioned_slots - : kMaxSlotsPerSlotSpanBits = 0u; + 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). - MaybeConstT marked_full : 1 = 0u; + uint32_t marked_full : 1; - protected: - const uint32_t can_store_raw_size_ : 1 = 0u; - MaybeConstT freelist_is_sorted_ : 1 = 1u; + private: + const uint32_t can_store_raw_size_ : 1; + uint16_t freelist_is_sorted_ : 1; // If |in_empty_cache_|==1, |empty_cache_index| is undefined and mustn't be // used. - MaybeConstT in_empty_cache_ : 1 = 0u; + uint16_t in_empty_cache_ : 1; // Index of the page in the empty cache. This is in the range // [0, `kMaxEmptySlotSpanRingSize - 1`] so it fits in // `BitWidth(kMaxEmptySlotSpanRingSize - 1)`. - MaybeConstT empty_cache_index_ - : internal::base::bits::BitWidth(kMaxEmptySlotSpanRingSize - 1) = 0u; + uint16_t empty_cache_index_ + : internal::base::bits::BitWidth(kMaxEmptySlotSpanRingSize - 1); // 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. public: - // Methods required by both SlotSpanMetadata and . - // Checks if it is feasible to store raw_size. PA_ALWAYS_INLINE bool CanStoreRawSize() const { return can_store_raw_size_; } @@ -133,67 +130,75 @@ struct SlotSpanMetadataBase { PA_ALWAYS_INLINE bool in_empty_cache() const { return in_empty_cache_; } - protected: - constexpr SlotSpanMetadataBase() noexcept = default; - explicit SlotSpanMetadataBase(PartitionBucket* b) - : bucket(b), can_store_raw_size_(b->CanStoreRawSize()) {} + PA_COMPONENT_EXPORT(PARTITION_ALLOC) + explicit SlotSpanMetadata(PartitionBucket* bucket); - bool is_decommitted_internal() const { - bool ret = (!num_allocated_slots && !freelist_head); - if (ret) { - PA_DCHECK(!marked_full); - PA_DCHECK(!num_unprovisioned_slots); - PA_DCHECK(!in_empty_cache_); - } - return ret; - } - - bool is_empty_internal() const { - bool ret = (!num_allocated_slots && freelist_head); - if (ret) { - PA_DCHECK(!marked_full); - } - return ret; - } -}; - -template <> -struct SlotSpanMetadata - : public SlotSpanMetadataBase { -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - // We don't need to directly create read-only SlotSpanMetadata. We will do: - // (1) we know the address of read-only SlotSpanMetadata. - // (2) we use ToWritable() to obtain its writable address. - // (3) we invoke writable SlotSpanMetadata's constructor. - // (4) we see that the read-only one has been initialized. - explicit SlotSpanMetadata(PartitionBucket*) = delete; -#else - explicit SlotSpanMetadata(PartitionBucket* b) - : SlotSpanMetadataBase(b) {} -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) // pa_tcache_inspect needs the copy constructor. - SlotSpanMetadata(const SlotSpanMetadata&) = default; + inline SlotSpanMetadata(const SlotSpanMetadata&); // Public API // Pointer/address manipulation functions. These must be static as the input // |slot_span| pointer may be the result of an offset calculation and // therefore cannot be trusted. The objective of these functions is to // sanitize this input. - PA_ALWAYS_INLINE static uintptr_t ToSlotSpanStart( - const SlotSpanMetadata* slot_span); - PA_ALWAYS_INLINE static SlotSpanMetadata* FromAddr( - uintptr_t address); - PA_ALWAYS_INLINE static SlotSpanMetadata* - FromSlotStart(uintptr_t slot_start); - PA_ALWAYS_INLINE static SlotSpanMetadata* FromObject( - const void* object); - PA_ALWAYS_INLINE static SlotSpanMetadata* - FromObjectInnerAddr(uintptr_t address); - PA_ALWAYS_INLINE static SlotSpanMetadata* - FromObjectInnerPtr(const void* ptr); - PA_ALWAYS_INLINE PartitionSuperPageExtentEntry* - ToSuperPageExtent() const; + // If metadata is outside of GigaCage, the following methods: + // ToSlotSpanStart(), FromAddr(), FromSlotStart(), FromObject(), + // FromObjectInnerAddr(), and FromObjectInnerAddr() + // are much slower, because: + // (1) need to find `pool` from the given address, + // (2) need to obtain `offset` from the `pool`. + // If `PartitionRoot` is known or metadata offset is known, it is much better + // to use methods with `root` or `offset`. + // For example, `FromAddr(uintptr_t address)` is slow and not recommended. + // `FromAddr(uintptr_t address, const PartitionRoot*)` takes a `root` + // parameter and `FromAddr(uintptr_t address, std::ptrdiff offset)` takes an + // `offset` parameter, which are recommended 146-147. + PA_ALWAYS_INLINE static uintptr_t ToSlotSpanStart( + const SlotSpanMetadata* slot_span, + [[maybe_unused]] const PartitionRoot* root); + PA_ALWAYS_INLINE static uintptr_t ToSlotSpanStart( + const SlotSpanMetadata* slot_span, + [[maybe_unused]] std::ptrdiff_t offset); + + PA_ALWAYS_INLINE static SlotSpanMetadata* FromAddr(uintptr_t address); + PA_ALWAYS_INLINE static SlotSpanMetadata* FromAddr( + uintptr_t address, + [[maybe_unused]] const PartitionRoot* root); + PA_ALWAYS_INLINE static SlotSpanMetadata* FromAddr( + uintptr_t address, + [[maybe_unused]] std::ptrdiff_t offset); + + PA_ALWAYS_INLINE static SlotSpanMetadata* FromSlotStart(uintptr_t slot_start); + PA_ALWAYS_INLINE static SlotSpanMetadata* FromSlotStart( + uintptr_t slot_start, + [[maybe_unused]] const PartitionRoot* root); + PA_ALWAYS_INLINE static SlotSpanMetadata* FromSlotStart( + uintptr_t slot_start, + [[maybe_unused]] std::ptrdiff_t offset); + + PA_ALWAYS_INLINE static SlotSpanMetadata* FromObject(const void* object); + PA_ALWAYS_INLINE static SlotSpanMetadata* FromObject( + const void* object, + [[maybe_unused]] const PartitionRoot* root); + PA_ALWAYS_INLINE static SlotSpanMetadata* FromObject( + const void* object, + [[maybe_unused]] std::ptrdiff_t offset); + + PA_ALWAYS_INLINE static SlotSpanMetadata* FromObjectInnerAddr( + uintptr_t address, + [[maybe_unused]] const PartitionRoot* root); + PA_ALWAYS_INLINE static SlotSpanMetadata* FromObjectInnerAddr( + uintptr_t address, + [[maybe_unused]] std::ptrdiff_t offset); + PA_ALWAYS_INLINE static SlotSpanMetadata* FromObjectInnerPtr( + const void* ptr, + [[maybe_unused]] const PartitionRoot* root); + PA_ALWAYS_INLINE static SlotSpanMetadata* FromObjectInnerPtr( + const void* ptr, + [[maybe_unused]] std::ptrdiff_t offset); + + PA_ALWAYS_INLINE PartitionSuperPageExtentEntry* ToSuperPageExtent() const; PA_ALWAYS_INLINE size_t GetRawSize() const; @@ -226,15 +231,13 @@ struct SlotSpanMetadata // TODO(ajwong): Can this be made private? https://crbug.com/787153 PA_COMPONENT_EXPORT(PARTITION_ALLOC) - static const SlotSpanMetadata* - get_sentinel_slot_span(); + static const SlotSpanMetadata* get_sentinel_slot_span(); // The sentinel is not supposed to be modified and hence we mark it as const // under the hood. However, we often store it together with mutable metadata // objects and need a non-const pointer. // You can use this function for this case, but you need to ensure that the // returned object will not be written to. - static SlotSpanMetadata* - get_sentinel_slot_span_non_const(); + static SlotSpanMetadata* get_sentinel_slot_span_non_const(); // Slot span state getters. PA_ALWAYS_INLINE bool is_active() const; @@ -245,57 +248,18 @@ struct SlotSpanMetadata return freelist_is_sorted_; } - PA_ALWAYS_INLINE SlotSpanMetadata* ToWritable( - const PartitionRoot* root) { - return ToWritableInternal(root); - } - - PA_ALWAYS_INLINE SlotSpanMetadata* ToReadOnly() { - return this; - } - private: - void IncrementNumberOfNonemptySlotSpans(); - - template - SlotSpanMetadata* ToWritableInternal( - [[maybe_unused]] T* root) { -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - // Must not make writable slot_span from sentinel slot_span. - PA_DCHECK(this != get_sentinel_slot_span()); - return reinterpret_cast*>( - reinterpret_cast(this) + root->ShadowPoolOffset()); -#else - return reinterpret_cast*>(this); -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) - } - // sentinel_slot_span_ is used as a sentinel to indicate that there is no slot // span in the active list. We could use nullptr, but in that case we need to // add a null-check branch to the hot allocation path. We want to avoid that. // // Note, this declaration is kept in the header as opposed to an anonymous // namespace so the getter can be fully inlined. - static const SlotSpanMetadata sentinel_slot_span_; + static const SlotSpanMetadata sentinel_slot_span_; // For the sentinel. - inline constexpr SlotSpanMetadata() noexcept = - default; -}; + inline constexpr SlotSpanMetadata() noexcept; -template <> -struct SlotSpanMetadata - : public SlotSpanMetadataBase { - PA_COMPONENT_EXPORT(PARTITION_ALLOC) - explicit SlotSpanMetadata(PartitionBucket* b) - : SlotSpanMetadataBase(b) {} - - PA_ALWAYS_INLINE PartitionSuperPageExtentEntry* - ToSuperPageExtent(); - - // Note the matching Alloc() functions are in PartitionPage. - PA_NOINLINE PA_COMPONENT_EXPORT(PARTITION_ALLOC) void FreeSlowPath( - size_t number_of_freed, - PartitionRoot* root); + public: // Note the matching Alloc() functions are in PartitionPage. PA_NOINLINE PA_COMPONENT_EXPORT(PARTITION_ALLOC) void FreeSlowPath( size_t number_of_freed); @@ -315,7 +279,7 @@ struct SlotSpanMetadata void DecommitIfPossible(PartitionRoot* root); // Sorts the freelist in ascending addresses order. - void SortFreelist(PartitionRoot* root); + void SortFreelist(const PartitionRoot* root); // Inserts the slot span into the empty ring, making space for the new slot // span, and potentially shrinking the ring. void RegisterEmpty(); @@ -324,50 +288,28 @@ struct SlotSpanMetadata // calling Set/GetRawSize. PA_ALWAYS_INLINE void SetRawSize(size_t raw_size); - PA_ALWAYS_INLINE void SetFreelistHead(FreelistEntry* new_head, - PartitionRoot* root); + PA_ALWAYS_INLINE void SetFreelistHead(FreelistEntry* new_head); PA_ALWAYS_INLINE void Reset(); -#if PA_BUILDFLAG(DCHECKS_ARE_ON) - // Slot span state getters. - PA_ALWAYS_INLINE bool is_empty() const; - PA_ALWAYS_INLINE bool is_decommitted() const; -#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) - PA_ALWAYS_INLINE void set_freelist_sorted() { freelist_is_sorted_ = true; } - - PA_ALWAYS_INLINE SlotSpanMetadata* ToWritable() { - return this; - } - - PA_ALWAYS_INLINE SlotSpanMetadata* ToReadOnly( - const PartitionRoot* root) { - return ToReadOnlyInternal(root); - } - - private: - void IncrementNumberOfNonemptySlotSpans(); - - template - PA_ALWAYS_INLINE SlotSpanMetadata* - ToReadOnlyInternal([[maybe_unused]] const T* root) { -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - return reinterpret_cast*>( - reinterpret_cast(this) - root->ShadowPoolOffset()); -#else - return reinterpret_cast*>(this); -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) - } }; #pragma pack(pop) -static_assert(sizeof(SlotSpanMetadata) <= - kPageMetadataSize, - "SlotSpanMetadata must fit into a Page " - "Metadata slot."); +static_assert(sizeof(SlotSpanMetadata) <= kPageMetadataSize, + "SlotSpanMetadata must fit into a Page Metadata slot."); + +inline constexpr SlotSpanMetadata::SlotSpanMetadata() noexcept + : num_allocated_slots(0u), + num_unprovisioned_slots(0u), + marked_full(0u), + can_store_raw_size_(0u), + freelist_is_sorted_(1u), + in_empty_cache_(0u), + empty_cache_index_(0u) {} + +inline SlotSpanMetadata::SlotSpanMetadata(const SlotSpanMetadata&) = default; // Metadata of a non-first partition page in a slot span. -template struct SubsequentPageMetadata { // Raw size is the size needed to satisfy the allocation (requested size + // extras). If available, it can be used to report better statistics or to @@ -379,7 +321,7 @@ struct SubsequentPageMetadata { // - there is more than one partition page in the slot span (the metadata of // the first one is used to store slot information, but the second one is // available for extra information) - MaybeConstT raw_size; + size_t raw_size; }; // Each partition page has metadata associated with it. The metadata of the @@ -389,20 +331,18 @@ struct SubsequentPageMetadata { // "Pack" the union so that common page metadata still fits within // kPageMetadataSize. (SlotSpanMetadata is also "packed".) #pragma pack(push, 1) -template -struct PartitionPageMetadataBase { +struct PartitionPageMetadata { union { - SlotSpanMetadata slot_span_metadata; + SlotSpanMetadata slot_span_metadata; - SubsequentPageMetadata subsequent_page_metadata; + SubsequentPageMetadata subsequent_page_metadata; // sizeof(PartitionPageMetadata) must always be: // - a power of 2 (for fast modulo operations) // - below kPageMetadataSize // // This makes sure that this is respected no matter the architecture. - MaybeConstT - optional_padding[kPageMetadataSize - sizeof(uint8_t) - sizeof(bool)]; + char optional_padding[kPageMetadataSize - sizeof(uint8_t) - sizeof(bool)]; }; // The first PartitionPage of the slot span holds its metadata. This offset @@ -416,8 +356,7 @@ struct PartitionPageMetadataBase { static constexpr uint16_t kMaxSlotSpanMetadataBits = 6; static constexpr uint16_t kMaxSlotSpanMetadataOffset = (1 << kMaxSlotSpanMetadataBits) - 1; - MaybeConstT slot_span_metadata_offset - : kMaxSlotSpanMetadataBits; + uint8_t slot_span_metadata_offset : kMaxSlotSpanMetadataBits; // |is_valid| tells whether the page is part of a slot span. If |false|, // |has_valid_span_after_this| tells whether it's an unused region in between @@ -425,73 +364,20 @@ struct PartitionPageMetadataBase { // Note, |is_valid| has been added for clarity, but if we ever need to save // this bit, it can be inferred from: // |!slot_span_metadata_offset && slot_span_metadata->bucket|. - MaybeConstT is_valid : 1; - MaybeConstT has_valid_span_after_this : 1; - MaybeConstT unused; -}; + bool is_valid : 1; + bool has_valid_span_after_this : 1; + uint8_t unused; -template -struct PartitionPageMetadata; - -template <> -struct PartitionPageMetadata - : public PartitionPageMetadataBase { - PA_ALWAYS_INLINE static PartitionPageMetadata* - FromAddr(uintptr_t address); - - PA_ALWAYS_INLINE PartitionPageMetadata* ToWritable( - PartitionRoot* root) { - return ToWritableInternal(root); - } - - // In order to resolve circular dependencies, i.e. ToWritable() needs - // PartitionRoot, define template method: ToWritableInternal() here and - // ToWritable() uses it. - template - PartitionPageMetadata* ToWritableInternal( - [[maybe_unused]] T* root) { -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - return reinterpret_cast*>( - reinterpret_cast(this) + root->ShadowPoolOffset()); -#else - return reinterpret_cast*>( - this); -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) - } -}; - -template <> -struct PartitionPageMetadata - : public PartitionPageMetadataBase { - PA_ALWAYS_INLINE PartitionPageMetadata* ToReadOnly( - PartitionRoot* root) { - return ToReadOnlyInternal(root); - } - - // In order to resolve circular dependencies, i.e. ToReadOnly() needs - // PartitionRoot, define template method: ToReadOnlyInternal() here and - // ToReadOnly() uses it. - template - PartitionPageMetadata* ToReadOnlyInternal( - [[maybe_unused]] T* root) { -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - return reinterpret_cast*>( - reinterpret_cast(this) - root->ShadowPoolOffset()); -#else - return reinterpret_cast*>( - this); -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) - } + PA_ALWAYS_INLINE static PartitionPageMetadata* FromAddr( + uintptr_t address, + [[maybe_unused]] const PartitionRoot* root); + PA_ALWAYS_INLINE static PartitionPageMetadata* FromAddr( + uintptr_t address, + [[maybe_unused]] std::ptrdiff_t offet); }; #pragma pack(pop) - -static_assert(sizeof(PartitionPageMetadata) == - kPageMetadataSize, +static_assert(sizeof(PartitionPageMetadata) == kPageMetadataSize, "PartitionPage must be able to fit in a metadata slot"); -static_assert(sizeof(PartitionPageMetadata) == - sizeof(PartitionPageMetadata), - "The size of PartitionPageMetadata must " - "be equal to PartitionPageMetadata."); // Certain functions rely on PartitionPageMetadata being either SlotSpanMetadata // or SubsequentPageMetadata, and therefore freely casting between each other. @@ -500,57 +386,61 @@ static_assert(sizeof(PartitionPageMetadata) == #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Winvalid-offsetof" #endif -static_assert(offsetof(PartitionPageMetadata, - slot_span_metadata) == 0, +static_assert(offsetof(PartitionPageMetadata, slot_span_metadata) == 0, "slot_span_metadata must be placed at the beginning of " - "PartitionPageMetadata."); -static_assert(offsetof(PartitionPageMetadata, - subsequent_page_metadata) == 0, + "PartitionPageMetadata."); +static_assert(offsetof(PartitionPageMetadata, subsequent_page_metadata) == 0, "subsequent_page_metadata must be placed at the beginning of " - "PartitionPageMetadata."); -static_assert(offsetof(PartitionPageMetadata, - slot_span_metadata) == 0, - "slot_span_metadata must be placed at the beginning of " - "PartitionPageMetadata."); -static_assert(offsetof(PartitionPageMetadata, - subsequent_page_metadata) == 0, - "subsequent_page_metadata must be placed at the beginning of " - "PartitionPageMetadata."); + "PartitionPageMetadata."); #if defined(__clang__) || defined(__GNUC__) #pragma GCC diagnostic pop #endif -PA_ALWAYS_INLINE PartitionPageMetadata* -PartitionSuperPageToMetadataArea(uintptr_t super_page) { +PA_ALWAYS_INLINE PartitionPageMetadata* PartitionSuperPageToMetadataArea( + uintptr_t super_page, + [[maybe_unused]] std::ptrdiff_t offset) { // This can't be just any super page, but it has to be the first super page of // the reservation, as we assume here that the metadata is near its beginning. PA_DCHECK( ReservationOffsetTable::Get(super_page).IsReservationStart(super_page)); PA_DCHECK(!(super_page & kSuperPageOffsetMask)); + uintptr_t address = PartitionSuperPageToMetadataPage(super_page, offset); +#if !PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) // The metadata area is exactly one system page (the guard page) into the // super page. - return reinterpret_cast*>( - super_page + SystemPageSize()); + PA_DCHECK(super_page + SystemPageSize() == address); +#endif + return reinterpret_cast(address); } -PA_ALWAYS_INLINE const SubsequentPageMetadata* -GetSubsequentPageMetadata( - const PartitionPageMetadata* page_metadata) { +PA_ALWAYS_INLINE PartitionPageMetadata* PartitionSuperPageToMetadataArea( + uintptr_t super_page, + [[maybe_unused]] const PartitionRoot* root) { + return PartitionSuperPageToMetadataArea(super_page, GetMetadataOffset(root)); +} + +PA_ALWAYS_INLINE const SubsequentPageMetadata* GetSubsequentPageMetadata( + const PartitionPageMetadata* page_metadata) { return &(page_metadata + 1)->subsequent_page_metadata; } -PA_ALWAYS_INLINE SubsequentPageMetadata* -GetSubsequentPageMetadata( - PartitionPageMetadata* page_metadata) { +PA_ALWAYS_INLINE SubsequentPageMetadata* GetSubsequentPageMetadata( + PartitionPageMetadata* page_metadata) { return &(page_metadata + 1)->subsequent_page_metadata; } -PA_ALWAYS_INLINE PartitionSuperPageExtentEntry* -PartitionSuperPageToExtent(uintptr_t super_page) { +PA_ALWAYS_INLINE PartitionSuperPageExtentEntry* PartitionSuperPageToExtent( + uintptr_t super_page, + [[maybe_unused]] std::ptrdiff_t offset) { // The very first entry of the metadata is the super page extent entry. - return reinterpret_cast< - PartitionSuperPageExtentEntry*>( - PartitionSuperPageToMetadataArea(super_page)); + return reinterpret_cast( + PartitionSuperPageToMetadataArea(super_page, offset)); +} + +PA_ALWAYS_INLINE PartitionSuperPageExtentEntry* PartitionSuperPageToExtent( + uintptr_t super_page, + [[maybe_unused]] const PartitionRoot* root) { + return PartitionSuperPageToExtent(super_page, GetMetadataOffset(root)); } PA_ALWAYS_INLINE PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR size_t @@ -580,24 +470,13 @@ PA_ALWAYS_INLINE size_t SuperPagePayloadSize(uintptr_t super_page) { return SuperPagePayloadEnd(super_page) - SuperPagePayloadBegin(super_page); } -PA_ALWAYS_INLINE PartitionSuperPageExtentEntry* -SlotSpanMetadata::ToSuperPageExtent() const { - uintptr_t super_page = reinterpret_cast(this) & kSuperPageBaseMask; - return PartitionSuperPageToExtent(super_page); -} - -PA_ALWAYS_INLINE PartitionSuperPageExtentEntry* -SlotSpanMetadata::ToSuperPageExtent() { -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - uintptr_t super_page_extent_entry = +PA_ALWAYS_INLINE PartitionSuperPageExtentEntry* +SlotSpanMetadata::ToSuperPageExtent() const { + // SlotSpanMetadata and SuperPageExtentEntry are always in the same cage. + // But the memory layout is different from GigaCage. + uintptr_t super_page = reinterpret_cast(this) & SystemPageBaseMask(); - return reinterpret_cast< - PartitionSuperPageExtentEntry*>( - super_page_extent_entry); -#else - // Must be no-op. - return ToReadOnly(nullptr)->ToSuperPageExtent()->ToWritable(nullptr); -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) + return reinterpret_cast(super_page); } // Returns whether the pointer lies within the super page's payload area (i.e. @@ -620,15 +499,22 @@ PA_ALWAYS_INLINE bool IsWithinSuperPagePayload(uintptr_t address) { // While it is generally valid for |ptr| to be in the middle of an allocation, // care has to be taken with direct maps that span multiple super pages. This // function's behavior is undefined if |ptr| lies in a subsequent super page. -PA_ALWAYS_INLINE PartitionPageMetadata* -PartitionPageMetadata::FromAddr(uintptr_t address) { +PA_ALWAYS_INLINE PartitionPageMetadata* PartitionPageMetadata::FromAddr( + uintptr_t address, + [[maybe_unused]] const PartitionRoot* root) { + return PartitionPageMetadata::FromAddr(address, GetMetadataOffset(root)); +} + +PA_ALWAYS_INLINE PartitionPageMetadata* PartitionPageMetadata::FromAddr( + uintptr_t address, + [[maybe_unused]] std::ptrdiff_t metadata_offset) { uintptr_t super_page = address & kSuperPageBaseMask; #if PA_BUILDFLAG(DCHECKS_ARE_ON) PA_DCHECK( ReservationOffsetTable::Get(super_page).IsReservationStart(super_page)); PA_DCHECK(IsWithinSuperPagePayload(address)); -#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) +#endif uintptr_t partition_page_index = (address & kSuperPageOffsetMask) >> PartitionPageShift(); @@ -638,17 +524,36 @@ PartitionPageMetadata::FromAddr(uintptr_t address) { // for other exclusions. PA_DCHECK(partition_page_index); PA_DCHECK(partition_page_index < NumPartitionPagesPerSuperPage() - 1); - return PartitionSuperPageToMetadataArea(super_page) + partition_page_index; + return PartitionSuperPageToMetadataArea(super_page, metadata_offset) + + partition_page_index; } // Converts from a pointer to the SlotSpanMetadata object (within a super // pages's metadata) into a pointer to the beginning of the slot span. This // works on direct maps too. PA_ALWAYS_INLINE uintptr_t -SlotSpanMetadata::ToSlotSpanStart( - const SlotSpanMetadata* slot_span) { - uintptr_t pointer_as_uint = reinterpret_cast(slot_span); - uintptr_t super_page_offset = (pointer_as_uint & kSuperPageOffsetMask); +SlotSpanMetadata::ToSlotSpanStart(const SlotSpanMetadata* slot_span, + [[maybe_unused]] const PartitionRoot* root) { + return ToSlotSpanStart(slot_span, GetMetadataOffset(root)); +} + +PA_ALWAYS_INLINE uintptr_t +SlotSpanMetadata::ToSlotSpanStart(const SlotSpanMetadata* slot_span, + [[maybe_unused]] std::ptrdiff_t offset) { + uintptr_t slot_span_addr = reinterpret_cast(slot_span); +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + uintptr_t partition_page_index = + (slot_span_addr & SystemPageOffsetMask()) >> kPageMetadataShift; + uintptr_t super_page_base = + PartitionMetadataPageToSuperPage(slot_span_addr, offset) & + kSuperPageBaseMask; +#if PA_BUILDFLAG(DCHECKS_ARE_ON) + PA_DCHECK(PartitionAddressSpace::IsInMetadataRegion(slot_span_addr) || + super_page_base == (slot_span_addr & kSuperPageBaseMask)); +#endif + return super_page_base + (partition_page_index << PartitionPageShift()); +#else + uintptr_t super_page_offset = (slot_span_addr & kSuperPageOffsetMask); // A valid |page| must be past the first guard System page and within // the following metadata region. @@ -664,8 +569,9 @@ SlotSpanMetadata::ToSlotSpanStart( // pages. PA_DCHECK(partition_page_index); PA_DCHECK(partition_page_index < NumPartitionPagesPerSuperPage() - 1); - uintptr_t super_page_base = (pointer_as_uint & kSuperPageBaseMask); + uintptr_t super_page_base = slot_span_addr & kSuperPageBaseMask; return super_page_base + (partition_page_index << PartitionPageShift()); +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) } // Converts an address inside a slot span into a pointer to the SlotSpanMetadata @@ -674,10 +580,41 @@ SlotSpanMetadata::ToSlotSpanStart( // // CAUTION! For direct-mapped allocation, |address| has to be within the first // partition page. -PA_ALWAYS_INLINE SlotSpanMetadata* -SlotSpanMetadata::FromAddr(uintptr_t address) { - auto* page_metadata = - PartitionPageMetadata::FromAddr(address); +PA_ALWAYS_INLINE SlotSpanMetadata* SlotSpanMetadata::FromAddr( + uintptr_t address) { +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + std::ptrdiff_t metadata_offset = + PartitionAddressSpace::MetadataOffset(GetPool(address)); +#else + constexpr std::ptrdiff_t metadata_offset = 0; +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + return FromAddr(address, metadata_offset); +} + +PA_ALWAYS_INLINE SlotSpanMetadata* SlotSpanMetadata::FromAddr( + uintptr_t address, + [[maybe_unused]] const PartitionRoot* root) { + auto* page_metadata = PartitionPageMetadata::FromAddr(address, root); + PA_DCHECK(page_metadata->is_valid); + // Partition pages in the same slot span share the same SlotSpanMetadata + // object (located in the first PartitionPageMetadata object of that span). + // Adjust for that. + page_metadata -= page_metadata->slot_span_metadata_offset; + PA_DCHECK(page_metadata->is_valid); + PA_DCHECK(!page_metadata->slot_span_metadata_offset); + auto* slot_span = &page_metadata->slot_span_metadata; + PA_DCHECK(DeducedRootIsValid(slot_span)); + // For direct map, if |address| doesn't point within the first partition page, + // |slot_span_metadata_offset| will be 0, |page_metadata| won't get shifted, + // leaving |slot_size| at 0. + PA_DCHECK(slot_span->bucket->slot_size); + return slot_span; +} + +PA_ALWAYS_INLINE SlotSpanMetadata* SlotSpanMetadata::FromAddr( + uintptr_t address, + [[maybe_unused]] std::ptrdiff_t offset) { + auto* page_metadata = PartitionPageMetadata::FromAddr(address, offset); PA_DCHECK(page_metadata->is_valid); // Partition pages in the same slot span share the same SlotSpanMetadata // object (located in the first PartitionPageMetadata object of that span). @@ -698,12 +635,30 @@ SlotSpanMetadata::FromAddr(uintptr_t address) { // beginning of a slot. It doesn't check if the slot is actually allocated. // // This works on direct maps too. -PA_ALWAYS_INLINE SlotSpanMetadata* -SlotSpanMetadata::FromSlotStart(uintptr_t slot_start) { - auto* slot_span = FromAddr(slot_start); +PA_ALWAYS_INLINE SlotSpanMetadata* SlotSpanMetadata::FromSlotStart( + uintptr_t slot_start) { +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + std::ptrdiff_t metadata_offset = + PartitionAddressSpace::MetadataOffset(GetPool(slot_start)); +#else + constexpr std::ptrdiff_t metadata_offset = 0; +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + return FromSlotStart(slot_start, metadata_offset); +} + +PA_ALWAYS_INLINE SlotSpanMetadata* SlotSpanMetadata::FromSlotStart( + uintptr_t slot_start, + [[maybe_unused]] const PartitionRoot* root) { + return FromSlotStart(slot_start, GetMetadataOffset(root)); +} + +PA_ALWAYS_INLINE SlotSpanMetadata* SlotSpanMetadata::FromSlotStart( + uintptr_t slot_start, + [[maybe_unused]] std::ptrdiff_t offset) { + auto* slot_span = FromAddr(slot_start, offset); #if PA_BUILDFLAG(DCHECKS_ARE_ON) // Checks that the pointer is a multiple of slot size. - uintptr_t slot_span_start = ToSlotSpanStart(slot_span); + uintptr_t slot_span_start = ToSlotSpanStart(slot_span, offset); PA_DCHECK(!((slot_start - slot_span_start) % slot_span->bucket->slot_size)); #endif // PA_BUILDFLAG(DCHECKS_ARE_ON) return slot_span; @@ -713,8 +668,21 @@ SlotSpanMetadata::FromSlotStart(uintptr_t slot_start) { // an object. It doesn't check if the object is actually allocated. // // This works on direct maps too. -PA_ALWAYS_INLINE SlotSpanMetadata* -SlotSpanMetadata::FromObject(const void* object) { +PA_ALWAYS_INLINE SlotSpanMetadata* SlotSpanMetadata::FromObject( + const void* object, + [[maybe_unused]] const PartitionRoot* root) { + uintptr_t object_addr = ObjectPtr2Addr(object); + auto* slot_span = FromAddr(object_addr, root); + DCheckIsValidObjectAddress(slot_span, object_addr); + return slot_span; +} + +// Like |FromAddr|, but asserts that |object| indeed points to the beginning of +// an object. It doesn't check if the object is actually allocated. +// +// This works on direct maps too. +PA_ALWAYS_INLINE SlotSpanMetadata* SlotSpanMetadata::FromObject( + const void* object) { uintptr_t object_addr = ObjectPtr2Addr(object); auto* slot_span = FromAddr(object_addr); DCheckIsValidObjectAddress(slot_span, object_addr); @@ -726,12 +694,19 @@ SlotSpanMetadata::FromObject(const void* object) { // // CAUTION! For direct-mapped allocation, |address| has to be within the first // partition page. -PA_ALWAYS_INLINE SlotSpanMetadata* SlotSpanMetadata< - MetadataKind::kReadOnly>::FromObjectInnerAddr(uintptr_t address) { - auto* slot_span = FromAddr(address); +PA_ALWAYS_INLINE SlotSpanMetadata* SlotSpanMetadata::FromObjectInnerAddr( + uintptr_t address, + [[maybe_unused]] const PartitionRoot* root) { + return FromObjectInnerAddr(address, GetMetadataOffset(root)); +} + +PA_ALWAYS_INLINE SlotSpanMetadata* SlotSpanMetadata::FromObjectInnerAddr( + uintptr_t address, + [[maybe_unused]] std::ptrdiff_t offset) { + auto* slot_span = FromAddr(address, offset); #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 slot_span_start = ToSlotSpanStart(slot_span, offset); uintptr_t shift_from_slot_start = (address - slot_span_start) % slot_span->bucket->slot_size; DCheckIsValidShiftFromSlotStart(slot_span, shift_from_slot_start); @@ -739,38 +714,42 @@ PA_ALWAYS_INLINE SlotSpanMetadata* SlotSpanMetadata< return slot_span; } -PA_ALWAYS_INLINE SlotSpanMetadata* -SlotSpanMetadata::FromObjectInnerPtr(const void* ptr) { - return FromObjectInnerAddr(ObjectInnerPtr2Addr(ptr)); +PA_ALWAYS_INLINE SlotSpanMetadata* SlotSpanMetadata::FromObjectInnerPtr( + const void* ptr, + [[maybe_unused]] const PartitionRoot* root) { + return FromObjectInnerAddr(ObjectInnerPtr2Addr(ptr), root); } -PA_ALWAYS_INLINE void SlotSpanMetadata::SetRawSize( - size_t raw_size) { +PA_ALWAYS_INLINE SlotSpanMetadata* SlotSpanMetadata::FromObjectInnerPtr( + const void* ptr, + [[maybe_unused]] std::ptrdiff_t offset) { + return FromObjectInnerAddr(ObjectInnerPtr2Addr(ptr), offset); +} + +PA_ALWAYS_INLINE void SlotSpanMetadata::SetRawSize(size_t raw_size) { PA_DCHECK(CanStoreRawSize()); - auto* subsequent_page_metadata = GetSubsequentPageMetadata( - reinterpret_cast*>(this)); + auto* subsequent_page_metadata = + GetSubsequentPageMetadata(reinterpret_cast(this)); subsequent_page_metadata->raw_size = raw_size; } -PA_ALWAYS_INLINE size_t -SlotSpanMetadata::GetRawSize() const { +PA_ALWAYS_INLINE size_t SlotSpanMetadata::GetRawSize() const { PA_DCHECK(CanStoreRawSize()); const auto* subsequent_page_metadata = GetSubsequentPageMetadata( - reinterpret_cast*>( - this)); + reinterpret_cast(this)); return subsequent_page_metadata->raw_size; } -PA_ALWAYS_INLINE void -SlotSpanMetadata::SetFreelistHead( - FreelistEntry* new_head, - [[maybe_unused]] PartitionRoot* root) { +PA_ALWAYS_INLINE void SlotSpanMetadata::SetFreelistHead( + FreelistEntry* new_head) { #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); + const PartitionRoot* root = ToSuperPageExtent()->root; PA_DCHECK(!new_head || - (reinterpret_cast(ToReadOnly(root)) & + (PartitionMetadataPageToSuperPage(reinterpret_cast(this), + GetMetadataOffset(root)) & kSuperPageBaseMask) == (new_head_untagged & kSuperPageBaseMask)); #endif // PA_BUILDFLAG(DCHECKS_ARE_ON) freelist_head = new_head; @@ -779,8 +758,7 @@ SlotSpanMetadata::SetFreelistHead( freelist_is_sorted_ = false; } -PA_ALWAYS_INLINE FreelistEntry* -SlotSpanMetadata::PopForAlloc(size_t size) { +PA_ALWAYS_INLINE FreelistEntry* SlotSpanMetadata::PopForAlloc(size_t size) { // Not using bucket->slot_size directly as the compiler doesn't know that // |bucket->slot_size| is the same as |size|. PA_DCHECK(size == bucket->slot_size); @@ -793,9 +771,8 @@ SlotSpanMetadata::PopForAlloc(size_t size) { return result; } -PA_ALWAYS_INLINE void SlotSpanMetadata::Free( - uintptr_t slot_start, - PartitionRoot* root) +PA_ALWAYS_INLINE void SlotSpanMetadata::Free(uintptr_t slot_start, + PartitionRoot* root) // PartitionRootLock() is not defined inside partition_page.h, but // static analysis doesn't require the implementation. PA_EXCLUSIVE_LOCKS_REQUIRED(PartitionRootLock(root)) { @@ -808,14 +785,14 @@ PA_ALWAYS_INLINE void SlotSpanMetadata::Free( PA_DCHECK(!freelist_head || entry != freelist_head->GetNext(bucket->slot_size)); entry->SetNext(freelist_head); - SetFreelistHead(entry, root); + SetFreelistHead(entry); // A best effort double-free check. Works only on empty slot spans. PA_CHECK(num_allocated_slots); --num_allocated_slots; // If the span is marked full, or became empty, take the slow path to update // internal state. if (marked_full || num_allocated_slots == 0) [[unlikely]] { - FreeSlowPath(1, root); + FreeSlowPath(1); } else { // All single-slot allocations must go through the slow path to // correctly update the raw size. @@ -823,11 +800,11 @@ PA_ALWAYS_INLINE void SlotSpanMetadata::Free( } } -PA_ALWAYS_INLINE void SlotSpanMetadata::AppendFreeList( - FreelistEntry* head, - FreelistEntry* tail, - size_t number_of_freed, - PartitionRoot* root) PA_EXCLUSIVE_LOCKS_REQUIRED(PartitionRootLock(root)) { +PA_ALWAYS_INLINE void SlotSpanMetadata::AppendFreeList(FreelistEntry* head, + FreelistEntry* tail, + size_t number_of_freed, + PartitionRoot* root) + PA_EXCLUSIVE_LOCKS_REQUIRED(PartitionRootLock(root)) { #if PA_BUILDFLAG(DCHECKS_ARE_ON) DCheckRootLockIsAcquired(root); PA_DCHECK(!(tail->GetNext(bucket->slot_size))); @@ -842,25 +819,22 @@ PA_ALWAYS_INLINE void SlotSpanMetadata::AppendFreeList( entry = entry->GetNext(bucket->slot_size), ++number_of_entries) { uintptr_t untagged_entry = UntagPtr(entry); // Check that all entries belong to this slot span. - PA_DCHECK(SlotSpanMetadata::ToSlotSpanStart( - ToReadOnly(root)) <= untagged_entry); + PA_DCHECK(ToSlotSpanStart(this, root) <= untagged_entry); PA_DCHECK(untagged_entry < - SlotSpanMetadata::ToSlotSpanStart( - ToReadOnly(root)) + - bucket->get_bytes_per_span()); + ToSlotSpanStart(this, root) + bucket->get_bytes_per_span()); } PA_DCHECK(number_of_entries == number_of_freed); } #endif // PA_BUILDFLAG(DCHECKS_ARE_ON) tail->SetNext(freelist_head); - SetFreelistHead(head, root); + SetFreelistHead(head); PA_DCHECK(num_allocated_slots >= number_of_freed); num_allocated_slots -= number_of_freed; // If the span is marked full, or became empty, take the slow path to update // internal state. if (marked_full || num_allocated_slots == 0) [[unlikely]] { - FreeSlowPath(number_of_freed, root); + FreeSlowPath(number_of_freed); } else { // All single-slot allocations must go through the slow path to // correctly update the raw size. @@ -868,8 +842,7 @@ PA_ALWAYS_INLINE void SlotSpanMetadata::AppendFreeList( } } -PA_ALWAYS_INLINE bool SlotSpanMetadata::is_active() - const { +PA_ALWAYS_INLINE bool SlotSpanMetadata::is_active() const { PA_DCHECK(this != get_sentinel_slot_span()); bool ret = (num_allocated_slots > 0 && (freelist_head || num_unprovisioned_slots)); @@ -880,8 +853,7 @@ PA_ALWAYS_INLINE bool SlotSpanMetadata::is_active() return ret; } -PA_ALWAYS_INLINE bool SlotSpanMetadata::is_full() - const { +PA_ALWAYS_INLINE bool SlotSpanMetadata::is_full() const { PA_DCHECK(this != get_sentinel_slot_span()); bool ret = (num_allocated_slots == bucket->get_slots_per_span()); if (ret) { @@ -892,29 +864,35 @@ PA_ALWAYS_INLINE bool SlotSpanMetadata::is_full() return ret; } -PA_ALWAYS_INLINE bool SlotSpanMetadata::is_empty() - const { +PA_ALWAYS_INLINE bool SlotSpanMetadata::is_empty() const { PA_DCHECK(this != get_sentinel_slot_span()); - return is_empty_internal(); + bool ret = (!num_allocated_slots && freelist_head); + if (ret) { + PA_DCHECK(!marked_full); + } + return ret; } -PA_ALWAYS_INLINE bool -SlotSpanMetadata::is_decommitted() const { +PA_ALWAYS_INLINE bool SlotSpanMetadata::is_decommitted() const { PA_DCHECK(this != get_sentinel_slot_span()); - return is_decommitted_internal(); + bool ret = (!num_allocated_slots && !freelist_head); + if (ret) { + PA_DCHECK(!marked_full); + PA_DCHECK(!num_unprovisioned_slots); + PA_DCHECK(!in_empty_cache_); + } + return ret; } -PA_ALWAYS_INLINE void SlotSpanMetadata::Reset() { -#if PA_BUILDFLAG(DCHECKS_ARE_ON) - PA_DCHECK(is_decommitted_internal()); -#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) +PA_ALWAYS_INLINE void SlotSpanMetadata::Reset() { + PA_DCHECK(is_decommitted()); 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); PA_DCHECK(num_unprovisioned_slots); - IncrementNumberOfNonemptySlotSpans(); + ToSuperPageExtent()->IncrementNumberOfNonemptySlotSpans(); next_slot_span = nullptr; } @@ -922,21 +900,21 @@ PA_ALWAYS_INLINE void SlotSpanMetadata::Reset() { // 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, Callback callback) { +void IterateSlotSpans(uintptr_t super_page, + [[maybe_unused]] const PartitionRoot* root, + Callback callback) { #if PA_BUILDFLAG(DCHECKS_ARE_ON) PA_DCHECK(!(super_page % kSuperPageAlignment)); - auto* extent_entry = PartitionSuperPageToExtent(super_page); + auto* extent_entry = PartitionSuperPageToExtent(super_page, root); DCheckRootLockIsAcquired(extent_entry->root); #endif // PA_BUILDFLAG(DCHECKS_ARE_ON) auto* const first_page_metadata = - PartitionPageMetadata::FromAddr( - SuperPagePayloadBegin(super_page)); - auto* const last_page_metadata = - PartitionPageMetadata::FromAddr( - SuperPagePayloadEnd(super_page) - PartitionPageSize()); - PartitionPageMetadata* page_metadata = nullptr; - SlotSpanMetadata* slot_span = nullptr; + PartitionPageMetadata::FromAddr(SuperPagePayloadBegin(super_page), root); + auto* const last_page_metadata = PartitionPageMetadata::FromAddr( + SuperPagePayloadEnd(super_page) - PartitionPageSize(), root); + PartitionPageMetadata* page_metadata = nullptr; + SlotSpanMetadata* slot_span = nullptr; for (page_metadata = first_page_metadata; page_metadata <= last_page_metadata;) { PA_DCHECK(!page_metadata @@ -963,8 +941,7 @@ void IterateSlotSpans(uintptr_t super_page, Callback callback) { // Just a quick check that the search ended at a valid slot span and there // was no unnecessary iteration over gaps afterwards. PA_DCHECK(page_metadata == - reinterpret_cast*>( - slot_span) + + reinterpret_cast(slot_span) + slot_span->bucket->get_pages_per_slot_span()); } @@ -980,19 +957,22 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) SlotStart { public: template PA_ALWAYS_INLINE static SlotStart FromUntaggedAddr( - uintptr_t untagged_slot_start) { + uintptr_t untagged_slot_start, + [[maybe_unused]] const PartitionRoot* root) { auto result = SlotStart(untagged_slot_start); if constexpr (enforce) { - result.CheckIsSlotStart(); + result.CheckIsSlotStart(root); } return result; } template - PA_ALWAYS_INLINE static SlotStart FromObject(const void* tagged_object) { + PA_ALWAYS_INLINE static SlotStart FromObject( + const void* tagged_object, + [[maybe_unused]] const PartitionRoot* root) { uintptr_t untagged_slot_start = internal::UntagAddr(reinterpret_cast(tagged_object)); - return SlotStart::FromUntaggedAddr(untagged_slot_start); + return SlotStart::FromUntaggedAddr(untagged_slot_start, root); } // Tagging objects is not free. Avoid calling this repeatedly. @@ -1001,13 +981,11 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) SlotStart { } PA_ALWAYS_INLINE - void CheckIsSlotStart() const { + void CheckIsSlotStart([[maybe_unused]] const PartitionRoot* root) const { auto* slot_span_metadata = - SlotSpanMetadata::FromAddr( - untagged_slot_start_); + SlotSpanMetadata::FromAddr(untagged_slot_start_, root); uintptr_t slot_span = - SlotSpanMetadata::ToSlotSpanStart( - slot_span_metadata); + SlotSpanMetadata::ToSlotSpanStart(slot_span_metadata, root); PA_CHECK(!((untagged_slot_start_ - slot_span) % slot_span_metadata->bucket->slot_size)); } 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 68090efc49..4f1a354af3 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_PAGE_CONSTANTS_H_ #define PARTITION_ALLOC_PARTITION_PAGE_CONSTANTS_H_ 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 636ace1b93..280ba23648 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_root.h" #include @@ -27,7 +32,6 @@ #include "partition_alloc/partition_cookie.h" #include "partition_alloc/partition_oom.h" #include "partition_alloc/partition_page.h" -#include "partition_alloc/partition_superpage_extent_entry.h" #include "partition_alloc/reservation_offset_table.h" #include "partition_alloc/spinning_mutex.h" #include "partition_alloc/tagging.h" @@ -49,9 +53,6 @@ #if PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS) #include -#if PA_CONFIG(ENABLE_SHADOW_METADATA) -#include -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) #endif // PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS) #if defined(__MUSL__) @@ -61,8 +62,8 @@ namespace partition_alloc::internal { #if PA_BUILDFLAG(RECORD_ALLOC_INFO) -// Even if this is not hidden behind a PA_BUILDFLAG, it should not use any -// memory when recording is disabled, since it ends up in the .bss section. +// Even if this is not hidden behind a BUILDFLAG, it should not use any memory +// when recording is disabled, since it ends up in the .bss section. AllocInfo g_allocs = {}; void RecordAllocOrFree(uintptr_t addr, size_t size) { @@ -86,8 +87,13 @@ PtrPosWithinAlloc IsPtrWithinSameAlloc(uintptr_t orig_address, // Zero it just in case, to catch errors. orig_address = 0; - auto* slot_span = internal::SlotSpanMetadata< - internal::MetadataKind::kReadOnly>::FromSlotStart(slot_start); +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + std::ptrdiff_t offset = internal::PartitionAddressSpace::MetadataOffset( + pool_handle::kBRPPoolHandle); +#else + std::ptrdiff_t offset = 0; +#endif + auto* slot_span = SlotSpanMetadata::FromSlotStart(slot_start, offset); 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. @@ -113,10 +119,6 @@ PtrPosWithinAlloc IsPtrWithinSameAlloc(uintptr_t orig_address, namespace partition_alloc { -#if PA_CONFIG(ENABLE_SHADOW_METADATA) -internal::SharedMutex PartitionRoot::g_shadow_metadata_init_mutex_; -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) - #if PA_CONFIG(USE_PARTITION_ROOT_ENUMERATOR) namespace { @@ -215,9 +217,7 @@ class PartitionRootEnumerator { #endif // PA_USE_PARTITION_ROOT_ENUMERATOR -#if (PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \ - PA_CONFIG(HAS_ATFORK_HANDLER)) || \ - PA_CONFIG(ENABLE_SHADOW_METADATA) +#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && PA_CONFIG(HAS_ATFORK_HANDLER) namespace { @@ -243,9 +243,8 @@ void UnlockOrReinitRoot(PartitionRoot* root, } } // namespace - -#endif // (PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && - // PA_CONFIG(HAS_ATFORK_HANDLER)) || PA_CONFIG(ENABLE_SHADOW_METADATA) +#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && + // PA_CONFIG(HAS_ATFORK_HANDLER) #if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) @@ -256,8 +255,8 @@ namespace { // PA_NO_THREAD_SAFETY_ANALYSIS: acquires the lock and doesn't release it, by // design. void BeforeForkInParent() PA_NO_THREAD_SAFETY_ANALYSIS { - // PartitionRoot::GetLock() is private. So use - // g_root_enumerator_lock here. + // PartitionRoot::GetLock() is private. So use + // g_root_enumerator_lock here. g_root_enumerator_lock.Acquire(); internal::PartitionRootEnumerator::Instance().Enumerate( LockRoot, false, @@ -367,72 +366,6 @@ void PartitionAllocMallocHookOnAfterForkInChild() { #endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) -#if PA_CONFIG(ENABLE_SHADOW_METADATA) -namespace { - -void MakeSuperPageExtentEntriesShared(PartitionRoot* root, - internal::PoolHandleMask mask) - PA_NO_THREAD_SAFETY_ANALYSIS { - PA_DCHECK(root); - // Regardless of root->ChoosePool(), no chance if shadow_pool_offset_ is - // non-zero. - if (root->settings.shadow_pool_offset_) { - return; - } - - switch (root->ChoosePool()) { - case internal::kRegularPoolHandle: - if (!ContainsFlags(mask, internal::PoolHandleMask::kRegular)) { - return; - } - root->settings.shadow_pool_offset_ = - internal::PartitionAddressSpace::RegularPoolShadowOffset(); - break; - case internal::kBRPPoolHandle: - if (!ContainsFlags(mask, internal::PoolHandleMask::kBRP)) { - return; - } - root->settings.shadow_pool_offset_ = - internal::PartitionAddressSpace::BRPPoolShadowOffset(); - break; - case internal::kConfigurablePoolHandle: - if (!ContainsFlags(mask, internal::PoolHandleMask::kConfigurable)) { - return; - } - root->settings.shadow_pool_offset_ = - internal::PartitionAddressSpace::ConfigurablePoolShadowOffset(); - break; - default: - return; - } - - // For normal-bucketed. - for (const internal::PartitionSuperPageExtentEntry< - internal::MetadataKind::kReadOnly>* extent = root->first_extent; - extent != nullptr; extent = extent->next) { - // The page which contains the extent is in-used and shared mapping. - uintptr_t super_page = SuperPagesBeginFromExtent(extent); - for (size_t i = 0; i < extent->number_of_consecutive_super_pages; ++i) { - internal::PartitionAddressSpace::MapMetadata(super_page, - /*copy_metadata=*/true); - super_page += kSuperPageSize; - } - PA_DCHECK(extent->root == root); - } - - // For direct-mapped. - for (const internal::PartitionDirectMapExtent< - internal::MetadataKind::kReadOnly>* extent = root->direct_map_list; - extent != nullptr; extent = extent->next_extent) { - internal::PartitionAddressSpace::MapMetadata( - reinterpret_cast(extent) & internal::kSuperPageBaseMask, - /*copy_metadata=*/true); - } -} - -} // namespace -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) - namespace internal { namespace { @@ -462,10 +395,9 @@ MinConservativePurgeableSlotSize() { // If `accounting_only` is set to true, no action is performed and the function // merely returns the number of bytes in the would-be discarded pages. PA_NOPROFILE -static size_t PartitionPurgeSlotSpan( - PartitionRoot* root, - internal::SlotSpanMetadata* slot_span, - bool accounting_only) +static size_t PartitionPurgeSlotSpan(PartitionRoot* root, + internal::SlotSpanMetadata* slot_span, + bool accounting_only) PA_EXCLUSIVE_LOCKS_REQUIRED(internal::PartitionRootLock(root)) { const internal::PartitionBucket* bucket = slot_span->bucket; size_t slot_size = bucket->slot_size; @@ -482,8 +414,8 @@ static size_t PartitionPurgeSlotSpan( RoundUpToSystemPage(slot_span->GetUtilizedSlotSize())); discardable_bytes = bucket->slot_size - utilized_slot_size; if (discardable_bytes && !accounting_only) { - uintptr_t slot_span_start = internal::SlotSpanMetadata< - internal::MetadataKind::kReadOnly>::ToSlotSpanStart(slot_span); + uintptr_t slot_span_start = + internal::SlotSpanMetadata::ToSlotSpanStart(slot_span, root); uintptr_t committed_data_end = slot_span_start + utilized_slot_size; ScopedSyscallTimer timer{root}; DiscardSystemPages(committed_data_end, discardable_bytes); @@ -520,8 +452,8 @@ static size_t PartitionPurgeSlotSpan( size_t last_slot = static_cast(-1); #endif std::fill_n(slot_usage.begin(), num_provisioned_slots, 1); - uintptr_t slot_span_start = internal::SlotSpanMetadata< - internal::MetadataKind::kReadOnly>::ToSlotSpanStart(slot_span); + uintptr_t slot_span_start = + internal::SlotSpanMetadata::ToSlotSpanStart(slot_span, root); // First, walk the freelist for this slot span and make a bitmap of which // slots are not in use. for (FreelistEntry* entry = slot_span->get_freelist_head(); entry; @@ -596,8 +528,7 @@ static size_t PartitionPurgeSlotSpan( size_t new_unprovisioned_slots = truncated_slots + slot_span->num_unprovisioned_slots; PA_DCHECK(new_unprovisioned_slots <= bucket->get_slots_per_span()); - slot_span->ToWritable(root)->num_unprovisioned_slots = - new_unprovisioned_slots; + slot_span->num_unprovisioned_slots = new_unprovisioned_slots; size_t num_new_freelist_entries = 0; internal::FreelistEntry* back = nullptr; @@ -626,7 +557,7 @@ static size_t PartitionPurgeSlotSpan( if (num_new_freelist_entries) { back->SetNext(entry); } else { - slot_span->ToWritable(root)->SetFreelistHead(entry, root); + slot_span->SetFreelistHead(entry); } back = entry; num_new_freelist_entries++; @@ -651,7 +582,7 @@ static size_t PartitionPurgeSlotSpan( if (num_new_freelist_entries) { back->SetNext(entry); } else { - slot_span->ToWritable(root)->SetFreelistHead(entry, root); + slot_span->SetFreelistHead(entry); } skipped = false; } @@ -674,7 +605,7 @@ static size_t PartitionPurgeSlotSpan( #endif } else { PA_DCHECK(!back); - slot_span->ToWritable(root)->SetFreelistHead(nullptr, root); + slot_span->SetFreelistHead(nullptr); } PA_DCHECK(num_new_freelist_entries == num_provisioned_slots - slot_span->num_allocated_slots); @@ -775,24 +706,19 @@ static void PartitionPurgeBucket(PartitionRoot* root, internal::PartitionBucket* bucket) PA_EXCLUSIVE_LOCKS_REQUIRED(internal::PartitionRootLock(root)) { if (bucket->active_slot_spans_head != - internal::SlotSpanMetadata< - internal::MetadataKind::kReadOnly>::get_sentinel_slot_span()) { - for (internal::SlotSpanMetadata* - slot_span = bucket->active_slot_spans_head; + internal::SlotSpanMetadata::get_sentinel_slot_span()) { + for (internal::SlotSpanMetadata* slot_span = bucket->active_slot_spans_head; slot_span; slot_span = slot_span->next_slot_span) { - PA_DCHECK( - slot_span != - internal::SlotSpanMetadata< - internal::MetadataKind::kReadOnly>::get_sentinel_slot_span()); + PA_DCHECK(slot_span != + internal::SlotSpanMetadata::get_sentinel_slot_span()); PartitionPurgeSlotSpan(root, slot_span, false); } } } -static void PartitionDumpSlotSpanStats( - PartitionBucketMemoryStats* stats_out, - PartitionRoot* root, - internal::SlotSpanMetadata* slot_span) +static void PartitionDumpSlotSpanStats(PartitionBucketMemoryStats* stats_out, + PartitionRoot* root, + internal::SlotSpanMetadata* slot_span) PA_EXCLUSIVE_LOCKS_REQUIRED(internal::PartitionRootLock(root)) { uint16_t bucket_num_slots = slot_span->bucket->get_slots_per_span(); @@ -832,13 +758,12 @@ static void PartitionDumpBucketStats(PartitionBucketMemoryStats* stats_out, PA_EXCLUSIVE_LOCKS_REQUIRED(internal::PartitionRootLock(root)) { PA_DCHECK(!bucket->is_direct_mapped()); stats_out->is_valid = false; - // If the active slot span list is empty (==internal::SlotSpanMetadata< - // internal::MetadataKind::kReadOnly>::get_sentinel_slot_span()), - // the bucket might still need to be reported if it has a list of empty, - // decommitted or full slot spans. + // If the active slot span list is empty (== + // internal::SlotSpanMetadata::get_sentinel_slot_span()), the bucket might + // still need to be reported if it has a list of empty, decommitted or full + // slot spans. if (bucket->active_slot_spans_head == - internal::SlotSpanMetadata< - internal::MetadataKind::kReadOnly>::get_sentinel_slot_span() && + internal::SlotSpanMetadata::get_sentinel_slot_span() && !bucket->empty_slot_spans_head && !bucket->decommitted_slot_spans_head && !bucket->num_full_slot_spans) { return; @@ -858,29 +783,24 @@ static void PartitionDumpBucketStats(PartitionBucketMemoryStats* stats_out, stats_out->resident_bytes = bucket->num_full_slot_spans * stats_out->allocated_slot_span_size; - for (internal::SlotSpanMetadata* - slot_span = bucket->empty_slot_spans_head; + for (internal::SlotSpanMetadata* slot_span = bucket->empty_slot_spans_head; slot_span; slot_span = slot_span->next_slot_span) { PA_DCHECK(slot_span->is_empty() || slot_span->is_decommitted()); PartitionDumpSlotSpanStats(stats_out, root, slot_span); } - for (internal::SlotSpanMetadata* - slot_span = bucket->decommitted_slot_spans_head; + for (internal::SlotSpanMetadata* slot_span = + bucket->decommitted_slot_spans_head; slot_span; slot_span = slot_span->next_slot_span) { PA_DCHECK(slot_span->is_decommitted()); PartitionDumpSlotSpanStats(stats_out, root, slot_span); } if (bucket->active_slot_spans_head != - internal::SlotSpanMetadata< - internal::MetadataKind::kReadOnly>::get_sentinel_slot_span()) { - for (internal::SlotSpanMetadata* - slot_span = bucket->active_slot_spans_head; + internal::SlotSpanMetadata::get_sentinel_slot_span()) { + for (internal::SlotSpanMetadata* slot_span = bucket->active_slot_spans_head; slot_span; slot_span = slot_span->next_slot_span) { - PA_DCHECK( - slot_span != - internal::SlotSpanMetadata< - internal::MetadataKind::kReadOnly>::get_sentinel_slot_span()); + PA_DCHECK(slot_span != + internal::SlotSpanMetadata::get_sentinel_slot_span()); PartitionDumpSlotSpanStats(stats_out, root, slot_span); } } @@ -890,13 +810,13 @@ static void PartitionDumpBucketStats(PartitionBucketMemoryStats* stats_out, void DCheckIfManagedByPartitionAllocBRPPool(uintptr_t address) { PA_DCHECK(IsManagedByPartitionAllocBRPPool(address)); } -#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) +#endif #if PA_BUILDFLAG(ENABLE_THREAD_ISOLATION) void PartitionAllocThreadIsolationInit(ThreadIsolationOption thread_isolation) { #if PA_BUILDFLAG(DCHECKS_ARE_ON) ThreadIsolationSettings::settings.enabled = true; -#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) +#endif PartitionAddressSpace::InitThreadIsolatedPool(thread_isolation); // Call WriteProtectThreadIsolatedGlobals last since we might not have write // permissions to to globals afterwards. @@ -992,39 +912,48 @@ void PartitionRoot::DestructForTesting() #else PA_DCHECK(pool_handle <= internal::kNumPools); #endif - +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + std::ptrdiff_t metadata_offset = MetadataOffset(); + bool must_decommit_metadata = MetadataOffset() & internal::kSuperPageBaseMask; +#endif { auto* curr = first_extent; while (curr != nullptr) { auto* next = curr->next; - uintptr_t address = SuperPagesBeginFromExtent(curr); - size_t size = - internal::kSuperPageSize * curr->number_of_consecutive_super_pages; + uintptr_t super_page = SuperPagesBeginFromExtent(curr); + size_t num_super_pages = curr->number_of_consecutive_super_pages; + size_t size = internal::kSuperPageSize * num_super_pages; #if !PA_BUILDFLAG(HAS_64_BIT_POINTERS) internal::AddressPoolManager::GetInstance().MarkUnused(pool_handle, - address, size); + super_page, size); #endif - internal::AddressPoolManager::GetInstance().UnreserveAndDecommit( - pool_handle, address, size); -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - if (internal::PartitionAddressSpace::IsShadowMetadataEnabled( - pool_handle)) { - internal::PartitionAddressSpace::UnmapShadowMetadata(address, - pool_handle); +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + if (must_decommit_metadata) { + uintptr_t metadata_start = internal::PartitionSuperPageToMetadataPage( + super_page, metadata_offset); + for (size_t index = 0; index < num_super_pages; ++index) { + DecommitAndZeroSystemPages(metadata_start, SystemPageSize(), + PageTag::kPartitionAlloc); + metadata_start += internal::kSuperPageSize; + } } -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + internal::AddressPoolManager::GetInstance().UnreserveAndDecommit( + pool_handle, super_page, size); curr = next; } first_extent = current_extent = nullptr; } -#if PA_CONFIG(ENABLE_SHADOW_METADATA) +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) // Decommit direct-mapped allocations too. - if (internal::PartitionAddressSpace::IsShadowMetadataEnabled(pool_handle)) { + { auto* curr = direct_map_list; while (curr != nullptr) { auto* next = curr->next_extent; uintptr_t reservation_start = internal::base::bits::AlignDown( - reinterpret_cast(curr), kSuperPageSize); + internal::PartitionMetadataPageToSuperPage( + reinterpret_cast(curr), metadata_offset), + internal::kSuperPageAlignment); size_t reservation_size = curr->reservation_size; GetReservationOffsetTable().SetNotAllocatedTag(reservation_start, @@ -1034,17 +963,21 @@ void PartitionRoot::DestructForTesting() pool_handle, reservation_start, reservation_size); #endif // !PA_BUILDFLAG(HAS_64_BIT_POINTERS) + if (must_decommit_metadata) { + uintptr_t metadata_start = internal::PartitionSuperPageToMetadataPage( + reservation_start, metadata_offset); + DecommitAndZeroSystemPages(metadata_start, SystemPageSize(), + PageTag::kPartitionAlloc); + } + // After resetting the table entries, unreserve and decommit the memory. internal::AddressPoolManager::GetInstance().UnreserveAndDecommit( pool_handle, reservation_start, reservation_size); - - internal::PartitionAddressSpace::UnmapShadowMetadata(reservation_start, - pool_handle); curr = next; } direct_map_list = nullptr; } -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) } #if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) && \ @@ -1205,8 +1138,8 @@ void PartitionRoot::Init(PartitionOptions opts) { // We mark the sentinel slot span as free to make sure it is skipped by our // logic to find a new active slot span. memset(&sentinel_bucket, 0, sizeof(sentinel_bucket)); - sentinel_bucket.active_slot_spans_head = internal::SlotSpanMetadata< - internal::MetadataKind::kReadOnly>::get_sentinel_slot_span_non_const(); + sentinel_bucket.active_slot_spans_head = + internal::SlotSpanMetadata::get_sentinel_slot_span_non_const(); // This is a "magic" value so we can test if a root pointer is valid. inverted_self = ~reinterpret_cast(this); @@ -1240,27 +1173,10 @@ void PartitionRoot::Init(PartitionOptions opts) { internal::PartitionRootEnumerator::Instance().Register(this); #endif -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - if (internal::PartitionAddressSpace::IsShadowMetadataEnabled( - settings.pool_handle)) { - switch (settings.pool_handle) { - case internal::kRegularPoolHandle: - settings.shadow_pool_offset_ = - internal::PartitionAddressSpace::RegularPoolShadowOffset(); - break; - case internal::kBRPPoolHandle: - settings.shadow_pool_offset_ = - internal::PartitionAddressSpace::BRPPoolShadowOffset(); - break; - case internal::kConfigurablePoolHandle: - settings.shadow_pool_offset_ = - internal::PartitionAddressSpace::ConfigurablePoolShadowOffset(); - break; - default: - break; - } - } -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + settings.metadata_offset_ = + internal::PartitionAddressSpace::MetadataOffset(settings.pool_handle); +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) initialized = true; } @@ -1319,15 +1235,19 @@ void PartitionRoot::EnableThreadCacheIfSupported() { } bool PartitionRoot::TryReallocInPlaceForDirectMap( - internal::SlotSpanMetadata* slot_span, + internal::SlotSpanMetadata* slot_span, size_t requested_size) { +#if PA_BUILDFLAG(DCHECKS_ARE_ON) PA_DCHECK(slot_span->bucket->is_direct_mapped()); // Slot-span metadata isn't MTE-tagged. + // Metadata may not be placed inside GigaCage. PA_DCHECK(GetReservationOffsetTable().IsManagedByDirectMap( - reinterpret_cast(slot_span))); + internal::PartitionMetadataPageToSuperPage( + reinterpret_cast(slot_span), MetadataOffset()))); +#endif size_t raw_size = AdjustSizeForExtrasAdd(requested_size); - auto* extent = ReadOnlyDirectMapExtent::FromSlotSpanMetadata(slot_span); + auto* extent = DirectMapExtent::FromSlotSpanMetadata(slot_span); size_t current_reservation_size = extent->reservation_size; // Calculate the new reservation size the way PartitionDirectMap() would, but // skip the alignment, because this call isn't requesting it. @@ -1364,8 +1284,8 @@ bool PartitionRoot::TryReallocInPlaceForDirectMap( // bucket->slot_size is the currently committed size of the allocation. size_t current_slot_size = slot_span->bucket->slot_size; size_t current_usable_size = GetSlotUsableSize(slot_span); - uintptr_t slot_start = internal::SlotSpanMetadata< - internal::MetadataKind::kReadOnly>::ToSlotSpanStart(slot_span); + uintptr_t slot_start = + internal::SlotSpanMetadata::ToSlotSpanStart(slot_span, this); // This is the available part of the reservation up to which the new // allocation can grow. size_t available_reservation_size = @@ -1415,15 +1335,8 @@ bool PartitionRoot::TryReallocInPlaceForDirectMap( DecreaseTotalSizeOfAllocatedBytes(reinterpret_cast(slot_span), slot_span->bucket->slot_size); - slot_span->ToWritable(this)->SetRawSize(raw_size); -#if !PA_CONFIG(ENABLE_SHADOW_METADATA) + slot_span->SetRawSize(raw_size); slot_span->bucket->slot_size = new_slot_size; -#else - internal::PartitionBucket* writable_bucket = - reinterpret_cast( - reinterpret_cast(slot_span->bucket) + ShadowPoolOffset()); - writable_bucket->slot_size = new_slot_size; -#endif // !PA_CONFIG(ENABLE_SHADOW_METADATA) IncreaseTotalSizeOfAllocatedBytes(reinterpret_cast(slot_span), slot_span->bucket->slot_size, raw_size); @@ -1450,7 +1363,7 @@ bool PartitionRoot::TryReallocInPlaceForDirectMap( bool PartitionRoot::TryReallocInPlaceForNormalBuckets( void* object, - internal::SlotSpanMetadata* slot_span, + internal::SlotSpanMetadata* slot_span, size_t new_size) { uintptr_t slot_start = ObjectToSlotStart(object); PA_DCHECK(GetReservationOffsetTable().IsManagedByNormalBuckets(slot_start)); @@ -1477,7 +1390,7 @@ bool PartitionRoot::TryReallocInPlaceForNormalBuckets( #endif // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) && // PA_BUILDFLAG(DCHECKS_ARE_ON) size_t new_raw_size = AdjustSizeForExtrasAdd(new_size); - slot_span->ToWritable(this)->SetRawSize(new_raw_size); + slot_span->SetRawSize(new_raw_size); #if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) && PA_BUILDFLAG(DCHECKS_ARE_ON) if (brp_enabled()) [[likely]] { internal::InSlotMetadata* new_ref_count = @@ -1563,10 +1476,10 @@ void PartitionRoot::PurgeMemory(int flags) { // Do it at the end, as the actions above change the status of slot // spans (e.g. empty -> decommitted). - bucket.MaintainActiveList(this); + bucket.MaintainActiveList(); if (sort_active_slot_spans_) { - bucket.SortActiveSlotSpans(this); + bucket.SortActiveSlotSpans(); } // Checking at the end to make sure we make progress by processing at // least one bucket. @@ -1597,11 +1510,10 @@ void PartitionRoot::ShrinkEmptySlotSpansRing(size_t limit) { int16_t index = global_empty_slot_span_ring_index; int16_t starting_index = index; while (empty_slot_spans_dirty_bytes > limit) { - internal::SlotSpanMetadata* slot_span = - global_empty_slot_span_ring[index]; + internal::SlotSpanMetadata* slot_span = global_empty_slot_span_ring[index]; // The ring is not always full, may be nullptr. if (slot_span) { - slot_span->ToWritable(this)->DecommitIfPossible(this); + slot_span->DecommitIfPossible(this); // DecommitIfPossible() should set the buffer to null. PA_DCHECK(!global_empty_slot_span_ring[index]); } @@ -1694,7 +1606,7 @@ void PartitionRoot::DumpStats(const char* partition_name, } } - for (const ReadOnlyDirectMapExtent* extent = direct_map_list; + for (const DirectMapExtent* extent = direct_map_list; extent && num_direct_mapped_allocations < kMaxReportableDirectMaps; extent = extent->next_extent, ++num_direct_mapped_allocations) { PA_DCHECK(!extent->next_extent || @@ -1787,10 +1699,8 @@ void PartitionRoot::ResetForTesting(bool allow_leaks) { unsigned num_allocated_slots = 0; for (Bucket& bucket : buckets) { if (bucket.active_slot_spans_head != - internal::SlotSpanMetadata< - internal::MetadataKind::kReadOnly>::get_sentinel_slot_span()) { - for (const internal::SlotSpanMetadata< - internal::MetadataKind::kReadOnly>* slot_span = + internal::SlotSpanMetadata::get_sentinel_slot_span()) { + for (const internal::SlotSpanMetadata* slot_span = bucket.active_slot_spans_head; slot_span; slot_span = slot_span->next_slot_span) { num_allocated_slots += slot_span->num_allocated_slots; @@ -1819,8 +1729,8 @@ void PartitionRoot::ResetForTesting(bool allow_leaks) { #endif // PA_CONFIG(USE_PARTITION_ROOT_ENUMERATOR) for (Bucket& bucket : buckets) { - bucket.active_slot_spans_head = internal::SlotSpanMetadata< - internal::MetadataKind::kReadOnly>::get_sentinel_slot_span_non_const(); + bucket.active_slot_spans_head = + internal::SlotSpanMetadata::get_sentinel_slot_span_non_const(); bucket.empty_slot_spans_head = nullptr; bucket.decommitted_slot_spans_head = nullptr; bucket.num_full_slot_spans = 0; @@ -1928,7 +1838,7 @@ void PartitionRoot::SetSortActiveSlotSpansEnabled(bool new_value) { #if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) PA_NOINLINE void PartitionRoot::QuarantineForBrp( - internal::SlotSpanMetadata* slot_span, + const internal::SlotSpanMetadata* slot_span, void* object) { auto usable_size = GetSlotUsableSize(slot_span); auto hook = PartitionAllocHooks::GetQuarantineOverrideHook(); @@ -1944,38 +1854,6 @@ PA_NOINLINE void PartitionRoot::QuarantineForBrp( } #endif // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) -// static -#if PA_CONFIG(ENABLE_SHADOW_METADATA) -void PartitionRoot::EnableShadowMetadata(internal::PoolHandleMask mask) { -#if PA_BUILDFLAG(IS_LINUX) - // TODO(crbug.com/40238514): implement ModuleCache() or something to - // load required shared libraries in advance. - // Since memfd_create() causes dlsym(), it is not possible to invoke - // memfd_create() while PartitionRoot-s are locked. - // So invoke memfd_create() here and invoke dysym() in advance. - // This is required to enable ShadowMetadata on utility processes. - { close(memfd_create("module_cache", MFD_CLOEXEC)); } -#endif - internal::UniqueLock unique_lock(g_shadow_metadata_init_mutex_); - - internal::ScopedGuard guard(g_root_enumerator_lock); - // Must lock all PartitionRoot-s and ThreadCache. - internal::PartitionRootEnumerator::Instance().Enumerate( - LockRoot, false, - internal::PartitionRootEnumerator::EnumerateOrder::kNormal); - { - internal::ScopedGuard thread_cache_guard(ThreadCacheRegistry::GetLock()); - internal::PartitionAddressSpace::InitShadowMetadata(mask); - internal::PartitionRootEnumerator::Instance().Enumerate( - MakeSuperPageExtentEntriesShared, mask, - internal::PartitionRootEnumerator::EnumerateOrder::kNormal); - } - internal::PartitionRootEnumerator::Instance().Enumerate( - UnlockOrReinitRoot, false, - internal::PartitionRootEnumerator::EnumerateOrder::kReverse); -} -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) - // static void PartitionRoot::CheckMetadataIntegrity(const void* ptr) { uintptr_t address = internal::ObjectInnerPtr2Addr(ptr); @@ -1984,10 +1862,8 @@ void PartitionRoot::CheckMetadataIntegrity(const void* ptr) { return; } - auto* root = FromAddrInFirstSuperpage(address); - const internal::ReservationOffsetTable& reservation_offset = - root->GetReservationOffsetTable(); + internal::ReservationOffsetTable::Get(address); if (reservation_offset.IsManagedByDirectMap(address)) { // OOB for direct-mapped allocations is likely immediate crash. // No extra benefit from additional checks. @@ -1995,14 +1871,15 @@ void PartitionRoot::CheckMetadataIntegrity(const void* ptr) { } PA_CHECK(reservation_offset.IsManagedByNormalBuckets(address)); - ReadOnlySlotSpanMetadata* slot_span = - ReadOnlySlotSpanMetadata::FromAddr(address); + + auto* root = FromAddrInFirstSuperpage(address); + SlotSpanMetadata* slot_span = SlotSpanMetadata::FromAddr(address, root); PA_CHECK(PartitionRoot::FromSlotSpanMetadata(slot_span) == root); #if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) || \ PA_BUILDFLAG(USE_PARTITION_COOKIE) uintptr_t slot_span_start = - ReadOnlySlotSpanMetadata::ToSlotSpanStart(slot_span); + SlotSpanMetadata::ToSlotSpanStart(slot_span, root); size_t offset_in_slot_span = address - slot_span_start; auto* bucket = slot_span->bucket; 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 91bb8bb43c..d8161834f9 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_ROOT_H_ #define PARTITION_ALLOC_PARTITION_ROOT_H_ @@ -69,7 +74,6 @@ #include "partition_alloc/partition_lock.h" #include "partition_alloc/partition_oom.h" #include "partition_alloc/partition_page.h" -#include "partition_alloc/partition_shared_mutex.h" #include "partition_alloc/reservation_offset_table.h" #include "partition_alloc/scheduler_loop_quarantine.h" #include "partition_alloc/tagging.h" @@ -187,7 +191,17 @@ struct PartitionOptions { // compression ratio of freed memory inside partially allocated pages (due to // fragmentation). EnableToggle eventually_zero_freed_memory = kDisabled; - EnableToggle fewer_memory_regions = kDisabled; + // Linux-based systems have a limited per-process VMA limit, be more + // conservative there. This matches the feature setting in + // partition_alloc_features.cc, but not all clients use Chromium's feature + // system to configure PartitionAlloc. + EnableToggle fewer_memory_regions = +#if PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_ANDROID) || \ + PA_BUILDFLAG(IS_CHROMEOS) + kEnabled; +#else + kDisabled; +#endif struct { EnableToggle enabled = kDisabled; @@ -216,20 +230,11 @@ enum class StraightenLargerSlotSpanFreeListsMode { // Never instantiate a PartitionRoot directly, instead use // PartitionAllocator. struct alignas(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot { - using ReadOnlySlotSpanMetadata = - internal::SlotSpanMetadata; - using WritableSlotSpanMetadata = - internal::SlotSpanMetadata; + using SlotSpanMetadata = internal::SlotSpanMetadata; using Bucket = internal::PartitionBucket; using FreeListEntry = internal::FreelistEntry; - using WritableSuperPageExtentEntry = internal::PartitionSuperPageExtentEntry< - internal::MetadataKind::kWritable>; - using ReadOnlySuperPageExtentEntry = internal::PartitionSuperPageExtentEntry< - internal::MetadataKind::kReadOnly>; - using WritableDirectMapExtent = - internal::PartitionDirectMapExtent; - using ReadOnlyDirectMapExtent = - internal::PartitionDirectMapExtent; + using SuperPageExtentEntry = internal::PartitionSuperPageExtentEntry; + using DirectMapExtent = internal::PartitionDirectMapExtent; enum class BucketDistribution : uint8_t { kNeutral, kDenser }; @@ -288,8 +293,8 @@ struct alignas(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot { static inline constexpr uint32_t extras_size = 0; #endif // PA_CONFIG(EXTRAS_REQUIRED) -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - std::ptrdiff_t shadow_pool_offset_ = 0; +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + std::ptrdiff_t metadata_offset_ = 0; #endif }; @@ -359,11 +364,11 @@ struct alignas(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot { uintptr_t next_super_page = 0; uintptr_t next_partition_page = 0; uintptr_t next_partition_page_end = 0; - ReadOnlySuperPageExtentEntry* current_extent = nullptr; - ReadOnlySuperPageExtentEntry* first_extent = nullptr; - ReadOnlyDirectMapExtent* direct_map_list + SuperPageExtentEntry* current_extent = nullptr; + SuperPageExtentEntry* first_extent = nullptr; + DirectMapExtent* direct_map_list PA_GUARDED_BY(internal::PartitionRootLock(this)) = nullptr; - ReadOnlySlotSpanMetadata* global_empty_slot_span_ring + SlotSpanMetadata* global_empty_slot_span_ring [internal::kMaxEmptySlotSpanRingSize] PA_GUARDED_BY( internal::PartitionRootLock(this)) = {}; int16_t global_empty_slot_span_ring_index @@ -396,12 +401,6 @@ struct alignas(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot { internal::base::TimeTicks (*now_maybe_overridden_for_testing)() = internal::base::TimeTicks::Now; -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - // Locks not to run EnableShadowMetadata() and PartitionDirectMap() - // at the same time. - static internal::SharedMutex g_shadow_metadata_init_mutex_; -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) - PartitionRoot(); explicit PartitionRoot(PartitionOptions opts); @@ -434,9 +433,7 @@ struct alignas(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot { PA_LOCKS_EXCLUDED(thread_cache_construction_lock, lock_); PA_ALWAYS_INLINE static PartitionRoot* FromSlotSpanMetadata( - const ReadOnlySlotSpanMetadata* slot_span); - PA_ALWAYS_INLINE static PartitionRoot* FromSlotSpanMetadata( - WritableSlotSpanMetadata* slot_span); + const SlotSpanMetadata* slot_span); // These two functions work unconditionally for normal buckets. // For direct map, they only work for the first super page of a reservation, @@ -572,10 +569,9 @@ struct alignas(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot { // Immediately frees the pointer bypassing the quarantine. |slot_start| is the // beginning of the slot that contains |object|. template - PA_ALWAYS_INLINE void FreeNoHooksImmediate( - void* object, - ReadOnlySlotSpanMetadata* slot_span, - uintptr_t slot_start); + PA_ALWAYS_INLINE void FreeNoHooksImmediate(void* object, + SlotSpanMetadata* slot_span, + uintptr_t slot_start); #if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) // Actual free operation on BRP dequarantine. @@ -583,8 +579,7 @@ struct alignas(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot { size_t slot_size); #endif // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) - PA_ALWAYS_INLINE size_t - GetSlotUsableSize(const ReadOnlySlotSpanMetadata* slot_span) { + PA_ALWAYS_INLINE size_t GetSlotUsableSize(const SlotSpanMetadata* slot_span) { return AdjustSizeForExtrasSubtract(slot_span->GetUtilizedSlotSize()); } @@ -649,18 +644,17 @@ struct alignas(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot { BucketDistribution bucket_distribution); PA_ALWAYS_INLINE void FreeInSlotSpan(uintptr_t slot_start, - ReadOnlySlotSpanMetadata* slot_span) + SlotSpanMetadata* slot_span) PA_EXCLUSIVE_LOCKS_REQUIRED(internal::PartitionRootLock(this)); // Frees memory, with |slot_start| as returned by |RawAlloc()|. PA_ALWAYS_INLINE void RawFree(uintptr_t slot_start, - ReadOnlySlotSpanMetadata* slot_span) + SlotSpanMetadata* slot_span) PA_LOCKS_EXCLUDED(internal::PartitionRootLock(this)); - PA_ALWAYS_INLINE void RawFreeWithThreadCache( - uintptr_t slot_start, - void* object, - ReadOnlySlotSpanMetadata* slot_span); + PA_ALWAYS_INLINE void RawFreeWithThreadCache(uintptr_t slot_start, + void* object, + SlotSpanMetadata* slot_span); #if PA_BUILDFLAG(HAS_MEMORY_TAGGING) // Sets a new MTE tag on the slot. This must not be called when an object @@ -753,9 +747,7 @@ struct alignas(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot { } PA_ALWAYS_INLINE bool IsDirectMapped( - partition_alloc::internal::SlotSpanMetadata< - partition_alloc::internal::MetadataKind::kReadOnly>* slot_span) - const { + partition_alloc::internal::SlotSpanMetadata* slot_span) const { return IsDirectMappedBucket(slot_span->bucket); } @@ -800,7 +792,7 @@ struct alignas(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot { } PA_ALWAYS_INLINE uintptr_t SlotStartToObjectAddr(uintptr_t slot_start) const { - return internal::SlotStart::FromUntaggedAddr(slot_start) + return internal::SlotStart::FromUntaggedAddr(slot_start, this) .untagged_slot_start_; } @@ -811,7 +803,7 @@ struct alignas(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot { PA_ALWAYS_INLINE uintptr_t ObjectToSlotStart(void* object) const { uintptr_t untagged_slot_start = internal::UntagAddr(reinterpret_cast(object)); - return internal::SlotStart::FromUntaggedAddr(untagged_slot_start) + return internal::SlotStart::FromUntaggedAddr(untagged_slot_start, this) .untagged_slot_start_; } @@ -876,19 +868,15 @@ struct alignas(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot { scheduler_loop_quarantine_root, config); } -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - // TODO(crbug.com/40238514) This is an unused function. Start using it in - // tests and/or in production code. - static void EnableShadowMetadata(internal::PoolHandleMask mask); - - PA_ALWAYS_INLINE std::ptrdiff_t ShadowPoolOffset() const { - return settings.shadow_pool_offset_; +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + PA_ALWAYS_INLINE std::ptrdiff_t MetadataOffset() const { + return settings.metadata_offset_; } #else - PA_ALWAYS_INLINE constexpr std::ptrdiff_t ShadowPoolOffset() const { - return 0; - } -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) + PA_ALWAYS_INLINE + PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR + size_t MetadataOffset() const { return internal::SystemPageSize(); } +#endif // PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) PA_NOINLINE static void CheckMetadataIntegrity(const void* object); @@ -997,10 +985,10 @@ struct alignas(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot { } bool TryReallocInPlaceForNormalBuckets(void* object, - ReadOnlySlotSpanMetadata* slot_span, + SlotSpanMetadata* slot_span, size_t new_size) PA_LOCKS_EXCLUDED(thread_cache_construction_lock); - bool TryReallocInPlaceForDirectMap(ReadOnlySlotSpanMetadata* slot_span, + bool TryReallocInPlaceForDirectMap(SlotSpanMetadata* slot_span, size_t requested_size) PA_EXCLUSIVE_LOCKS_REQUIRED(internal::PartitionRootLock(this)); void DecommitEmptySlotSpans() @@ -1034,7 +1022,7 @@ struct alignas(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot { CreateFreeNotificationData(void* address) const; #if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) - PA_NOINLINE void QuarantineForBrp(ReadOnlySlotSpanMetadata* slot_span, + PA_NOINLINE void QuarantineForBrp(const SlotSpanMetadata* slot_span, void* object); #endif // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) @@ -1105,23 +1093,27 @@ PartitionAllocGetDirectMapSlotStartAndSizeInBRPPool(uintptr_t address) { return SlotAddressAndSize{.slot_start = uintptr_t(0), .size = size_t(0)}; } +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + std::ptrdiff_t metadata_offset = + PartitionAddressSpace::MetadataOffset(pool_handle::kBRPPoolHandle); +#else + constexpr std::ptrdiff_t metadata_offset = 0; +#endif // The direct map allocation may not start exactly from the first page, as // there may be padding for alignment. The first page metadata holds an offset // to where direct map metadata, and thus direct map start, are located. - auto* first_page_metadata = - PartitionPageMetadata::FromAddr( - reservation_start + PartitionPageSize()); + auto* first_page_metadata = PartitionPageMetadata::FromAddr( + reservation_start + PartitionPageSize(), metadata_offset); auto* page_metadata = first_page_metadata + first_page_metadata->slot_span_metadata_offset; PA_DCHECK(page_metadata->is_valid); PA_DCHECK(!page_metadata->slot_span_metadata_offset); auto* slot_span = &page_metadata->slot_span_metadata; uintptr_t slot_start = - SlotSpanMetadata::ToSlotSpanStart(slot_span); + SlotSpanMetadata::ToSlotSpanStart(slot_span, metadata_offset); #if PA_BUILDFLAG(DCHECKS_ARE_ON) auto* direct_map_metadata = - PartitionDirectMapMetadata::FromSlotSpanMetadata( - slot_span); + PartitionDirectMapMetadata::FromSlotSpanMetadata(slot_span); size_t padding_for_alignment = direct_map_metadata->direct_map_extent.padding_for_alignment; PA_DCHECK(padding_for_alignment == @@ -1154,8 +1146,14 @@ PartitionAllocGetSlotStartAndSizeInBRPPool(uintptr_t address) { return directmap_slot_info; } - auto* slot_span = - SlotSpanMetadata::FromAddr(address); +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + std::ptrdiff_t metadata_offset = + PartitionAddressSpace::MetadataOffset(pool_handle::kBRPPoolHandle); +#else + constexpr std::ptrdiff_t metadata_offset = 0; +#endif + auto* slot_span = SlotSpanMetadata::FromAddr(address, metadata_offset); + #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 @@ -1165,7 +1163,7 @@ PartitionAllocGetSlotStartAndSizeInBRPPool(uintptr_t address) { // Get the offset from the beginning of the slot span. uintptr_t slot_span_start = - SlotSpanMetadata::ToSlotSpanStart(slot_span); + SlotSpanMetadata::ToSlotSpanStart(slot_span, metadata_offset); size_t offset_in_slot_span = address - slot_span_start; auto* bucket = slot_span->bucket; @@ -1219,7 +1217,7 @@ PartitionRoot::AllocFromBucket(Bucket* bucket, bool* is_already_zeroed) { PA_DCHECK((slot_span_alignment >= internal::PartitionPageSize()) && internal::base::bits::HasSingleBit(slot_span_alignment)); - ReadOnlySlotSpanMetadata* slot_span = bucket->active_slot_spans_head; + 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); // Check that it isn't marked full, which could only be true if the span was @@ -1248,7 +1246,7 @@ PartitionRoot::AllocFromBucket(Bucket* bucket, PA_DCHECK(!slot_span->CanStoreRawSize()); PA_DCHECK(!slot_span->bucket->is_direct_mapped()); - void* entry = slot_span->ToWritable(this)->PopForAlloc(bucket->slot_size); + void* entry = slot_span->PopForAlloc(bucket->slot_size); PA_DCHECK(internal::SlotStartPtr2Addr(entry) == slot_start); @@ -1260,7 +1258,7 @@ PartitionRoot::AllocFromBucket(Bucket* bucket, if (!slot_start) [[unlikely]] { return 0; } - PA_DCHECK(slot_span == ReadOnlySlotSpanMetadata::FromSlotStart(slot_start)); + PA_DCHECK(slot_span == SlotSpanMetadata::FromSlotStart(slot_start, this)); PA_CHECK(DeducedRootIsValid(slot_span)); // For direct mapped allocations, |bucket| is the sentinel. PA_DCHECK((slot_span->bucket == bucket) || @@ -1430,13 +1428,13 @@ PA_ALWAYS_INLINE void PartitionRoot::FreeInline(void* object) { PA_CHECK(IsManagedByPartitionAlloc(object_addr)); #endif - ReadOnlySlotSpanMetadata* slot_span = - ReadOnlySlotSpanMetadata::FromObject(object); + SlotSpanMetadata* slot_span = SlotSpanMetadata::FromObject(object, this); PA_DCHECK(PartitionRoot::FromSlotSpanMetadata(slot_span) == this); - internal::SlotStart slot_start = internal::SlotStart::FromObject(object); - PA_DCHECK(slot_span == ReadOnlySlotSpanMetadata::FromSlotStart( - slot_start.untagged_slot_start_)); + internal::SlotStart slot_start = + internal::SlotStart::FromObject(object, this); + PA_DCHECK(slot_span == SlotSpanMetadata::FromSlotStart( + slot_start.untagged_slot_start_, this)); // We are going to read from |*slot_span| in all branches, but haven't done it // yet. @@ -1454,7 +1452,7 @@ PA_ALWAYS_INLINE void PartitionRoot::FreeInline(void* object) { template PA_ALWAYS_INLINE void PartitionRoot::FreeNoHooksImmediate( void* object, - ReadOnlySlotSpanMetadata* slot_span, + SlotSpanMetadata* slot_span, uintptr_t slot_start) { // The thread cache is added "in the middle" of the main allocator, that is: // - After all the cookie/in-slot metadata management @@ -1558,8 +1556,7 @@ PA_ALWAYS_INLINE void PartitionRoot::FreeNoHooksImmediate( PA_ALWAYS_INLINE void PartitionRoot::FreeAfterBRPQuarantine( uintptr_t slot_start, size_t slot_size) { - auto* slot_span = internal::SlotSpanMetadata< - internal::MetadataKind::kReadOnly>::FromSlotStart(slot_start); + auto* slot_span = internal::SlotSpanMetadata::FromSlotStart(slot_start); auto* root = PartitionRoot::FromSlotSpanMetadata(slot_span); // Currently, InSlotMetadata is allocated when BRP is used. PA_DCHECK(root->brp_enabled()); @@ -1612,11 +1609,11 @@ PA_ALWAYS_INLINE void PartitionRoot::FreeAfterBRPQuarantine( PA_ALWAYS_INLINE void PartitionRoot::FreeInSlotSpan( uintptr_t slot_start, - ReadOnlySlotSpanMetadata* slot_span) { + SlotSpanMetadata* slot_span) { DecreaseTotalSizeOfAllocatedBytes(slot_start, slot_span->GetSlotSizeForBookkeeping()); - return slot_span->ToWritable(this)->Free(slot_start, this); + return slot_span->Free(slot_start, this); } #if PA_CONFIG(IS_NONCLANG_MSVC) @@ -1627,9 +1624,8 @@ PA_ALWAYS_INLINE void PartitionRoot::FreeInSlotSpan( // a no-op or similar. The documentation doesn't say. #pragma optimize("", off) #endif -PA_ALWAYS_INLINE void PartitionRoot::RawFree( - uintptr_t slot_start, - ReadOnlySlotSpanMetadata* slot_span) { +PA_ALWAYS_INLINE void PartitionRoot::RawFree(uintptr_t slot_start, + SlotSpanMetadata* slot_span) { void* ptr = internal::SlotStartAddr2Ptr(slot_start); // At this point we are about to acquire the lock, so we try to minimize the // risk of blocking inside the locked section. @@ -1715,7 +1711,7 @@ PA_ALWAYS_INLINE void PartitionRoot::RetagSlotIfNeeded(void* slot_start_ptr, PA_ALWAYS_INLINE void PartitionRoot::RawFreeWithThreadCache( uintptr_t slot_start, void* slot_start_ptr, - ReadOnlySlotSpanMetadata* slot_span) { + SlotSpanMetadata* slot_span) { #if PA_BUILDFLAG(HAS_MEMORY_TAGGING) RetagSlotIfNeeded(slot_start_ptr, slot_span->bucket->slot_size); #endif @@ -1753,8 +1749,8 @@ PA_ALWAYS_INLINE void PartitionRoot::RawFreeWithThreadCache( } PA_ALWAYS_INLINE void PartitionRoot::RawFreeLocked(uintptr_t slot_start) { - ReadOnlySlotSpanMetadata* slot_span = - ReadOnlySlotSpanMetadata::FromSlotStart(slot_start); + SlotSpanMetadata* slot_span = + SlotSpanMetadata::FromSlotStart(slot_start, this); // Direct-mapped deallocation releases then re-acquires the lock. The caller // may not expect that, but we never call this function on direct-mapped // allocations. @@ -1763,15 +1759,8 @@ PA_ALWAYS_INLINE void PartitionRoot::RawFreeLocked(uintptr_t slot_start) { } PA_ALWAYS_INLINE PartitionRoot* PartitionRoot::FromSlotSpanMetadata( - const ReadOnlySlotSpanMetadata* slot_span) { - auto* extent_entry = reinterpret_cast( - reinterpret_cast(slot_span) & internal::SystemPageBaseMask()); - return extent_entry->root; -} - -PA_ALWAYS_INLINE PartitionRoot* PartitionRoot::FromSlotSpanMetadata( - WritableSlotSpanMetadata* slot_span) { - auto* extent_entry = reinterpret_cast( + const SlotSpanMetadata* slot_span) { + auto* extent_entry = reinterpret_cast( reinterpret_cast(slot_span) & internal::SystemPageBaseMask()); return extent_entry->root; } @@ -1780,7 +1769,14 @@ PA_ALWAYS_INLINE PartitionRoot* PartitionRoot::FromFirstSuperPage( uintptr_t super_page) { PA_DCHECK(internal::ReservationOffsetTable::Get(super_page) .IsReservationStart(super_page)); - auto* extent_entry = internal::PartitionSuperPageToExtent(super_page); +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + // Slow + std::ptrdiff_t offset = + internal::PartitionAddressSpace::MetadataOffsetFromAddr(super_page); +#else + std::ptrdiff_t offset = 0; +#endif + auto* extent_entry = internal::PartitionSuperPageToExtent(super_page, offset); PartitionRoot* root = extent_entry->root; PA_DCHECK(root->inverted_self == ~reinterpret_cast(root)); return root; @@ -1938,7 +1934,14 @@ PA_ALWAYS_INLINE size_t PartitionRoot::GetUsableSize(const void* ptr) { if (!ptr) { return 0; } - auto* slot_span = ReadOnlySlotSpanMetadata::FromObjectInnerPtr(ptr); +#if PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE) + std::ptrdiff_t offset = + internal::PartitionAddressSpace::MetadataOffsetFromAddr( + internal::ObjectInnerPtr2Addr(ptr)); +#else + constexpr std::ptrdiff_t offset = 0; +#endif + auto* slot_span = SlotSpanMetadata::FromObjectInnerPtr(ptr, offset); auto* root = FromSlotSpanMetadata(slot_span); return root->GetSlotUsableSize(slot_span); } @@ -1977,7 +1980,7 @@ PartitionRoot::PageAccessibilityWithThreadIsolationIfEnabled( // the same amount of underlying memory. PA_ALWAYS_INLINE size_t PartitionRoot::AllocationCapacityFromSlotStart(uintptr_t slot_start) const { - auto* slot_span = ReadOnlySlotSpanMetadata::FromSlotStart(slot_start); + auto* slot_span = SlotSpanMetadata::FromSlotStart(slot_start, this); return AdjustSizeForExtrasSubtract(slot_span->bucket->slot_size); } @@ -1991,7 +1994,7 @@ PartitionRoot::InSlotMetadataPointerFromSlotStartAndSize(uintptr_t slot_start, PA_ALWAYS_INLINE internal::InSlotMetadata* PartitionRoot::InSlotMetadataPointerFromObjectForTesting(void* object) const { uintptr_t slot_start = ObjectToSlotStart(object); - auto* slot_span = ReadOnlySlotSpanMetadata::FromSlotStart(slot_start); + auto* slot_span = SlotSpanMetadata::FromSlotStart(slot_start, this); return InSlotMetadataPointerFromSlotStartAndSize( slot_start, slot_span->bucket->slot_size); } @@ -2131,8 +2134,8 @@ PA_ALWAYS_INLINE void* PartitionRoot::AllocInternalNoHooks( #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. - ReadOnlySlotSpanMetadata* slot_span = - ReadOnlySlotSpanMetadata::FromSlotStart(slot_start); + SlotSpanMetadata* slot_span = + SlotSpanMetadata::FromSlotStart(slot_start, this); PA_DCHECK(DeducedRootIsValid(slot_span)); PA_DCHECK(slot_span->bucket == &bucket_at(bucket_index)); PA_DCHECK(slot_span->bucket->slot_size == slot_size); @@ -2379,8 +2382,7 @@ void* PartitionRoot::ReallocInline(void* ptr, } if (!overridden) [[likely]] { // |ptr| may have been allocated in another root. - ReadOnlySlotSpanMetadata* slot_span = - ReadOnlySlotSpanMetadata::FromObject(ptr); + SlotSpanMetadata* slot_span = SlotSpanMetadata::FromObject(ptr); auto* old_root = PartitionRoot::FromSlotSpanMetadata(slot_span); bool success = false; bool tried_in_place_for_direct_map = false; diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_shared_mutex.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_shared_mutex.h deleted file mode 100644 index 46cbc1029c..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_shared_mutex.h +++ /dev/null @@ -1,82 +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 PARTITION_ALLOC_PARTITION_SHARED_MUTEX_H_ -#define PARTITION_ALLOC_PARTITION_SHARED_MUTEX_H_ - -#include "partition_alloc/partition_alloc_base/thread_annotations.h" -#include "partition_alloc/partition_lock.h" - -namespace partition_alloc::internal { - -// A partial implementation of `std::shared_mutex` for PartitionAllocator. -// Since `std::shared_mutex` allocates memory, we cannot use it inside -// PartitionAllocator. The difference between `std::shared_mutex` and this -// SharedMutex, this SharedMutex doesn't support try_lock() and -// try_lock_shared(), because no code uses the methods. -class PA_LOCKABLE SharedMutex { - public: - inline constexpr SharedMutex() = default; - - void lock() PA_EXCLUSIVE_LOCK_FUNCTION() { writer_lock_.Acquire(); } - - void unlock() PA_UNLOCK_FUNCTION() { writer_lock_.Release(); } - - void lock_shared() PA_SHARED_LOCK_FUNCTION() { - ScopedGuard lock(reader_lock_); - ++counter_; - if (counter_ == 1u) { - writer_lock_.Acquire(); - } - } - - void unlock_shared() PA_UNLOCK_FUNCTION() { - ScopedGuard lock(reader_lock_); - --counter_; - if (counter_ == 0u) { - writer_lock_.Release(); - } - } - - private: - Lock reader_lock_; - Lock writer_lock_; - size_t counter_ PA_GUARDED_BY(reader_lock_) = 0; -}; - -static_assert(std::is_trivially_destructible_v, - "SharedMutex must be trivally destructible."); - -// A partial implementation of `std::unique_lock` for PartitionAllocator. -// Locking a UniqueLock locks the associated shared mutex in exclusive mode. -class PA_SCOPED_LOCKABLE UniqueLock { - public: - explicit UniqueLock(SharedMutex& mutex) PA_EXCLUSIVE_LOCK_FUNCTION(mutex) - : mutex_(mutex) { - mutex_.lock(); - } - ~UniqueLock() PA_UNLOCK_FUNCTION() { mutex_.unlock(); } - - private: - SharedMutex& mutex_; -}; - -// A partial implementation of `std::shared_lock` for PartitionAllocator. -// Locking a SharedLock locks the associated shared mutex in shared mode. -// (like std::shared_lock). -class PA_SCOPED_LOCKABLE SharedLock { - public: - explicit SharedLock(SharedMutex& mutex) PA_SHARED_LOCK_FUNCTION(mutex) - : mutex_(mutex) { - mutex_.lock_shared(); - } - ~SharedLock() PA_UNLOCK_FUNCTION() { mutex_.unlock_shared(); } - - private: - SharedMutex& mutex_; -}; - -} // namespace partition_alloc::internal - -#endif // PARTITION_ALLOC_PARTITION_SHARED_MUTEX_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_stats.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_stats.cc index 93a314ad7e..c8cf441047 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_stats.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_stats.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_stats.h" #include 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 ac68d42fa2..c71755671d 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_STATS_H_ #define PARTITION_ALLOC_PARTITION_STATS_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_superpage_extent_entry.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_superpage_extent_entry.h index 465068a26a..8f6ea39ca3 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_superpage_extent_entry.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_superpage_extent_entry.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_SUPERPAGE_EXTENT_ENTRY_H_ #define PARTITION_ALLOC_PARTITION_SUPERPAGE_EXTENT_ENTRY_H_ @@ -9,6 +14,7 @@ #include "partition_alloc/address_pool_manager.h" #include "partition_alloc/address_pool_manager_types.h" +#include "partition_alloc/partition_alloc-inl.h" #include "partition_alloc/partition_alloc_constants.h" #include "partition_alloc/partition_alloc_forward.h" #include "partition_alloc/partition_dcheck_helper.h" @@ -18,63 +24,14 @@ namespace partition_alloc::internal { -template -struct PartitionSuperPageExtentEntry; - // An "extent" is a span of consecutive superpages. We link the partition's next // extent (if there is one) to the very start of a superpage's metadata area. -template -struct PartitionSuperPageExtentEntryBase { - // The data member of PartitionSuperPageExtentEntry. To make - // PartitionSuperPageExtentEntry have the same data member and - // the same memory layout, all the data member are put into this struct. - // PartitionSuperPageExtentEntry extends this class without - // adding any data members. - MaybeConstT root; - MaybeConstT*> - next; - MaybeConstT number_of_consecutive_super_pages; - MaybeConstT number_of_nonempty_slot_spans; -}; +struct PartitionSuperPageExtentEntry { + PartitionRoot* root; + PartitionSuperPageExtentEntry* next; + uint16_t number_of_consecutive_super_pages; + uint16_t number_of_nonempty_slot_spans; -template -struct PartitionSuperPageExtentEntry; - -template <> -struct PartitionSuperPageExtentEntry - : public PartitionSuperPageExtentEntryBase { - PartitionSuperPageExtentEntry* ToWritable( - const PartitionRoot* partition_root) { - return ToWritableInternal(partition_root); - } - -#if PA_BUILDFLAG(DCHECKS_ARE_ON) - PartitionSuperPageExtentEntry* ToReadOnly() { - return this; - } -#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) - - private: - // In order to resolve circular dependencies, i.e. ToWritable() needs - // PartitionRoot, define template method: ToWritableInternal() here and - // ToWritable() uses it. - template - PartitionSuperPageExtentEntry* ToWritableInternal( - [[maybe_unused]] T* partition_root) { -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - return reinterpret_cast< - PartitionSuperPageExtentEntry*>( - reinterpret_cast(this) + partition_root->ShadowPoolOffset()); -#else - return reinterpret_cast< - PartitionSuperPageExtentEntry*>(this); -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) - } -}; - -template <> -struct PartitionSuperPageExtentEntry - : public PartitionSuperPageExtentEntryBase { PA_ALWAYS_INLINE void IncrementNumberOfNonemptySlotSpans() { DCheckNumberOfPartitionPagesInSuperPagePayload( this, root, number_of_nonempty_slot_spans); @@ -85,64 +42,27 @@ struct PartitionSuperPageExtentEntry PA_DCHECK(number_of_nonempty_slot_spans); --number_of_nonempty_slot_spans; } - -#if !PA_CONFIG(ENABLE_SHADOW_METADATA) - PartitionSuperPageExtentEntry* ToWritable() { - return this; - } -#endif // !PA_CONFIG(ENABLE_SHADOW_METADATA) - -#if PA_BUILDFLAG(DCHECKS_ARE_ON) || !PA_CONFIG(ENABLE_SHADOW_METADATA) - PartitionSuperPageExtentEntry* ToReadOnly( - const PartitionRoot* partition_root) { - return ToReadOnlyInternal(partition_root); - } - - private: - // In order to resolve circular dependencies, i.e. ToReadOnly() needs - // PartitionRoot, define template method: ToReadOnlyInternal() and - // ToReadOnly() uses it. - template - PartitionSuperPageExtentEntry* ToReadOnlyInternal( - [[maybe_unused]] T* partition_root) { -#if PA_CONFIG(ENABLE_SHADOW_METADATA) - return reinterpret_cast< - PartitionSuperPageExtentEntry*>( - reinterpret_cast(this) - partition_root->ShadowPoolOffset()); -#else - return reinterpret_cast< - PartitionSuperPageExtentEntry*>(this); -#endif // PA_CONFIG(ENABLE_SHADOW_METADATA) - } -#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) || !PA_CONFIG(ENABLE_SHADOW_METADATA) }; static_assert( - sizeof(PartitionSuperPageExtentEntry) == - sizeof(PartitionSuperPageExtentEntry), - "PartitionSuperPageExtentEntry and " - "PartitionSuperPageExtentEntry must have the same " - "size"); -static_assert( - sizeof(PartitionSuperPageExtentEntry) <= - kPageMetadataSize, + sizeof(PartitionSuperPageExtentEntry) <= kPageMetadataSize, "PartitionSuperPageExtentEntry must be able to fit in a metadata slot"); -static_assert( - kMaxSuperPagesInPool / kSuperPageSize <= - std::numeric_limits< - decltype(PartitionSuperPageExtentEntry:: - number_of_consecutive_super_pages)>::max(), - "number_of_consecutive_super_pages must be big enough"); +static_assert(kMaxSuperPagesInPool / kSuperPageSize <= + std::numeric_limits< + decltype(PartitionSuperPageExtentEntry :: + number_of_consecutive_super_pages)>::max(), + "number_of_consecutive_super_pages must be big enough"); // Returns the base of the first super page in the range of consecutive super // pages. // // CAUTION! |extent| must point to the extent of the first super page in the // range of consecutive super pages. -PA_ALWAYS_INLINE uintptr_t SuperPagesBeginFromExtent( - const PartitionSuperPageExtentEntry* extent) { +PA_ALWAYS_INLINE uintptr_t +SuperPagesBeginFromExtent(const PartitionSuperPageExtentEntry* extent) { PA_DCHECK(0 < extent->number_of_consecutive_super_pages); - uintptr_t extent_as_uintptr = reinterpret_cast(extent); + uintptr_t extent_as_uintptr = PartitionMetadataPageToSuperPage( + reinterpret_cast(extent), GetMetadataOffset(extent->root)); PA_DCHECK(ReservationOffsetTable::Get(extent_as_uintptr) .IsManagedByNormalBuckets(extent_as_uintptr)); return base::bits::AlignDown(extent_as_uintptr, kSuperPageAlignment); @@ -153,8 +73,8 @@ PA_ALWAYS_INLINE uintptr_t SuperPagesBeginFromExtent( // // CAUTION! |extent| must point to the extent of the first super page in the // range of consecutive super pages. -PA_ALWAYS_INLINE uintptr_t SuperPagesEndFromExtent( - const PartitionSuperPageExtentEntry* extent) { +PA_ALWAYS_INLINE uintptr_t +SuperPagesEndFromExtent(const PartitionSuperPageExtentEntry* extent) { return SuperPagesBeginFromExtent(extent) + (extent->number_of_consecutive_super_pages * kSuperPageSize); } diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_tls.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_tls.h index 619115520a..741ba12035 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_tls.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_tls.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_PARTITION_TLS_H_ #define PARTITION_ALLOC_PARTITION_TLS_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_tls_win.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_tls_win.cc index e28ffe82f3..e8d26ca446 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_tls_win.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_tls_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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/partition_tls.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/empty.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/empty.cc index f2cab74076..26ae2c5e11 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/empty.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/empty.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // This empty.cc is built when raw_ptr_noop_impl.h is used to avoid // the situation: no object files are linked to build raw_ptr.dll. // If raw_ptr target's sources has only header files, no object diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.cc index fecc2c35a3..6e800adaaa 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/pointers/instance_tracer.h" #include 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 c8e55d7b0b..7612e41177 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_POINTERS_INSTANCE_TRACER_H_ #define PARTITION_ALLOC_POINTERS_INSTANCE_TRACER_H_ 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 bab29ddc7b..0546bb210d 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // IWYU pragma: private, include "base/memory/raw_ptr.h" #ifndef PARTITION_ALLOC_POINTERS_RAW_PTR_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_asan_unowned_impl.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_asan_unowned_impl.cc index 00724df455..4705d9b79c 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_asan_unowned_impl.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_asan_unowned_impl.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/pointers/raw_ptr_asan_unowned_impl.h" #include 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 c2ba4a81d9..c0bac5207d 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_POINTERS_RAW_PTR_ASAN_UNOWNED_IMPL_H_ #define PARTITION_ALLOC_POINTERS_RAW_PTR_ASAN_UNOWNED_IMPL_H_ 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 7c63aac80f..20f2e8335f 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/pointers/raw_ptr_backup_ref_impl.h" #include 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 f49a35b5c1..2de94215cb 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_POINTERS_RAW_PTR_BACKUP_REF_IMPL_H_ #define PARTITION_ALLOC_POINTERS_RAW_PTR_BACKUP_REF_IMPL_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_cast.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_cast.h index f00bad8d5d..e4e5f915a9 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_cast.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_cast.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // IWYU pragma: private, include "base/memory/raw_ptr_cast.h" #ifndef PARTITION_ALLOC_POINTERS_RAW_PTR_CAST_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_counting_impl_for_test.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_counting_impl_for_test.h index 3628c09168..df7e7b23b7 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_counting_impl_for_test.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_counting_impl_for_test.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_POINTERS_RAW_PTR_COUNTING_IMPL_FOR_TEST_H_ #define PARTITION_ALLOC_POINTERS_RAW_PTR_COUNTING_IMPL_FOR_TEST_H_ 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 f56f733984..eaa2710fb1 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // IWYU pragma: private, include "base/memory/raw_ptr_exclusion.h" #ifndef PARTITION_ALLOC_POINTERS_RAW_PTR_EXCLUSION_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_hookable_impl.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_hookable_impl.cc index e23ee5264d..be5a85ea81 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_hookable_impl.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_hookable_impl.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/pointers/raw_ptr_hookable_impl.h" #include 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 404c8ed4ac..64d28ad826 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_POINTERS_RAW_PTR_HOOKABLE_IMPL_H_ #define PARTITION_ALLOC_POINTERS_RAW_PTR_HOOKABLE_IMPL_H_ 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 75d2de6b3a..7224bef305 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // This is a "No Compile Test" suite. // http://dev.chromium.org/developers/testing/no-compile-tests diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_noop_impl.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_noop_impl.h index cee11317b3..d4ef251dd7 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_noop_impl.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_noop_impl.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_POINTERS_RAW_PTR_NOOP_IMPL_H_ #define PARTITION_ALLOC_POINTERS_RAW_PTR_NOOP_IMPL_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_test_support.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_test_support.h index 8f3b550153..8cd44a48d4 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_test_support.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_test_support.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_POINTERS_RAW_PTR_TEST_SUPPORT_H_ #define PARTITION_ALLOC_POINTERS_RAW_PTR_TEST_SUPPORT_H_ 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 2e619ba69b..b21e468008 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // IWYU pragma: private, include "base/memory/raw_ref.h" #ifndef PARTITION_ALLOC_POINTERS_RAW_REF_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref_nocompile.nc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref_nocompile.nc index e4e9b023df..634ad1cd06 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref_nocompile.nc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref_nocompile.nc @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // This is a "No Compile Test" suite. // http://dev.chromium.org/developers/testing/no-compile-tests 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 56b7f391a1..90688eaca4 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_POOL_OFFSET_FREELIST_H_ #define PARTITION_ALLOC_POOL_OFFSET_FREELIST_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/random.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/random.cc index 32ddc753a2..06447a7906 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/random.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/random.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/random.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/random.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/random.h index 9355b749f2..de6b29aa5f 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/random.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/random.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_RANDOM_H_ #define PARTITION_ALLOC_RANDOM_H_ 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 a333a74279..6bbe423fef 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/reservation_offset_table.h" #include "partition_alloc/buildflags.h" 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 a7636b1b39..0269eff48e 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_RESERVATION_OFFSET_TABLE_H_ #define PARTITION_ALLOC_RESERVATION_OFFSET_TABLE_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/reverse_bytes.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/reverse_bytes.h index d9db43e197..1173806673 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/reverse_bytes.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/reverse_bytes.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_REVERSE_BYTES_H_ #define PARTITION_ALLOC_REVERSE_BYTES_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/scheduler_loop_quarantine.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/scheduler_loop_quarantine.cc index 06f2c01977..d7fb206505 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/scheduler_loop_quarantine.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/scheduler_loop_quarantine.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/scheduler_loop_quarantine.h" #include "partition_alloc/internal_allocator.h" @@ -116,7 +121,7 @@ void SchedulerLoopQuarantineBranch::Destroy() { template void SchedulerLoopQuarantineBranch::Quarantine( void* object, - SlotSpanMetadata* slot_span, + SlotSpanMetadata* slot_span, uintptr_t slot_start) { #if PA_BUILDFLAG(DCHECKS_ARE_ON) PA_DCHECK(!being_destructed_); @@ -196,8 +201,7 @@ SchedulerLoopQuarantineBranch::PurgeInternal( // Going to `RawFree()` directly. slot_size = BucketIndexLookup::GetBucketSize(bucket_index); auto* slot_span = - SlotSpanMetadata::FromSlotStart( - to_free.slot_start); + SlotSpanMetadata::FromSlotStart(to_free.slot_start, allocator_root_); allocator_root_->RawFree(to_free.slot_start, slot_span); } else { // Unless during its destruction, we can assume ThreadCache is valid @@ -218,9 +222,8 @@ SchedulerLoopQuarantineBranch::PurgeInternal( allocator_root_->AdjustSizeForExtrasSubtract(slot_size); #if PA_BUILDFLAG(DCHECKS_ARE_ON) - auto* slot_span = - SlotSpanMetadata::FromSlotStart( - to_free.slot_start); + auto* slot_span = SlotSpanMetadata::FromSlotStart(to_free.slot_start, + allocator_root_); PA_DCHECK(!slot_span->CanStoreRawSize()); PA_DCHECK(usable_size == allocator_root_->GetSlotUsableSize(slot_span)); #endif @@ -230,16 +233,15 @@ SchedulerLoopQuarantineBranch::PurgeInternal( // ThreadCache refused to take ownership of the allocation, hence we // free it. slot_size = BucketIndexLookup::GetBucketSize(bucket_index); - auto* slot_span = - SlotSpanMetadata::FromSlotStart( - to_free.slot_start); + auto* slot_span = SlotSpanMetadata::FromSlotStart(to_free.slot_start, + allocator_root_); size_t usable_size = allocator_root_->GetSlotUsableSize(slot_span); tcache_->RecordDeallocation(usable_size); allocator_root_->RawFree(to_free.slot_start, slot_span); } } - freed_count++; + ++freed_count; PA_DCHECK(slot_size > 0); freed_size_in_bytes += slot_size; branch_size_in_bytes_ -= slot_size; @@ -252,6 +254,31 @@ SchedulerLoopQuarantineBranch::PurgeInternal( root_->count_.fetch_sub(freed_count, std::memory_order_relaxed); } +template +void SchedulerLoopQuarantineBranch::AllowScanlessPurge() { + PA_DCHECK(kThreadBound); + // Always thread-bound; no need to lock. + FakeScopedGuard guard(lock_); + + PA_CHECK(disallow_scanless_purge_ > 0); + --disallow_scanless_purge_; + if (disallow_scanless_purge_ == 0) { + // Now scanless purge is allowed. Purging at this timing is more performance + // efficient. + PurgeInternal(0); + } +} + +template +void SchedulerLoopQuarantineBranch::DisallowScanlessPurge() { + PA_DCHECK(kThreadBound); + // Always thread-bound; no need to lock. + FakeScopedGuard guard(lock_); + + ++disallow_scanless_purge_; + PA_CHECK(disallow_scanless_purge_ > 0); // Overflow check. +} + template const SchedulerLoopQuarantineConfig& SchedulerLoopQuarantineBranch::GetConfigurationForTesting() { diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/scheduler_loop_quarantine.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/scheduler_loop_quarantine.h index 8154fd75db..2d91eb29dc 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/scheduler_loop_quarantine.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/scheduler_loop_quarantine.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // Scheduler-loop Quarantine is a quarantine pool behind PartitionAlloc with // Advanced Checks and `ADVANCED_MEMORY_SAFETY_CHECKS()`. // Both requests to prevent `free()`d allocation getting released to free-list, @@ -73,6 +78,8 @@ struct SchedulerLoopQuarantineConfig { bool leak_on_destruction = false; bool enable_quarantine = false; bool enable_zapping = false; + // For informational purposes only. + char branch_name[32] = ""; }; class PA_COMPONENT_EXPORT(PARTITION_ALLOC) SchedulerLoopQuarantineRoot { @@ -123,7 +130,8 @@ class SchedulerLoopQuarantineBranch { ~SchedulerLoopQuarantineBranch(); void Configure(SchedulerLoopQuarantineRoot& root, - const SchedulerLoopQuarantineConfig& config); + const SchedulerLoopQuarantineConfig& config) + PA_LOCKS_EXCLUDED(lock_); Root& GetRoot() { PA_CHECK(enable_quarantine_ && root_); return *root_; @@ -131,13 +139,13 @@ class SchedulerLoopQuarantineBranch { // Dequarantine all entries **held by this branch**. // It is possible that another branch with entries and it remains untouched. - void Purge(); + void Purge() PA_LOCKS_EXCLUDED(lock_); // Similar to `Purge()`, but marks this branch as unusable. Can be called // multiple times. - void Destroy(); + void Destroy() PA_LOCKS_EXCLUDED(lock_); // Determines this list contains an object. - bool IsQuarantinedForTesting(void* object); + bool IsQuarantinedForTesting(void* object) PA_LOCKS_EXCLUDED(lock_); size_t GetCapacityInBytes() { return branch_capacity_in_bytes_.load(std::memory_order_relaxed); @@ -147,8 +155,11 @@ class SchedulerLoopQuarantineBranch { void SetCapacityInBytes(size_t capacity_in_bytes); void Quarantine(void* object, - SlotSpanMetadata* slot_span, - uintptr_t slot_start); + SlotSpanMetadata* slot_span, + uintptr_t slot_start) PA_LOCKS_EXCLUDED(lock_); + + void AllowScanlessPurge(); + void DisallowScanlessPurge(); const SchedulerLoopQuarantineConfig& GetConfigurationForTesting(); @@ -217,6 +228,15 @@ class SchedulerLoopQuarantineBranch { // Using `std::atomic` here so that other threads can update this value. std::atomic_size_t branch_capacity_in_bytes_ = 0; + // TODO(http://crbug.com/329027914): Implement stack scanning, to be performed + // when this value is non-zero. + // + // Currently, a scanless purge is always performed. However, this value is + // still used as a hint to determine safer purge timings for memory + // optimization. + uint32_t disallow_scanless_purge_ PA_GUARDED_BY(lock_) = 0; + + // Debug and testing data. #if PA_BUILDFLAG(DCHECKS_ARE_ON) std::atomic_bool being_destructed_ = false; #endif // PA_BUILDFLAG(DCHECKS_ARE_ON) diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/scheduler_loop_quarantine_support.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/scheduler_loop_quarantine_support.cc index 2daeca1bba..3670be1aa9 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/scheduler_loop_quarantine_support.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/scheduler_loop_quarantine_support.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/scheduler_loop_quarantine_support.h" namespace partition_alloc { @@ -16,6 +21,50 @@ ScopedSchedulerLoopQuarantineExclusion:: ScopedSchedulerLoopQuarantineExclusion:: ~ScopedSchedulerLoopQuarantineExclusion() {} +SchedulerLoopQuarantineScanPolicyUpdater:: + SchedulerLoopQuarantineScanPolicyUpdater() = default; + +SchedulerLoopQuarantineScanPolicyUpdater:: + ~SchedulerLoopQuarantineScanPolicyUpdater() { + // Ensure all `DisallowScanlessPurge()` calls were followed by + // `AllowScanlessPurge()`. + PA_CHECK(disallow_scanless_purge_calls_ == 0); +} + +void SchedulerLoopQuarantineScanPolicyUpdater::DisallowScanlessPurge() { + disallow_scanless_purge_calls_++; + PA_CHECK(0 < disallow_scanless_purge_calls_); // Overflow check. + + auto* branch = GetQuarantineBranch(); + PA_CHECK(branch); + branch->DisallowScanlessPurge(); +} + +void SchedulerLoopQuarantineScanPolicyUpdater::AllowScanlessPurge() { + PA_CHECK(0 < disallow_scanless_purge_calls_); + disallow_scanless_purge_calls_--; + + auto* branch = GetQuarantineBranch(); + PA_CHECK(branch); + branch->AllowScanlessPurge(); +} + +internal::ThreadBoundSchedulerLoopQuarantineBranch* +SchedulerLoopQuarantineScanPolicyUpdater::GetQuarantineBranch() { + ThreadCache* tcache = ThreadCache::EnsureAndGet(); + if (!ThreadCache::IsValid(tcache)) { + return nullptr; + } + + uintptr_t current_tcache_addr = reinterpret_cast(tcache); + if (tcache_address_ == 0) { + tcache_address_ = current_tcache_addr; + } else { + PA_CHECK(tcache_address_ == current_tcache_addr); + } + return &tcache->GetSchedulerLoopQuarantineBranch(); +} + namespace internal { ScopedSchedulerLoopQuarantineBranchAccessorForTesting:: ScopedSchedulerLoopQuarantineBranchAccessorForTesting( diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/scheduler_loop_quarantine_support.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/scheduler_loop_quarantine_support.h index 824dbce1d3..77842160ee 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/scheduler_loop_quarantine_support.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/scheduler_loop_quarantine_support.h @@ -2,14 +2,21 @@ // 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 PARTITION_ALLOC_SCHEDULER_LOOP_QUARANTINE_SUPPORT_H_ #define PARTITION_ALLOC_SCHEDULER_LOOP_QUARANTINE_SUPPORT_H_ +#include #include #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_root.h" #include "partition_alloc/scheduler_loop_quarantine.h" #include "partition_alloc/thread_cache.h" @@ -34,6 +41,49 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) instance_; }; +// An utility class to update Scheduler-Loop Quarantine's purging strategy for +// the current thread. By default it uses "scanless" purge for best performance. +// However, it also supports stack-scanning before purging to verify there is no +// dangling pointer in stack memory. Stack-scanning comes with some performance +// cost, but there is security benefit. This class can be used to switch between +// these two strategies dynamically. +// An example usage is to allow scanless purge only around "stack bottom". +// We can safely assume there is no dangling pointer if stack memory is barely +// used thus safe to purge quarantine. +// At Chrome layer it is task execution and we expect +// `DisallowScanlessPurge()` to be called before task execution and +// `AllowScanlessPurge()` after. Since there is no unified way to hook +// task execution in Chrome, we provide an abstract utility here. +// This class is not thread-safe. +// +// TODO(http://crbug.com/329027914): stack-scanning is not implemented yet +// and this class is effectively "disallow any purge unless really needed". +// It still gives some hints on purging timing for memory efficiency. +class PA_COMPONENT_EXPORT(PARTITION_ALLOC) + SchedulerLoopQuarantineScanPolicyUpdater { + public: + SchedulerLoopQuarantineScanPolicyUpdater(); + ~SchedulerLoopQuarantineScanPolicyUpdater(); + + // Disallows scanless purge and performs stack-scanning when needed. + // Can be called multiple times, but each call to this function must be + // followed by `AllowScanlessPurge()`. + void DisallowScanlessPurge(); + + // Re-activate scanless purge. `DisallowScanlessPurge()` must be called prior + // to use of this function. This may trigger purge immediately. + void AllowScanlessPurge(); + + private: + PA_ALWAYS_INLINE internal::ThreadBoundSchedulerLoopQuarantineBranch* + GetQuarantineBranch(); + + uint32_t disallow_scanless_purge_calls_ = 0; + + // An address of `ThreadCache` instance works as a thread ID. + uintptr_t tcache_address_ = 0; +}; + namespace internal { class PA_COMPONENT_EXPORT(PARTITION_ALLOC) 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 ebde848816..bc112965cd 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_SHIM_ALLOCATOR_DISPATCH_H_ #define PARTITION_ALLOC_SHIM_ALLOCATOR_DISPATCH_H_ 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 0ffe987a55..de10bbf5ab 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_SHIM_ALLOCATOR_INTERCEPTION_APPLE_H_ #define PARTITION_ALLOC_SHIM_ALLOCATOR_INTERCEPTION_APPLE_H_ 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 63345f8c49..f0f87234e4 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // This file contains all the logic necessary to intercept allocations on // macOS. "malloc zones" are an abstraction that allows the process to intercept // all malloc-related functions. There is no good mechanism [short of 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 fa5ee97c4d..b5ce80dbd9 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/shim/allocator_shim.h" #include 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 d43a9fffbd..fae4719e1b 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_H_ #define PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_H_ 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 a92a713606..3659a1b427 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/shim/allocator_shim.h" #include 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 6a89deeccc..3214cf5b28 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/shim/allocator_shim.h" #include 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 65eb0b3081..a59ee70449 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include #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_glibc.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_glibc.cc index 143c1d3b08..aa42c8d7f4 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include #include 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 3ef3f9170b..668ce7be53 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include #include "partition_alloc/build_config.h" 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 c864ee736b..928d1432cd 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.h" #include 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 d969bc9057..4aaf8fa9e0 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_DEFAULT_DISPATCH_TO_PARTITION_ALLOC_H_ #define 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_default_dispatch_to_partition_alloc_internal.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc_internal.h index b65a3b3ca1..2fa7ea27ee 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc_internal.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc_internal.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_DEFAULT_DISPATCH_TO_PARTITION_ALLOC_INTERNAL_H_ #define PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_DEFAULT_DISPATCH_TO_PARTITION_ALLOC_INTERNAL_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc_with_advanced_checks.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc_with_advanced_checks.cc index 99c633799a..bfa15991f6 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc_with_advanced_checks.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc_with_advanced_checks.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc_with_advanced_checks.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc_with_advanced_checks.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc_with_advanced_checks.h index 635d81354b..57ea1f778d 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc_with_advanced_checks.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc_with_advanced_checks.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_DEFAULT_DISPATCH_TO_PARTITION_ALLOC_WITH_ADVANCED_CHECKS_H_ #define PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_DEFAULT_DISPATCH_TO_PARTITION_ALLOC_WITH_ADVANCED_CHECKS_H_ 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 f994c53594..fff088fff4 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include #include "partition_alloc/partition_alloc_check.h" 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 2fa401bd45..7fca9c959e 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/shim/allocator_shim_dispatch_to_noop_on_free.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_dispatch_to_noop_on_free.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_dispatch_to_noop_on_free.h index b37bf97bfc..614c1ba6bb 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_dispatch_to_noop_on_free.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_dispatch_to_noop_on_free.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_DISPATCH_TO_NOOP_ON_FREE_H_ #define PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_DISPATCH_TO_NOOP_ON_FREE_H_ 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 15b8e5b78e..0df8695acd 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifdef PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_FUNCTIONS_H_ #error This header is meant to be included only once by allocator_shim*.cc except allocator_shim_win_component.cc #endif diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_functions_win_component.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_functions_win_component.cc index 3781708f04..a2d2872f14 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_functions_win_component.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_functions_win_component.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/shim/allocator_shim.h" #include "partition_alloc/shim/allocator_shim_functions.h" #include "partition_alloc/shim/checked_multiply_win.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_internals.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_internals.h index d7d178d646..79ab27718f 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_internals.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_internals.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_INTERNALS_H_ #define PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_INTERNALS_H_ 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 51d4b74d24..5c32bd8518 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifdef PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_OVERRIDE_APPLE_DEFAULT_ZONE_H_ #error This header is meant to be included only once by allocator_shim.cc #endif 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 4537d02cc6..d208a397df 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifdef PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_OVERRIDE_APPLE_SYMBOLS_H_ #error This header is meant to be included only once by allocator_shim.cc #endif 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 1ba4cca8db..fd9bf4c0d8 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifdef PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_OVERRIDE_CPP_SYMBOLS_H_ #error This header is meant to be included only once by allocator_shim.cc #endif 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 e26027f5a5..68fb5a4fd9 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifdef PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_OVERRIDE_GLIBC_WEAK_SYMBOLS_H_ #error This header is meant to be included only once by allocator_shim.cc #endif 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 a7206d73d7..53a77b92f0 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // Its purpose is to preempt the Libc symbols for malloc/new so they call the // shim layer entry points. 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 3a63ea77c9..98457c72b4 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifdef PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_OVERRIDE_LINKER_WRAPPED_SYMBOLS_H_ #error This header is meant to be included only once by allocator_shim.cc #endif 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 450719d362..1bfc7d32b4 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // This header defines symbols to override the same functions in the Visual C++ // CRT implementation. 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 f60e2b7e36..2cd1ae10b3 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/build_config.h" #include "partition_alloc/buildflags.h" #include "partition_alloc/shim/allocator_dispatch.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 dc1061e4b4..2439b45c7e 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/build_config.h" #include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/checked_multiply_win.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/checked_multiply_win.h index a520b07139..e868dec5f6 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/checked_multiply_win.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/checked_multiply_win.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_SHIM_CHECKED_MULTIPLY_WIN_H_ #define PARTITION_ALLOC_SHIM_CHECKED_MULTIPLY_WIN_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/early_zone_registration_constants.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/early_zone_registration_constants.h index 68c7324440..821a84d42e 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/early_zone_registration_constants.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/early_zone_registration_constants.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_SHIM_EARLY_ZONE_REGISTRATION_CONSTANTS_H_ #define PARTITION_ALLOC_SHIM_EARLY_ZONE_REGISTRATION_CONSTANTS_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/empty.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/empty.cc index b8096fd662..d7d300c5a4 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/empty.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/empty.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // This empty.cc is built when use_allocator_shim is false to avoid // the situation: no object files are linked to build allocator_shim.dll. // If allocator_shim target's sources has only header files, no object diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/malloc_zone_functions_apple.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/malloc_zone_functions_apple.cc index 6d7b5c9625..eeb33dd299 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/malloc_zone_functions_apple.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/malloc_zone_functions_apple.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/shim/malloc_zone_functions_apple.h" #include 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 1eeb3b7d2c..a96449482f 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_SHIM_MALLOC_ZONE_FUNCTIONS_APPLE_H_ #define PARTITION_ALLOC_SHIM_MALLOC_ZONE_FUNCTIONS_APPLE_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 7ae82b01a6..2d0a64436d 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifdef PARTITION_ALLOC_SHIM_SHIM_ALLOC_FUNCTIONS_H_ #error This header is meant to be included only once by allocator_shim*.cc #endif 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 cc02584a20..8dc4a7d4e9 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // This code should move into the default Windows shim once the win-specific // allocation shim has been removed, and the generic shim has becaome the // default. 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 61055584cf..e3fef1fe64 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // Thin allocation wrappers for the windows heap. This file should be deleted // once the win-specific allocation shim has been removed, and the generic shim // has becaome the default. 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 e427e5362b..da7885756a 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/spinning_mutex.h" #include 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 08e99d6fa3..a456727a3f 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_SPINNING_MUTEX_H_ #define PARTITION_ALLOC_SPINNING_MUTEX_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/arm/push_registers_asm.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/arm/push_registers_asm.cc index 4a0e0cb7ae..b18a0ea073 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/arm/push_registers_asm.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/arm/push_registers_asm.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // Push all callee-saved registers to get them on the stack for conservative // stack scanning. // diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/arm64/push_registers_asm.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/arm64/push_registers_asm.cc index e9e872f1f2..75885b1161 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/arm64/push_registers_asm.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/arm64/push_registers_asm.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // Push all callee-saved registers to get them on the stack for conservative // stack scanning. // diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/loong64/push_registers_asm.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/loong64/push_registers_asm.cc index 574c9ea846..c58a5bd6db 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/loong64/push_registers_asm.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/loong64/push_registers_asm.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // Push all callee-saved registers to get them on the stack for conservative // stack scanning. // diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/riscv64/push_registers_asm.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/riscv64/push_registers_asm.cc index b387211a43..4ddfd1787b 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/riscv64/push_registers_asm.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/riscv64/push_registers_asm.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // Push all callee-saved registers to get them on the stack for conservative // stack scanning. // diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/x64/push_registers_asm.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/x64/push_registers_asm.cc index b5ed711624..d204a6ce59 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/x64/push_registers_asm.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/x64/push_registers_asm.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // Push all callee-saved registers to get them on the stack for conservative // stack scanning. // diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/x86/push_registers_asm.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/x86/push_registers_asm.cc index edf6d11fdd..40cf7345a4 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/x86/push_registers_asm.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/asm/x86/push_registers_asm.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // Push all callee-saved registers to get them on the stack for conservative // stack scanning. // 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 efa2fc298a..542b30c202 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/stack/stack.h" #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/stack.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/stack.h index 504924c484..b57e09ef68 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/stack.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/stack.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_STACK_STACK_H_ #define PARTITION_ALLOC_STACK_STACK_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 0258d90d7b..c598bb3935 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/tagging.h" #include 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 08b6d24311..a60311270f 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_TAGGING_H_ #define 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 05fd78ee8e..e0a52923e0 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/thread_cache.h" #include @@ -382,9 +387,6 @@ void ThreadCache::RemoveTombstoneForTesting() { // static void ThreadCache::Init(PartitionRoot* root) { -#if PA_BUILDFLAG(IS_NACL) - static_assert(false, "PartitionAlloc isn't supported for NaCl"); -#endif PA_CHECK(root->buckets[kBucketCount - 1].slot_size == ThreadCache::kLargeSizeThreshold); PA_CHECK(root->buckets[largest_active_bucket_index_].slot_size == @@ -408,6 +410,15 @@ void ThreadCache::Init(PartitionRoot* root) { SetGlobalLimits(root, kDefaultMultiplier); } +// static +ThreadCache* ThreadCache::EnsureAndGet() { + PartitionRoot* root = g_thread_cache_root.load(std::memory_order_relaxed); + if (root) { + return root->EnsureThreadCache(); + } + return nullptr; +} + // static void ThreadCache::SetGlobalLimits(PartitionRoot* root, float multiplier) { size_t initial_value = 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 5bb1fe87f2..67c9c9ab30 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_THREAD_CACHE_H_ #define PARTITION_ALLOC_THREAD_CACHE_H_ @@ -270,6 +275,8 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) ThreadCache { #endif } + static ThreadCache* EnsureAndGet(); + static bool IsValid(ThreadCache* tcache) { // Do not MTE-untag, as it'd mess up the sentinel value. return reinterpret_cast(tcache) & kTombstoneMask; 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 9b68a05fc6..4a7ed2880f 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_THREAD_ISOLATION_ALIGNMENT_H_ #define PARTITION_ALLOC_THREAD_ISOLATION_ALIGNMENT_H_ 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 47ea68cdab..005fb0d7a1 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/thread_isolation/pkey.h" #if PA_BUILDFLAG(ENABLE_PKEYS) 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 8c233f6bc5..38d5df29c9 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_THREAD_ISOLATION_PKEY_H_ #define PARTITION_ALLOC_THREAD_ISOLATION_PKEY_H_ 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 f22b55b49a..089316c8bd 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #include "partition_alloc/thread_isolation/thread_isolation.h" #if PA_BUILDFLAG(ENABLE_THREAD_ISOLATION) 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 f3dbe9de17..454c2144f5 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 @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_THREAD_ISOLATION_THREAD_ISOLATION_H_ #define PARTITION_ALLOC_THREAD_ISOLATION_THREAD_ISOLATION_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/use_death_tests.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/use_death_tests.h index 7c795d4cee..ed52070eb6 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/use_death_tests.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/use_death_tests.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_USE_DEATH_TESTS_H_ #define PARTITION_ALLOC_USE_DEATH_TESTS_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/yield_processor.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/yield_processor.h index e486f59a3c..82e7bd198a 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/yield_processor.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/yield_processor.h @@ -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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + #ifndef PARTITION_ALLOC_YIELD_PROCESSOR_H_ #define PARTITION_ALLOC_YIELD_PROCESSOR_H_ diff --git a/naiveproxy/src/base/allocator/scheduler_loop_quarantine_config.cc b/naiveproxy/src/base/allocator/scheduler_loop_quarantine_config.cc new file mode 100644 index 0000000000..b8b1e20249 --- /dev/null +++ b/naiveproxy/src/base/allocator/scheduler_loop_quarantine_config.cc @@ -0,0 +1,146 @@ +// Copyright 2025 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/allocator/scheduler_loop_quarantine_config.h" + +#include + +#include "base/allocator/partition_alloc_features.h" +#include "base/feature_list.h" +#include "base/json/json_reader.h" +#include "base/logging.h" +#include "base/notreached.h" +#include "base/strings/safe_sprintf.h" +#include "base/strings/strcat.h" + +namespace base::allocator { + +namespace { +// For configuration purpose use "browser" instead of "" for visibility. +constexpr char kProcessTypeBrowserStr[] = "browser"; +constexpr char kProcessTypeWildcardStr[] = "*"; +// SchedulerLoopQuarantineBranchType string representation. +constexpr char kBranchTypeGlobalStr[] = "global"; +constexpr char kBranchTypeThreadLocalDefaultStr[] = "*"; +constexpr char kBranchTypeMainStr[] = "main"; + +constexpr std::string_view GetSchedulerLoopQuarantineBranchTypeStr( + SchedulerLoopQuarantineBranchType type) { + switch (type) { + case SchedulerLoopQuarantineBranchType::kGlobal: + return kBranchTypeGlobalStr; + case SchedulerLoopQuarantineBranchType::kThreadLocalDefault: + return kBranchTypeThreadLocalDefaultStr; + case SchedulerLoopQuarantineBranchType::kMain: + return kBranchTypeMainStr; + } + NOTREACHED(); +} + +#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) +// JSON parsing options. +constexpr int kJSONParserOptions = + JSONParserOptions::JSON_PARSE_CHROMIUM_EXTENSIONS | + JSONParserOptions::JSON_ALLOW_TRAILING_COMMAS; + +// JSON keys for parameters. +constexpr char kKeyEnableQuarantine[] = "enable-quarantine"; +constexpr char kKeyEnableZapping[] = "enable-zapping"; +constexpr char kKeyLeakOnDestruction[] = "leak-on-destruction"; +constexpr char kKeyBranchCapacityInBytes[] = "branch-capacity-in-bytes"; +#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) +} // namespace + +::partition_alloc::internal::SchedulerLoopQuarantineConfig +GetSchedulerLoopQuarantineConfiguration( + const std::string& process_type, + SchedulerLoopQuarantineBranchType branch_type) { + ::partition_alloc::internal::SchedulerLoopQuarantineConfig config = {}; + + std::string_view process_type_str = process_type; + if (process_type_str.empty()) { + process_type_str = kProcessTypeBrowserStr; + } + // Should not be a special name. + DCHECK_NE(process_type_str, kProcessTypeWildcardStr); + + std::string_view branch_type_str = + GetSchedulerLoopQuarantineBranchTypeStr(branch_type); + + // Set a branch name like "browser/main" or "renderer/*"; + std::string branch_name = + base::StrCat({process_type_str, "/", branch_type_str}); + // `std::string::copy` does not append a null character. + branch_name.copy(config.branch_name, sizeof(config.branch_name) - 1); + config.branch_name[sizeof(config.branch_name) - 1] = '\0'; + +#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) + if (!FeatureList::IsEnabled( + features::kPartitionAllocSchedulerLoopQuarantine)) { + return config; // Feature disabled. + } + + // TODO(https://crbug.com/434693933): Also read from command-line switches + // to support an enterprise policy. It is loaded after PA configuration in + // child processes so we should pass it from the Browser process via switches. + std::string config_str = + features::kPartitionAllocSchedulerLoopQuarantineConfig.Get(); + + std::optional config_processes = + JSONReader::ReadDict(config_str, kJSONParserOptions); + if (!config_processes) { + LOG(ERROR) << "Unparseable JSON: " << config_str; + return config; // Ill-formed JSON; disabled. + } + + const Value::Dict* config_entry = nullptr; + + const Value::Dict* config_current_process = + config_processes->FindDict(process_type_str); + if (config_current_process) { + // First, try the exact match. + config_entry = config_current_process->FindDict(branch_type_str); + + // Falls back to thread-local default unless global. + if (!config_entry && + branch_type != SchedulerLoopQuarantineBranchType::kGlobal) { + config_entry = + config_current_process->FindDict(kBranchTypeThreadLocalDefaultStr); + } + } + + Value::Dict* config_wildcard_process = + config_processes->FindDict(kProcessTypeWildcardStr); + if (!config_entry && config_wildcard_process) { + // Couldn't find a configuration entry with the exact process name match. + // Look-up an entry with a process name being "*". + config_entry = config_wildcard_process->FindDict(branch_type_str); + + // Falls back to thread-local default unless global. + if (!config_entry && + branch_type != SchedulerLoopQuarantineBranchType::kGlobal) { + config_entry = + config_wildcard_process->FindDict(kBranchTypeThreadLocalDefaultStr); + } + } + + if (!config_entry) { + VLOG(1) << "No entry found for " << branch_name << "."; + return config; // No config found; disabled. + } + + config.enable_quarantine = config_entry->FindBool(kKeyEnableQuarantine) + .value_or(config.enable_quarantine); + config.enable_zapping = + config_entry->FindBool(kKeyEnableZapping).value_or(config.enable_zapping); + config.leak_on_destruction = config_entry->FindBool(kKeyLeakOnDestruction) + .value_or(config.leak_on_destruction); + config.branch_capacity_in_bytes = + static_cast(config_entry->FindInt(kKeyBranchCapacityInBytes) + .value_or(config.branch_capacity_in_bytes)); +#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) + + return config; +} +} // namespace base::allocator diff --git a/naiveproxy/src/base/allocator/scheduler_loop_quarantine_config.h b/naiveproxy/src/base/allocator/scheduler_loop_quarantine_config.h new file mode 100644 index 0000000000..50e421e208 --- /dev/null +++ b/naiveproxy/src/base/allocator/scheduler_loop_quarantine_config.h @@ -0,0 +1,35 @@ +// Copyright 2025 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_ALLOCATOR_SCHEDULER_LOOP_QUARANTINE_CONFIG_H_ +#define BASE_ALLOCATOR_SCHEDULER_LOOP_QUARANTINE_CONFIG_H_ + +#include + +#include "base/base_export.h" +#include "partition_alloc/scheduler_loop_quarantine_support.h" + +// This header declares utilities to load +// `::partition_alloc::internal::SchedulerLoopQuarantineConfig` for the current +// process from the feature list. +namespace base::allocator { + +enum class SchedulerLoopQuarantineBranchType { + // The global quarantine branch, shared across threads. + kGlobal, + // Default configuration for thread-local branches on new threads. + kThreadLocalDefault, + // Specialized configuration for the main thread of a process. + kMain, +}; + +// Returns quarantine configuration for `process_name` and `branch_type`. +BASE_EXPORT ::partition_alloc::internal::SchedulerLoopQuarantineConfig +GetSchedulerLoopQuarantineConfiguration( + const std::string& process_type, + SchedulerLoopQuarantineBranchType branch_type); + +} // namespace base::allocator + +#endif // BASE_ALLOCATOR_SCHEDULER_LOOP_QUARANTINE_CONFIG_H_ diff --git a/naiveproxy/src/base/allocator/unittest_utils.cc b/naiveproxy/src/base/allocator/unittest_utils.cc index 6e728b29c0..fcec8c455a 100644 --- a/naiveproxy/src/base/allocator/unittest_utils.cc +++ b/naiveproxy/src/base/allocator/unittest_utils.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/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + // The unittests need a this in order to link up without pulling in tons // of other libraries diff --git a/naiveproxy/src/base/android/android_image_reader_compat.cc b/naiveproxy/src/base/android/android_image_reader_compat.cc deleted file mode 100644 index 662e23aca2..0000000000 --- a/naiveproxy/src/base/android/android_image_reader_compat.cc +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2018 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/android_image_reader_compat.h" - -namespace base { -namespace android { - -bool EnableAndroidImageReader() { - // Currently we want to enable AImageReader only for android P+ devices. - if (__builtin_available(android 28, *)) { - return true; - } - return false; -} - -} // namespace android -} // namespace base diff --git a/naiveproxy/src/base/android/android_image_reader_compat.h b/naiveproxy/src/base/android/android_image_reader_compat.h deleted file mode 100644 index 5e2bd9e569..0000000000 --- a/naiveproxy/src/base/android/android_image_reader_compat.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2018 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_ANDROID_IMAGE_READER_COMPAT_H_ -#define BASE_ANDROID_ANDROID_IMAGE_READER_COMPAT_H_ - -#include "base/base_export.h" - -namespace base { -namespace android { - -// Check if the image reader usage is supported. -BASE_EXPORT bool EnableAndroidImageReader(); - -} // namespace android -} // namespace base - -#endif // BASE_ANDROID_ANDROID_IMAGE_READER_COMPAT_H_ diff --git a/naiveproxy/src/base/android/android_info.cc b/naiveproxy/src/base/android/android_info.cc index 632029bac7..2d59521611 100644 --- a/naiveproxy/src/base/android/android_info.cc +++ b/naiveproxy/src/base/android/android_info.cc @@ -28,10 +28,6 @@ using aidl::org::chromium::base::IAndroidInfo; #endif -namespace base::android::android_info { - -namespace { - #if __ANDROID_API__ < 29 struct IAndroidInfo { const std::string abiName; @@ -54,6 +50,10 @@ struct IAndroidInfo { }; #endif +namespace base::android::android_info { + +namespace { + static std::optional& get_holder() { static base::NoDestructor> holder; return *holder; @@ -69,6 +69,12 @@ const IAndroidInfo& get_android_info() { } // namespace +void Set(const IAndroidInfo& info) { + std::optional& holder = get_holder(); + DCHECK(!holder.has_value()); + holder.emplace(info); +} + static void JNI_AndroidInfo_FillFields(JNIEnv* env, std::string& brand, std::string& device, @@ -86,10 +92,7 @@ static void JNI_AndroidInfo_FillFields(JNIEnv* env, jint sdkInt, jboolean isDebugAndroid, std::string& securityPatch) { - std::optional& holder = get_holder(); - DCHECK(!holder.has_value()); - holder.emplace( - IAndroidInfo{.abiName = supportedAbis, + Set(IAndroidInfo{.abiName = supportedAbis, .androidBuildFp = androidBuildFingerprint, .androidBuildId = buildId, .board = board, diff --git a/naiveproxy/src/base/android/android_info.h b/naiveproxy/src/base/android/android_info.h index 4a9e51c6ff..c124a93b0a 100644 --- a/naiveproxy/src/base/android/android_info.h +++ b/naiveproxy/src/base/android/android_info.h @@ -8,6 +8,14 @@ #include #include "base/base_export.h" +#if __ANDROID_API__ >= 29 +namespace aidl::org::chromium::base { +class IAndroidInfo; +} // namespace aidl::org::chromium::base +using ::aidl::org::chromium::base::IAndroidInfo; +#else +struct IAndroidInfo; +#endif namespace base::android::android_info { @@ -70,6 +78,7 @@ const std::string& abi_name(); BASE_EXPORT const std::string& security_patch(); +BASE_EXPORT void Set(const IAndroidInfo& info); } // namespace base::android::android_info #endif // BASE_ANDROID_ANDROID_INFO_H_ diff --git a/naiveproxy/src/base/android/apk_info.cc b/naiveproxy/src/base/android/apk_info.cc index de707f3fb1..294708135b 100644 --- a/naiveproxy/src/base/android/apk_info.cc +++ b/naiveproxy/src/base/android/apk_info.cc @@ -58,6 +58,12 @@ const IApkInfo& get_apk_info() { } // namespace +void Set(const IApkInfo& info) { + std::optional& holder = get_holder(); + DCHECK(!holder.has_value()); + holder.emplace(info); +} + static void JNI_ApkInfo_FillFields(JNIEnv* env, std::string& hostPackageName, std::string& hostVersionCode, @@ -69,18 +75,16 @@ static void JNI_ApkInfo_FillFields(JNIEnv* env, std::string& installerPackageName, jboolean isDebugApp, jint targetSdkVersion) { - std::optional& holder = get_holder(); - DCHECK(!holder.has_value()); - holder.emplace(IApkInfo{.hostPackageLabel = hostPackageLabel, - .hostPackageName = hostPackageName, - .hostVersionCode = hostVersionCode, - .installerPackageName = installerPackageName, - .isDebugApp = static_cast(isDebugApp), - .packageName = packageName, - .packageVersionCode = packageVersionCode, - .packageVersionName = packageVersionName, - .resourcesVersion = resourcesVersion, - .targetSdkVersion = targetSdkVersion}); + Set(IApkInfo{.hostPackageLabel = hostPackageLabel, + .hostPackageName = hostPackageName, + .hostVersionCode = hostVersionCode, + .installerPackageName = installerPackageName, + .isDebugApp = static_cast(isDebugApp), + .packageName = packageName, + .packageVersionCode = packageVersionCode, + .packageVersionName = packageVersionName, + .resourcesVersion = resourcesVersion, + .targetSdkVersion = targetSdkVersion}); } const std::string& host_package_name() { diff --git a/naiveproxy/src/base/android/apk_info.h b/naiveproxy/src/base/android/apk_info.h index a3d14ec314..03c28c75d0 100644 --- a/naiveproxy/src/base/android/apk_info.h +++ b/naiveproxy/src/base/android/apk_info.h @@ -7,6 +7,17 @@ #include +#include "base/base_export.h" + +#if __ANDROID_API__ >= 29 +namespace aidl::org::chromium::base { +class IApkInfo; +} // namespace aidl::org::chromium::base +using ::aidl::org::chromium::base::IApkInfo; +#else +struct IApkInfo; +#endif + namespace base::android::apk_info { // The package name of the host app which has loaded WebView, retrieved from // the application context. In the context of the SDK Runtime, the package @@ -39,7 +50,6 @@ bool is_debug_app(); int target_sdk_version(); -bool targets_at_least_u(); - +BASE_EXPORT void Set(const IApkInfo& info); } // namespace base::android::apk_info #endif // BASE_ANDROID_APK_INFO_H_ diff --git a/naiveproxy/src/base/android/base_jni_onload.cc b/naiveproxy/src/base/android/base_jni_init.cc similarity index 91% rename from naiveproxy/src/base/android/base_jni_onload.cc rename to naiveproxy/src/base/android/base_jni_init.cc index 3e80a5aa5e..c542051f05 100644 --- a/naiveproxy/src/base/android/base_jni_onload.cc +++ b/naiveproxy/src/base/android/base_jni_init.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 "base/android/base_jni_onload.h" +#include "base/android/base_jni_init.h" #include "base/android/jni_android.h" #include "base/android/jni_utils.h" diff --git a/naiveproxy/src/base/android/base_jni_onload.h b/naiveproxy/src/base/android/base_jni_init.h similarity index 76% rename from naiveproxy/src/base/android/base_jni_onload.h rename to naiveproxy/src/base/android/base_jni_init.h index 5f989033a4..ba34bb2cf7 100644 --- a/naiveproxy/src/base/android/base_jni_onload.h +++ b/naiveproxy/src/base/android/base_jni_init.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 BASE_ANDROID_BASE_JNI_ONLOAD_H_ -#define BASE_ANDROID_BASE_JNI_ONLOAD_H_ +#ifndef BASE_ANDROID_BASE_JNI_INIT_H_ +#define BASE_ANDROID_BASE_JNI_INIT_H_ #include @@ -19,4 +19,4 @@ BASE_EXPORT bool OnJNIOnLoadInit(); } // namespace android } // namespace base -#endif // BASE_ANDROID_BASE_JNI_ONLOAD_H_ +#endif // BASE_ANDROID_BASE_JNI_INIT_H_ diff --git a/naiveproxy/src/base/android/binder.cc b/naiveproxy/src/base/android/binder.cc deleted file mode 100644 index 1601dec40d..0000000000 --- a/naiveproxy/src/base/android/binder.cc +++ /dev/null @@ -1,556 +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 "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, flags); - 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(); -} - -} // 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 deleted file mode 100644 index 915fcaf6d4..0000000000 --- a/naiveproxy/src/base/android/binder.h +++ /dev/null @@ -1,408 +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 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 deleted file mode 100644 index fa0481feeb..0000000000 --- a/naiveproxy/src/base/android/binder_box.cc +++ /dev/null @@ -1,93 +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 "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 deleted file mode 100644 index ae5236442a..0000000000 --- a/naiveproxy/src/base/android/binder_box.h +++ /dev/null @@ -1,39 +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 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 82bb2e7a25..a6452abeeb 100644 --- a/naiveproxy/src/base/android/build_info.h +++ b/naiveproxy/src/base/android/build_info.h @@ -160,7 +160,7 @@ class BASE_EXPORT BuildInfo { private: friend struct BuildInfoSingletonTraits; - explicit BuildInfo(); + BuildInfo(); const std::string brand_; const std::string device_; diff --git a/naiveproxy/src/base/android/child_process_binding_types.h b/naiveproxy/src/base/android/child_process_binding_types.h index 9d45897b91..dee98656f9 100644 --- a/naiveproxy/src/base/android/child_process_binding_types.h +++ b/naiveproxy/src/base/android/child_process_binding_types.h @@ -10,9 +10,14 @@ namespace android { // Defines the state of bindgings with child process. See ChildProcessConnection // to see what the bindings are. +// +// Note that the numerical order in ChildBindingState should be consistent +// because ChildBindingState is compared numerically in +// ChildProcessRanking.java. +// // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.base enum class ChildBindingState { - UNBOUND, + UNBOUND = 0, WAIVED, NOT_PERCEPTIBLE, VISIBLE, diff --git a/naiveproxy/src/base/android/child_process_service.cc b/naiveproxy/src/base/android/child_process_service.cc index 2165bdddf4..0002bfa9db 100644 --- a/naiveproxy/src/base/android/child_process_service.cc +++ b/naiveproxy/src/base/android/child_process_service.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/android/child_process_service.h" + #include #include "base/android/jni_array.h" @@ -22,6 +24,31 @@ using base::android::JavaParamRef; namespace base { namespace android { +void RegisterFileDescriptors(std::vector>& keys, + std::vector& ids, + std::vector& fds, + std::vector& offsets, + std::vector& sizes) { + DCHECK_EQ(keys.size(), ids.size()); + DCHECK_EQ(ids.size(), fds.size()); + DCHECK_EQ(fds.size(), offsets.size()); + DCHECK_EQ(offsets.size(), sizes.size()); + + for (size_t i = 0; i < ids.size(); i++) { + base::MemoryMappedFile::Region region = {offsets.at(i), + static_cast(sizes.at(i))}; + const std::optional& key = keys.at(i); + const auto id = static_cast(ids.at(i)); + int fd = fds.at(i); + if (key) { + base::FileDescriptorStore::GetInstance().Set(*key, base::ScopedFD(fd), + region); + } else { + base::GlobalDescriptors::GetInstance()->Set(id, fd, region); + } + } +} + void JNI_ChildProcessService_RegisterFileDescriptors( JNIEnv* env, const JavaParamRef& j_keys, @@ -48,25 +75,7 @@ void JNI_ChildProcessService_RegisterFileDescriptors( base::android::JavaLongArrayToInt64Vector(env, j_offsets, &offsets); std::vector sizes; base::android::JavaLongArrayToInt64Vector(env, j_sizes, &sizes); - - DCHECK_EQ(keys.size(), ids.size()); - DCHECK_EQ(ids.size(), fds.size()); - DCHECK_EQ(fds.size(), offsets.size()); - DCHECK_EQ(offsets.size(), sizes.size()); - - for (size_t i = 0; i < ids.size(); i++) { - base::MemoryMappedFile::Region region = {offsets.at(i), - static_cast(sizes.at(i))}; - const std::optional& key = keys.at(i); - const auto id = static_cast(ids.at(i)); - int fd = fds.at(i); - if (key) { - base::FileDescriptorStore::GetInstance().Set(*key, base::ScopedFD(fd), - region); - } else { - base::GlobalDescriptors::GetInstance()->Set(id, fd, region); - } - } + RegisterFileDescriptors(keys, ids, fds, offsets, sizes); } void JNI_ChildProcessService_ExitChildProcess(JNIEnv* env) { @@ -79,11 +88,19 @@ void JNI_ChildProcessService_ExitChildProcess(JNIEnv* env) { // the function body unique by adding a log line, so it doesn't get merged // with other functions by link time optimizations (ICF). NOINLINE void JNI_ChildProcessService_DumpProcessStack(JNIEnv* env) { + DumpProcessStack(); +} + +void DumpProcessStack() { LOG(ERROR) << "Dumping as requested."; base::debug::DumpWithoutCrashing(); } void JNI_ChildProcessService_OnSelfFreeze(JNIEnv* env) { + OnSelfFreeze(); +} + +void OnSelfFreeze() { SelfCompactionManager::OnSelfFreeze(); } diff --git a/naiveproxy/src/base/android/child_process_service.h b/naiveproxy/src/base/android/child_process_service.h new file mode 100644 index 0000000000..222d29a728 --- /dev/null +++ b/naiveproxy/src/base/android/child_process_service.h @@ -0,0 +1,27 @@ +// Copyright 2025 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_CHILD_PROCESS_SERVICE_H_ +#define BASE_ANDROID_CHILD_PROCESS_SERVICE_H_ + +#include +#include +#include + +#include "base/base_export.h" + +namespace base::android { + +BASE_EXPORT void RegisterFileDescriptors( + std::vector>& keys, + std::vector& ids, + std::vector& fds, + std::vector& offsets, + std::vector& sizes); +BASE_EXPORT void DumpProcessStack(); +BASE_EXPORT void OnSelfFreeze(); + +} // namespace base::android + +#endif // BASE_ANDROID_CHILD_PROCESS_SERVICE_H_ diff --git a/naiveproxy/src/base/android/command_line_android.cc b/naiveproxy/src/base/android/command_line_android.cc index bb93f9599b..d71142efb9 100644 --- a/naiveproxy/src/base/android/command_line_android.cc +++ b/naiveproxy/src/base/android/command_line_android.cc @@ -1,10 +1,10 @@ // 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. - -#include "base/command_line.h" +#include "base/android/command_line_android.h" #include "base/android/jni_string.h" +#include "base/command_line.h" // Must come after all headers that specialize FromJniType() / ToJniType(). #include "base/command_line_jni/CommandLine_jni.h" @@ -60,8 +60,14 @@ static void JNI_CommandLine_RemoveSwitch(JNIEnv* env, static void JNI_CommandLine_Init(JNIEnv* env, std::vector& init_command_line) { + base::android::CommandLineInit(init_command_line); +} + +namespace base::android { +void CommandLineInit(std::vector& command_line) { // TODO(port): Make an overload of Init() that takes StringVector rather than // have to round-trip via AppendArguments. CommandLine::Init(0, nullptr); - AppendToCommandLine(init_command_line, true); + AppendToCommandLine(command_line, true); } +} // namespace base::android diff --git a/naiveproxy/src/base/android/command_line_android.h b/naiveproxy/src/base/android/command_line_android.h new file mode 100644 index 0000000000..58b54f8d20 --- /dev/null +++ b/naiveproxy/src/base/android/command_line_android.h @@ -0,0 +1,17 @@ +// Copyright 2025 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_COMMAND_LINE_ANDROID_H_ +#define BASE_ANDROID_COMMAND_LINE_ANDROID_H_ + +#include +#include + +#include "base/base_export.h" + +namespace base::android { +BASE_EXPORT void CommandLineInit(std::vector& command_line); +} // namespace base::android + +#endif // BASE_ANDROID_COMMAND_LINE_ANDROID_H_ diff --git a/naiveproxy/src/base/android/content_uri_utils.cc b/naiveproxy/src/base/android/content_uri_utils.cc index 59bc6ccd34..a1cb71c9cd 100644 --- a/naiveproxy/src/base/android/content_uri_utils.cc +++ b/naiveproxy/src/base/android/content_uri_utils.cc @@ -40,6 +40,8 @@ std::optional TranslateOpenFlagsToJavaMode(uint32_t open_flags) { switch (open_flags) { case File::FLAG_OPEN | File::FLAG_READ: + case File::FLAG_OPEN_ALWAYS | File::FLAG_READ: + case File::FLAG_CREATE | File::FLAG_READ: return "r"; case File::FLAG_OPEN_ALWAYS | File::FLAG_READ | File::FLAG_WRITE: return "rw"; diff --git a/naiveproxy/src/base/android/device_info.cc b/naiveproxy/src/base/android/device_info.cc index 81ed790284..6374a41793 100644 --- a/naiveproxy/src/base/android/device_info.cc +++ b/naiveproxy/src/base/android/device_info.cc @@ -35,6 +35,7 @@ struct IDeviceInfo { bool isTv; // Available only on Android T+. int32_t vulkanDeqpLevel; + bool isXr; }; #endif @@ -53,21 +54,27 @@ IDeviceInfo& get_device_info() { } // namespace +void Set(const IDeviceInfo& info) { + std::optional& holder = get_holder(); + DCHECK(!holder.has_value()); + holder.emplace(info); +} + static void JNI_DeviceInfo_FillFields(JNIEnv* env, std::string& gmsVersionCode, jboolean isTV, jboolean isAutomotive, jboolean isFoldable, jboolean isDesktop, - jint vulkanDeqpLevel) { - std::optional& holder = get_holder(); - DCHECK(!holder.has_value()); - holder.emplace(IDeviceInfo{.gmsVersionCode = gmsVersionCode, - .isAutomotive = static_cast(isAutomotive), - .isDesktop = static_cast(isDesktop), - .isFoldable = static_cast(isFoldable), - .isTv = static_cast(isTV), - .vulkanDeqpLevel = vulkanDeqpLevel}); + jint vulkanDeqpLevel, + jboolean isXr) { + Set(IDeviceInfo{.gmsVersionCode = gmsVersionCode, + .isAutomotive = static_cast(isAutomotive), + .isDesktop = static_cast(isDesktop), + .isFoldable = static_cast(isFoldable), + .isTv = static_cast(isTV), + .vulkanDeqpLevel = vulkanDeqpLevel, + .isXr = static_cast(isXr)}); } const std::string& gms_version_code() { @@ -99,4 +106,17 @@ int32_t vulkan_deqp_level() { return get_device_info().vulkanDeqpLevel; } +bool is_xr() { + return get_device_info().isXr; +} + +void set_is_xr_for_testing() { + Java_DeviceInfo_setIsXrForTesting(AttachCurrentThread()); // IN-TEST + get_holder().reset(); +} + +void reset_is_xr_for_testing() { + Java_DeviceInfo_resetIsXrForTesting(AttachCurrentThread()); // IN-TEST + get_holder().reset(); +} } // namespace base::android::device_info diff --git a/naiveproxy/src/base/android/device_info.h b/naiveproxy/src/base/android/device_info.h index 65dde11bcf..f4715bcf5e 100644 --- a/naiveproxy/src/base/android/device_info.h +++ b/naiveproxy/src/base/android/device_info.h @@ -7,18 +7,36 @@ #include +#include "base/base_export.h" + +#if __ANDROID_API__ >= 29 +namespace aidl::org::chromium::base { +class IDeviceInfo; +} // namespace aidl::org::chromium::base +using ::aidl::org::chromium::base::IDeviceInfo; +#else +struct IDeviceInfo; +#endif + namespace base::android::device_info { -const std::string& gms_version_code(); +BASE_EXPORT const std::string& gms_version_code(); -void set_gms_version_code_for_test(const std::string& gms_version_code); +BASE_EXPORT void set_gms_version_code_for_test( + const std::string& gms_version_code); -bool is_tv(); -bool is_automotive(); -bool is_foldable(); -bool is_desktop(); +BASE_EXPORT void Set(const IDeviceInfo& info); + +BASE_EXPORT bool is_tv(); +BASE_EXPORT bool is_automotive(); +BASE_EXPORT bool is_foldable(); +BASE_EXPORT bool is_desktop(); // Available only on Android T+. -int32_t vulkan_deqp_level(); +BASE_EXPORT int32_t vulkan_deqp_level(); +BASE_EXPORT bool is_xr(); +// For testing use only. +BASE_EXPORT void set_is_xr_for_testing(); +BASE_EXPORT void reset_is_xr_for_testing(); } // namespace base::android::device_info #endif // BASE_ANDROID_DEVICE_INFO_H_ diff --git a/naiveproxy/src/base/android/field_trial_list.cc b/naiveproxy/src/base/android/field_trial_list.cc index 80740b762e..e1856d43ed 100644 --- a/naiveproxy/src/base/android/field_trial_list.cc +++ b/naiveproxy/src/base/android/field_trial_list.cc @@ -6,11 +6,11 @@ #include #include "base/android/jni_string.h" -#include "base/lazy_instance.h" #include "base/logging.h" #include "base/metrics/field_trial.h" #include "base/metrics/field_trial_list_including_low_anonymity.h" #include "base/metrics/field_trial_params.h" +#include "base/no_destructor.h" // Must come after all headers that specialize FromJniType() / ToJniType(). #include "base/base_jni/FieldTrialList_jni.h" @@ -43,8 +43,10 @@ class TrialLogger : public base::FieldTrialList::Observer { ~TrialLogger() override = default; }; -base::LazyInstance::Leaky g_trial_logger = - LAZY_INSTANCE_INITIALIZER; +TrialLogger* GetTrialLogger() { + static base::NoDestructor trial_logger; + return trial_logger.get(); +} } // namespace @@ -92,11 +94,12 @@ class AndroidFieldTrialListLogActiveTrialsFriendHelper { }; static void JNI_FieldTrialList_LogActiveTrials(JNIEnv* env) { - DCHECK(!g_trial_logger.IsCreated()); // This need only be called once. + static int called_count = 0; + DCHECK_EQ(called_count++, 0); // This need only be called once. LOG(INFO) << "Logging active field trials..."; AndroidFieldTrialListLogActiveTrialsFriendHelper::AddObserver( - &g_trial_logger.Get()); + GetTrialLogger()); // Log any trials that were already active before adding the observer. std::vector active_groups; diff --git a/naiveproxy/src/base/android/input_hint_checker.cc b/naiveproxy/src/base/android/input_hint_checker.cc index 0f08387a0e..690b3831c5 100644 --- a/naiveproxy/src/base/android/input_hint_checker.cc +++ b/naiveproxy/src/base/android/input_hint_checker.cc @@ -94,8 +94,9 @@ void InputHintChecker::SetView( // 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())); + view_class_ = ScopedJavaGlobalRef( + env, ScopedJavaLocalRef::Adopt( + env, env->GetObjectClass(root_view.obj()))); pthread_t new_thread; if (pthread_create(&new_thread, nullptr, OffThreadInitInvoker::Run, nullptr) != 0) { diff --git a/naiveproxy/src/base/android/java_exception_reporter.cc b/naiveproxy/src/base/android/java_exception_reporter.cc index 025796a9ee..2c60a59be6 100644 --- a/naiveproxy/src/base/android/java_exception_reporter.cc +++ b/naiveproxy/src/base/android/java_exception_reporter.cc @@ -9,8 +9,8 @@ #include "base/debug/dump_without_crashing.h" #include "base/functional/bind.h" #include "base/functional/callback.h" -#include "base/lazy_instance.h" #include "base/logging.h" +#include "base/no_destructor.h" // Must come after all headers that specialize FromJniType() / ToJniType(). #include "base/base_minimal_jni/JavaExceptionReporter_jni.h" @@ -27,8 +27,10 @@ JavaExceptionCallback g_java_exception_callback; using JavaExceptionFilter = base::RepeatingCallback&)>; -LazyInstance::Leaky g_java_exception_filter = - LAZY_INSTANCE_INITIALIZER; +JavaExceptionFilter& GetJavaExceptionFilter() { + static base::NoDestructor java_exception_filter; + return *java_exception_filter; +} } // namespace @@ -57,7 +59,7 @@ void InitJavaExceptionReporterForChildProcess() { } void SetJavaExceptionFilter(JavaExceptionFilter java_exception_filter) { - g_java_exception_filter.Get() = std::move(java_exception_filter); + GetJavaExceptionFilter() = std::move(java_exception_filter); } void SetJavaExceptionCallback(JavaExceptionCallback callback) { @@ -82,7 +84,7 @@ void JNI_JavaExceptionReporter_ReportJavaException( jboolean crash_after_report, const JavaRef& e) { std::string exception_info = base::android::GetJavaExceptionInfo(env, e); - bool should_report_exception = g_java_exception_filter.Get().Run(e); + bool should_report_exception = GetJavaExceptionFilter().Run(e); if (should_report_exception) { SetJavaException(exception_info.c_str()); } diff --git a/naiveproxy/src/base/android/jni_android.cc b/naiveproxy/src/base/android/jni_android.cc index a885fda4b0..ad08aeeff2 100644 --- a/naiveproxy/src/base/android/jni_android.cc +++ b/naiveproxy/src/base/android/jni_android.cc @@ -49,7 +49,8 @@ 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)); + auto j_class_name = + ScopedJavaLocalRef::Adopt(env, env->NewStringUTF(class_name)); return static_cast(env->CallObjectMethod( GetSplitClassLoader(env, split_name), g_class_loader_load_class_method_id, j_class_name.obj())); @@ -62,7 +63,7 @@ jclass GetClassFromSplit(JNIEnv* env, void PrepareClassLoaders(JNIEnv* env) { if (g_class_loader_load_class_method_id == nullptr) { GetClassLoader(env); - ScopedJavaLocalRef class_loader_clazz = ScopedJavaLocalRef( + auto class_loader_clazz = ScopedJavaLocalRef::Adopt( env, env->FindClass("java/lang/ClassLoader")); CHECK(!ClearException(env)); g_class_loader_load_class_method_id = diff --git a/naiveproxy/src/base/android/jni_array.cc b/naiveproxy/src/base/android/jni_array.cc index ccd44a7973..762c0e6126 100644 --- a/naiveproxy/src/base/android/jni_array.cc +++ b/naiveproxy/src/base/android/jni_array.cc @@ -37,7 +37,7 @@ ScopedJavaLocalRef ToJavaByteArray( reinterpret_cast(bytes.data())); CheckException(env); - return ScopedJavaLocalRef(env, byte_array); + return ScopedJavaLocalRef::Adopt(env, byte_array); } ScopedJavaLocalRef ToJavaByteArray(JNIEnv* env, @@ -68,7 +68,7 @@ ScopedJavaLocalRef ToJavaBooleanArray(JNIEnv* env, reinterpret_cast(bools.data())); CheckException(env); - return ScopedJavaLocalRef(env, boolean_array); + return ScopedJavaLocalRef::Adopt(env, boolean_array); } ScopedJavaLocalRef ToJavaIntArray(JNIEnv* env, @@ -83,7 +83,7 @@ ScopedJavaLocalRef ToJavaIntArray(JNIEnv* env, reinterpret_cast(ints.data())); CheckException(env); - return ScopedJavaLocalRef(env, int_array); + return ScopedJavaLocalRef::Adopt(env, int_array); } // Returns a new Java long array converted from the given int64_t array. @@ -101,7 +101,7 @@ BASE_EXPORT ScopedJavaLocalRef ToJavaLongArray( reinterpret_cast(longs.data())); CheckException(env); - return ScopedJavaLocalRef(env, long_array); + return ScopedJavaLocalRef::Adopt(env, long_array); } BASE_EXPORT ScopedJavaLocalRef ToJavaFloatArray( @@ -119,7 +119,7 @@ BASE_EXPORT ScopedJavaLocalRef ToJavaFloatArray( reinterpret_cast(floats.data())); CheckException(env); - return ScopedJavaLocalRef(env, float_array); + return ScopedJavaLocalRef::Adopt(env, float_array); } BASE_EXPORT ScopedJavaLocalRef ToJavaDoubleArray( @@ -137,7 +137,7 @@ BASE_EXPORT ScopedJavaLocalRef ToJavaDoubleArray( reinterpret_cast(doubles.data())); CheckException(env); - return ScopedJavaLocalRef(env, double_array); + return ScopedJavaLocalRef::Adopt(env, double_array); } BASE_EXPORT ScopedJavaLocalRef ToJavaArrayOfObjects( @@ -151,7 +151,7 @@ BASE_EXPORT ScopedJavaLocalRef ToJavaArrayOfObjects( for (size_t i = 0; i < v.size(); ++i) { env->SetObjectArrayElement(joa, checked_cast(i), v[i].obj()); } - return ScopedJavaLocalRef(env, joa); + return ScopedJavaLocalRef::Adopt(env, joa); } BASE_EXPORT ScopedJavaLocalRef ToJavaArrayOfObjects( @@ -170,7 +170,7 @@ BASE_EXPORT ScopedJavaLocalRef ToJavaArrayOfObjects( for (size_t i = 0; i < v.size(); ++i) { env->SetObjectArrayElement(joa, checked_cast(i), v[i].obj()); } - return ScopedJavaLocalRef(env, joa); + return ScopedJavaLocalRef::Adopt(env, joa); } BASE_EXPORT ScopedJavaLocalRef ToTypedJavaArrayOfObjects( @@ -184,7 +184,7 @@ BASE_EXPORT ScopedJavaLocalRef ToTypedJavaArrayOfObjects( for (size_t i = 0; i < v.size(); ++i) { env->SetObjectArrayElement(joa, checked_cast(i), v[i].obj()); } - return ScopedJavaLocalRef(env, joa); + return ScopedJavaLocalRef::Adopt(env, joa); } BASE_EXPORT ScopedJavaLocalRef ToTypedJavaArrayOfObjects( @@ -198,7 +198,7 @@ BASE_EXPORT ScopedJavaLocalRef ToTypedJavaArrayOfObjects( for (size_t i = 0; i < v.size(); ++i) { env->SetObjectArrayElement(joa, checked_cast(i), v[i].obj()); } - return ScopedJavaLocalRef(env, joa); + return ScopedJavaLocalRef::Adopt(env, joa); } ScopedJavaLocalRef ToJavaArrayOfByteArray( @@ -213,7 +213,7 @@ ScopedJavaLocalRef ToJavaArrayOfByteArray( ScopedJavaLocalRef byte_array = ToJavaByteArray(env, v[i]); env->SetObjectArrayElement(joa, checked_cast(i), byte_array.obj()); } - return ScopedJavaLocalRef(env, joa); + return ScopedJavaLocalRef::Adopt(env, joa); } ScopedJavaLocalRef ToJavaArrayOfByteArray( @@ -228,7 +228,7 @@ ScopedJavaLocalRef ToJavaArrayOfByteArray( ScopedJavaLocalRef byte_array = ToJavaByteArray(env, v[i]); env->SetObjectArrayElement(joa, checked_cast(i), byte_array.obj()); } - return ScopedJavaLocalRef(env, joa); + return ScopedJavaLocalRef::Adopt(env, joa); } ScopedJavaLocalRef ToJavaArrayOfStrings( @@ -242,7 +242,7 @@ ScopedJavaLocalRef ToJavaArrayOfStrings( ScopedJavaLocalRef item = ConvertUTF8ToJavaString(env, v[i]); env->SetObjectArrayElement(joa, checked_cast(i), item.obj()); } - return ScopedJavaLocalRef(env, joa); + return ScopedJavaLocalRef::Adopt(env, joa); } ScopedJavaLocalRef ToJavaArrayOfStringArray( @@ -261,7 +261,7 @@ ScopedJavaLocalRef ToJavaArrayOfStringArray( env->SetObjectArrayElement(joa, checked_cast(i), inner.obj()); } - return ScopedJavaLocalRef(env, joa); + return ScopedJavaLocalRef::Adopt(env, joa); } ScopedJavaLocalRef ToJavaArrayOfStringArray( @@ -280,7 +280,7 @@ ScopedJavaLocalRef ToJavaArrayOfStringArray( env->SetObjectArrayElement(joa, checked_cast(i), inner.obj()); } - return ScopedJavaLocalRef(env, joa); + return ScopedJavaLocalRef::Adopt(env, joa); } ScopedJavaLocalRef ToJavaArrayOfStrings( @@ -294,7 +294,7 @@ ScopedJavaLocalRef ToJavaArrayOfStrings( ScopedJavaLocalRef item = ConvertUTF16ToJavaString(env, v[i]); env->SetObjectArrayElement(joa, checked_cast(i), item.obj()); } - return ScopedJavaLocalRef(env, joa); + return ScopedJavaLocalRef::Adopt(env, joa); } void AppendJavaStringArrayToStringVector(JNIEnv* env, @@ -311,7 +311,7 @@ void AppendJavaStringArrayToStringVector(JNIEnv* env, out->resize(out->size() + len); span back = span(*out).last(len); for (size_t i = 0; i < len; ++i) { - ScopedJavaLocalRef str( + auto str = ScopedJavaLocalRef::Adopt( env, static_cast(env->GetObjectArrayElement( array.obj(), checked_cast(i)))); ConvertJavaStringToUTF16(env, str.obj(), &back[i]); @@ -332,7 +332,7 @@ void AppendJavaStringArrayToStringVector(JNIEnv* env, out->resize(out->size() + len); span back = span(*out).last(len); for (size_t i = 0; i < len; ++i) { - ScopedJavaLocalRef str( + auto str = ScopedJavaLocalRef::Adopt( env, static_cast(env->GetObjectArrayElement( array.obj(), checked_cast(i)))); ConvertJavaStringToUTF8(env, str.obj(), &back[i]); @@ -490,7 +490,7 @@ void JavaArrayOfByteArrayToStringVector(JNIEnv* env, size_t len = SafeGetArrayLength(env, array); out->resize(len); for (size_t i = 0; i < len; ++i) { - ScopedJavaLocalRef bytes_array( + auto bytes_array = ScopedJavaLocalRef::Adopt( env, static_cast(env->GetObjectArrayElement( array.obj(), checked_cast(i)))); size_t bytes_len = SafeGetArrayLength(env, bytes_array); @@ -517,7 +517,7 @@ void JavaArrayOfByteArrayToBytesVector(JNIEnv* env, const size_t len = SafeGetArrayLength(env, array); out->resize(len); for (size_t i = 0; i < len; ++i) { - ScopedJavaLocalRef bytes_array( + auto bytes_array = ScopedJavaLocalRef::Adopt( env, static_cast(env->GetObjectArrayElement( array.obj(), checked_cast(i)))); JavaByteArrayToByteVector(env, bytes_array, &(*out)[i]); @@ -532,7 +532,7 @@ void Java2dStringArrayTo2dStringVector( size_t len = SafeGetArrayLength(env, array); out->resize(len); for (size_t i = 0; i < len; ++i) { - ScopedJavaLocalRef strings_array( + auto strings_array = ScopedJavaLocalRef::Adopt( env, static_cast(env->GetObjectArrayElement( array.obj(), checked_cast(i)))); @@ -549,7 +549,7 @@ void Java2dStringArrayTo2dStringVector( size_t len = SafeGetArrayLength(env, array); out->resize(len); for (size_t i = 0; i < len; ++i) { - ScopedJavaLocalRef strings_array( + auto strings_array = ScopedJavaLocalRef::Adopt( env, static_cast(env->GetObjectArrayElement( array.obj(), checked_cast(i)))); @@ -565,7 +565,7 @@ void JavaArrayOfIntArrayToIntVector(JNIEnv* env, size_t len = SafeGetArrayLength(env, array); out->resize(len); for (size_t i = 0; i < len; ++i) { - ScopedJavaLocalRef int_array( + auto int_array = ScopedJavaLocalRef::Adopt( env, static_cast(env->GetObjectArrayElement( array.obj(), checked_cast(i)))); JavaIntArrayToIntVector(env, int_array, &(*out)[i]); diff --git a/naiveproxy/src/base/android/jni_bytebuffer.cc b/naiveproxy/src/base/android/jni_bytebuffer.cc index 83a696d881..ce9dc44f41 100644 --- a/naiveproxy/src/base/android/jni_bytebuffer.cc +++ b/naiveproxy/src/base/android/jni_bytebuffer.cc @@ -8,13 +8,17 @@ namespace base::android { -base::span JavaByteBufferToSpan(JNIEnv* env, jobject buffer) { +base::span JavaByteBufferToSpan( + JNIEnv* env, + const jni_zero::JavaRef& buffer) { auto span = MaybeJavaByteBufferToSpan(env, buffer); CHECK(span.has_value()); return *span; } -base::span JavaByteBufferToMutableSpan(JNIEnv* env, jobject buffer) { +base::span JavaByteBufferToMutableSpan( + JNIEnv* env, + const jni_zero::JavaRef& buffer) { auto span = MaybeJavaByteBufferToMutableSpan(env, buffer); CHECK(span.has_value()); return *span; @@ -22,7 +26,7 @@ base::span JavaByteBufferToMutableSpan(JNIEnv* env, jobject buffer) { std::optional> MaybeJavaByteBufferToSpan( JNIEnv* env, - jobject buffer) { + const jni_zero::JavaRef& buffer) { auto span = MaybeJavaByteBufferToMutableSpan(env, buffer); return span ? std::make_optional(base::span(*span)) : std::nullopt; @@ -30,9 +34,9 @@ std::optional> MaybeJavaByteBufferToSpan( std::optional> MaybeJavaByteBufferToMutableSpan( JNIEnv* env, - jobject buffer) { - void* data = env->GetDirectBufferAddress(buffer); - jlong size = env->GetDirectBufferCapacity(buffer); + const jni_zero::JavaRef& buffer) { + void* data = env->GetDirectBufferAddress(buffer.obj()); + jlong size = env->GetDirectBufferCapacity(buffer.obj()); // !data && size == 0 is allowed - this is how a 0-length Buffer is // represented. diff --git a/naiveproxy/src/base/android/jni_bytebuffer.h b/naiveproxy/src/base/android/jni_bytebuffer.h index 990f6729e7..71a7bf201b 100644 --- a/naiveproxy/src/base/android/jni_bytebuffer.h +++ b/naiveproxy/src/base/android/jni_bytebuffer.h @@ -5,12 +5,11 @@ #ifndef BASE_ANDROID_JNI_BYTEBUFFER_H_ #define BASE_ANDROID_JNI_BYTEBUFFER_H_ -#include - #include #include "base/base_export.h" #include "base/containers/span.h" +#include "third_party/jni_zero/jni_zero.h" namespace base::android { @@ -26,17 +25,20 @@ namespace base::android { // // If needed, there are also variants below starting with Maybe that return // std::nullopt in that case and do not crash. -base::span BASE_EXPORT JavaByteBufferToSpan(JNIEnv* env, - jobject buffer); +base::span BASE_EXPORT +JavaByteBufferToSpan(JNIEnv* env, const jni_zero::JavaRef& buffer); -base::span BASE_EXPORT JavaByteBufferToMutableSpan(JNIEnv* env, - jobject buffer); +base::span BASE_EXPORT +JavaByteBufferToMutableSpan(JNIEnv* env, + const jni_zero::JavaRef& buffer); std::optional> BASE_EXPORT -MaybeJavaByteBufferToSpan(JNIEnv* env, jobject buffer); +MaybeJavaByteBufferToSpan(JNIEnv* env, + const jni_zero::JavaRef& buffer); std::optional> BASE_EXPORT -MaybeJavaByteBufferToMutableSpan(JNIEnv* env, jobject buffer); +MaybeJavaByteBufferToMutableSpan(JNIEnv* env, + const jni_zero::JavaRef& buffer); } // namespace base::android diff --git a/naiveproxy/src/base/android/jni_callback.cc b/naiveproxy/src/base/android/jni_callback.cc index 9b97caba62..7dd26f49ae 100644 --- a/naiveproxy/src/base/android/jni_callback.cc +++ b/naiveproxy/src/base/android/jni_callback.cc @@ -96,7 +96,7 @@ ScopedJavaLocalRef ToJniCallback( JNIEnv* env, const base::RepeatingCallback& callback) { return ToJniCallback( - env, base::BindOnce( + env, base::BindRepeating( [](const base::RepeatingCallback& captured_callback, const jni_zero::JavaRef& j_null) { // For callbacks with no parameters, the parameter from Java diff --git a/naiveproxy/src/base/android/jni_onload.cc b/naiveproxy/src/base/android/jni_onload.cc new file mode 100644 index 0000000000..24a7d6893e --- /dev/null +++ b/naiveproxy/src/base/android/jni_onload.cc @@ -0,0 +1,17 @@ +// Copyright 2025 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_onload.h" + +#include "base/android/jni_android.h" +#include "base/android/library_loader/library_loader_hooks.h" + +// This does not live in the "base" component, but rather belongs to a +// source_set that must be included in the root component of a shared library. +// Component build requires the OnLoad symbol to be available in the root +// component. +JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { + base::android::InitVM(vm); + base::android::SetNativeInitializationHook(NativeInitializationHook); + return JNI_VERSION_1_4; +} diff --git a/naiveproxy/src/base/android/jni_onload.h b/naiveproxy/src/base/android/jni_onload.h new file mode 100644 index 0000000000..2c6d622daf --- /dev/null +++ b/naiveproxy/src/base/android/jni_onload.h @@ -0,0 +1,15 @@ +// Copyright 2025 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_JNI_ONLOAD_H_ +#define BASE_ANDROID_JNI_ONLOAD_H_ + +#include "base/android/library_loader/library_loader_hooks.h" + +// The JNI_OnLoad in //base cannot depend on any specific process type's init +// function, so we have this hook that we compile different implementations +// for depending on what shared library we are building. +bool NativeInitializationHook(base::android::LibraryProcessType value); + +#endif // BASE_ANDROID_JNI_ONLOAD_H_ diff --git a/naiveproxy/src/base/android/jni_registrar.cc b/naiveproxy/src/base/android/jni_registrar.cc index 827a33ff66..80e8fa8c97 100644 --- a/naiveproxy/src/base/android/jni_registrar.cc +++ b/naiveproxy/src/base/android/jni_registrar.cc @@ -2,14 +2,10 @@ // 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/jni_registrar.h" #include "base/android/jni_android.h" +#include "base/compiler_specific.h" #include "base/logging.h" #include "base/trace_event/trace_event.h" @@ -20,13 +16,13 @@ bool RegisterNativeMethods(JNIEnv* env, const RegistrationMethod* method, size_t count) { TRACE_EVENT0("startup", "base_android::RegisterNativeMethods"); - const RegistrationMethod* end = method + count; + const RegistrationMethod* end = UNSAFE_TODO(method + count); while (method != end) { if (!method->func(env)) { DLOG(ERROR) << method->name << " failed registration!"; return false; } - method++; + UNSAFE_TODO(method++); } return true; } diff --git a/naiveproxy/src/base/android/jni_string.cc b/naiveproxy/src/base/android/jni_string.cc index cea0be7a68..ede1f29689 100644 --- a/naiveproxy/src/base/android/jni_string.cc +++ b/naiveproxy/src/base/android/jni_string.cc @@ -94,7 +94,7 @@ ScopedJavaLocalRef ConvertUTF8ToJavaString(JNIEnv* env, // it gets here, so constructing via UTF16 side-steps this issue. // (Dalvik stores strings internally as UTF16 anyway, so there shouldn't be // a significant performance hit by doing it this way). - return ScopedJavaLocalRef( + return ScopedJavaLocalRef::Adopt( env, ConvertUTF16ToJavaStringImpl(env, UTF8ToUTF16(str))); } @@ -155,8 +155,8 @@ ScopedJavaLocalRef ConvertUTF16ToJavaString(JNIEnv* env, if (str.empty()) { return jni_zero::g_empty_string.AsLocalRef(env); } - return ScopedJavaLocalRef(env, - ConvertUTF16ToJavaStringImpl(env, str)); + return ScopedJavaLocalRef::Adopt( + env, ConvertUTF16ToJavaStringImpl(env, str)); } } // namespace android diff --git a/naiveproxy/src/base/android/jni_utils.cc b/naiveproxy/src/base/android/jni_utils.cc index 1fdc90c3bd..78afb9210d 100644 --- a/naiveproxy/src/base/android/jni_utils.cc +++ b/naiveproxy/src/base/android/jni_utils.cc @@ -7,7 +7,6 @@ #include "base/android/jni_string.h" #include "base/android/scoped_java_ref.h" #include "base/containers/flat_map.h" -#include "base/lazy_instance.h" #include "base/no_destructor.h" #include "base/synchronization/lock.h" diff --git a/naiveproxy/src/base/android/library_loader/library_loader_hooks.cc b/naiveproxy/src/base/android/library_loader/library_loader_hooks.cc index cc20604b9a..056278ec97 100644 --- a/naiveproxy/src/base/android/library_loader/library_loader_hooks.cc +++ b/naiveproxy/src/base/android/library_loader/library_loader_hooks.cc @@ -44,29 +44,30 @@ void SetLibraryLoadedHook(LibraryLoadedHook* func) { g_registration_callback = func; } -static jboolean JNI_LibraryLoader_LibraryLoaded(JNIEnv* env, - jint library_process_type) { +bool LibraryLoaded(LibraryProcessType library_process_type) { DCHECK_EQ(g_library_process_type, PROCESS_UNINITIALIZED); - g_library_process_type = - static_cast(library_process_type); + g_library_process_type = library_process_type; #if BUILDFLAG(ORDERFILE_INSTRUMENTATION) orderfile::StartDelayedDump(); #endif if (g_native_initialization_hook && - !g_native_initialization_hook( - static_cast(library_process_type))) { + !g_native_initialization_hook(library_process_type)) { return false; } if (g_registration_callback && - !g_registration_callback( - static_cast(library_process_type))) { + !g_registration_callback(library_process_type)) { return false; } return true; } +static jboolean JNI_LibraryLoader_LibraryLoaded(JNIEnv* env, + jint library_process_type) { + return LibraryLoaded(static_cast(library_process_type)); +} + void LibraryLoaderExitHook() { if (g_at_exit_manager) { delete g_at_exit_manager; diff --git a/naiveproxy/src/base/android/library_loader/library_loader_hooks.h b/naiveproxy/src/base/android/library_loader/library_loader_hooks.h index 8213d1a2c7..a7772c8edc 100644 --- a/naiveproxy/src/base/android/library_loader/library_loader_hooks.h +++ b/naiveproxy/src/base/android/library_loader/library_loader_hooks.h @@ -66,6 +66,10 @@ BASE_EXPORT void LibraryLoaderExitHook(); // shared library. void InitAtExitManager(); +// First symbol called after library is done loading, and our OnLoad has +// finished. Sets and calls global initializer delegates. +BASE_EXPORT bool LibraryLoaded(LibraryProcessType library_process_type); + } // namespace android } // namespace base diff --git a/naiveproxy/src/base/android/linker/BUILD.gn b/naiveproxy/src/base/android/linker/BUILD.gn index 662c56cf27..91175a3d37 100644 --- a/naiveproxy/src/base/android/linker/BUILD.gn +++ b/naiveproxy/src/base/android/linker/BUILD.gn @@ -17,7 +17,7 @@ shared_library("chromium_android_linker") { deps = [ "//build:buildflag_header_h", - "//third_party/jni_zero:jni_zero", + "//third_party/jni_zero", ] # Export JNI symbols. diff --git a/naiveproxy/src/base/android/meminfo_dump_provider.cc b/naiveproxy/src/base/android/meminfo_dump_provider.cc index 75bf503cbb..10899a5921 100644 --- a/naiveproxy/src/base/android/meminfo_dump_provider.cc +++ b/naiveproxy/src/base/android/meminfo_dump_provider.cc @@ -73,7 +73,8 @@ bool MeminfoDumpProvider::OnMemoryDump( return false; } - ScopedJavaLocalRef clazz{env, env->GetObjectClass(memory_info.obj())}; + auto clazz = ScopedJavaLocalRef::Adopt( + env, env->GetObjectClass(memory_info.obj())); jfieldID other_private_dirty_id = env->GetFieldID(clazz.obj(), "otherPrivateDirty", "I"); diff --git a/naiveproxy/src/base/android/pmf_utils.cc b/naiveproxy/src/base/android/pmf_utils.cc index 8bcf121140..6858ea329f 100644 --- a/naiveproxy/src/base/android/pmf_utils.cc +++ b/naiveproxy/src/base/android/pmf_utils.cc @@ -2,17 +2,13 @@ // 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/pmf_utils.h" #include #include #include +#include "base/compiler_specific.h" #include "base/strings/string_number_conversions.h" #include "base/threading/thread_restrictions.h" @@ -30,30 +26,32 @@ std::optional CalculateProcessMemoryFootprint( constexpr uint32_t kMaxLineSize = 4096; char line[kMaxLineSize]; - int n = statm_file.ReadAtCurrentPos(line, sizeof(line) - 1); + int n = UNSAFE_TODO(statm_file.ReadAtCurrentPos(line, sizeof(line) - 1)); if (n <= 0) { return std::optional(); } - line[n] = '\0'; + UNSAFE_TODO(line[n]) = '\0'; - int num_scanned = sscanf(line, "%" SCNu64 " %" SCNu64 " %" SCNu64, - &vm_size_pages, &resident_pages, &shared_pages); + int num_scanned = + UNSAFE_TODO(sscanf(line, "%" SCNu64 " %" SCNu64 " %" SCNu64, + &vm_size_pages, &resident_pages, &shared_pages)); if (num_scanned != 3) { return std::optional(); } // Get swap size from status file. The format is: VmSwap : 10 kB. - n = status_file.ReadAtCurrentPos(line, sizeof(line) - 1); + n = UNSAFE_TODO(status_file.ReadAtCurrentPos(line, sizeof(line) - 1)); if (n <= 0) { return std::optional(); } - line[n] = '\0'; + UNSAFE_TODO(line[n]) = '\0'; - char* swap_line = strstr(line, "VmSwap"); + char* swap_line = UNSAFE_TODO(strstr(line, "VmSwap")); if (!swap_line) { return std::optional(); } - num_scanned = sscanf(swap_line, "VmSwap: %" SCNu64 " kB", &swap_footprint); + num_scanned = + UNSAFE_TODO(sscanf(swap_line, "VmSwap: %" SCNu64 " kB", &swap_footprint)); if (num_scanned != 1) { return std::optional(); } diff --git a/naiveproxy/src/base/android/pre_freeze_background_memory_trimmer.cc b/naiveproxy/src/base/android/pre_freeze_background_memory_trimmer.cc index 31f6e71316..fa8c4ee3d4 100644 --- a/naiveproxy/src/base/android/pre_freeze_background_memory_trimmer.cc +++ b/naiveproxy/src/base/android/pre_freeze_background_memory_trimmer.cc @@ -43,11 +43,6 @@ enum class MetricsFailure { kMaxValue = kMeasureFailure }; -// These values are logged to UMA. Entries should not be renumbered and -// numeric values should never be reused. Please keep in sync with -// "PreFreezeReadProcMapsType" in tools/metrics/histograms/enums.xml. -enum class ReadProcMaps { kFailed, kEmpty, kSuccess, kMaxValue = kSuccess }; - // This constant is chosen arbitrarily, to allow time for the background tasks // to finish running BEFORE collecting metrics. constexpr base::TimeDelta kDelayForMetrics = base::Seconds(2); @@ -216,106 +211,6 @@ void PreFreezeBackgroundMemoryTrimmer::PostMetricsTask() { kDelayForMetrics); } -void SelfCompactionManager::CompactionMetric::MaybeRecordCompactionMetrics() { - // If we did not record smaps_rollup for any reason, such as returning to - // foreground, being frozen by App Freezer, or failing to read - // /proc/self/smaps_rollup, skip emitting metrics. - if (!smaps_before_.has_value() || !smaps_after_.has_value() || - !smaps_after_1s_.has_value() || !smaps_after_10s_.has_value() || - !smaps_after_60s_.has_value()) { - return; - } - - if (!ShouldContinueCompaction(compaction_triggered_at_)) { - return; - } - - // Record absolute values of each metric. - RecordCompactionMetrics(*smaps_before_, "Before"); - RecordCompactionMetrics(*smaps_after_, "After"); - RecordCompactionMetrics(*smaps_after_1s_, "After1s"); - RecordCompactionMetrics(*smaps_after_10s_, "After10s"); - RecordCompactionMetrics(*smaps_after_60s_, "After60s"); - - // Record diff of before and after to see how much memory was compacted. - RecordCompactionDiffMetrics(*smaps_before_, *smaps_after_, "BeforeAfter"); - - // Record diff after a delay, so we can see if any memory comes back after - // compaction. - RecordCompactionDiffMetrics(*smaps_after_, *smaps_after_1s_, "After1s"); - RecordCompactionDiffMetrics(*smaps_after_, *smaps_after_10s_, "After10s"); - RecordCompactionDiffMetrics(*smaps_after_, *smaps_after_60s_, "After60s"); -} - -void SelfCompactionManager::CompactionMetric::RecordCompactionMetric( - size_t value_bytes, - std::string_view metric_name, - std::string_view suffix) { - UmaHistogramMemoryMB(GetMetricName(metric_name, suffix), - static_cast(BytesToMiB(value_bytes))); -} - -void SelfCompactionManager::CompactionMetric::RecordCompactionMetrics( - const debug::SmapsRollup& value, - std::string_view suffix) { - RecordCompactionMetric(value.rss, "Rss", suffix); - RecordCompactionMetric(value.pss, "Pss", suffix); - RecordCompactionMetric(value.pss_anon, "PssAnon", suffix); - RecordCompactionMetric(value.pss_file, "PssFile", suffix); - RecordCompactionMetric(value.swap_pss, "SwapPss", suffix); -} - -void SelfCompactionManager::CompactionMetric::RecordCompactionDiffMetric( - size_t before_value_bytes, - size_t after_value_bytes, - std::string_view name, - std::string_view suffix) { - size_t diff_non_negative = std::max(before_value_bytes, after_value_bytes) - - std::min(before_value_bytes, after_value_bytes); - const std::string full_suffix = StrCat( - {"Diff.", suffix, ".", - before_value_bytes < after_value_bytes ? "Increase" : "Decrease"}); - RecordCompactionMetric(diff_non_negative, name, full_suffix); -} - -void SelfCompactionManager::CompactionMetric::RecordCompactionDiffMetrics( - const debug::SmapsRollup& before, - const debug::SmapsRollup& after, - std::string_view suffix) { - RecordCompactionDiffMetric(before.rss, after.rss, "Rss", suffix); - RecordCompactionDiffMetric(before.pss, after.pss, "Pss", suffix); - RecordCompactionDiffMetric(before.pss_anon, after.pss_anon, "PssAnon", - suffix); - RecordCompactionDiffMetric(before.pss_file, after.pss_file, "PssFile", - suffix); - RecordCompactionDiffMetric(before.swap_pss, after.swap_pss, "SwapPss", - suffix); -} - -void SelfCompactionManager::CompactionMetric::RecordSmapsRollup( - std::optional* target) { - if (!ShouldContinueCompaction(compaction_triggered_at_)) { - return; - } - - *target = debug::ReadAndParseSmapsRollup(); - - MaybeRecordCompactionMetrics(); -} - -void SelfCompactionManager::CompactionMetric::RecordSmapsRollupWithDelay( - std::optional* target, - base::TimeDelta delay) { - base::ThreadPool::PostDelayedTask( - FROM_HERE, {base::TaskPriority::BEST_EFFORT, MayBlock()}, - base::BindOnce( - &SelfCompactionManager::CompactionMetric::RecordSmapsRollup, - // |target| is a member a of |this|, so it's lifetime is - // always ok here. - this, base::Unretained(target)), - delay); -} - // static void PreFreezeBackgroundMemoryTrimmer::PostDelayedBackgroundTask( scoped_refptr task_runner, @@ -422,32 +317,6 @@ void PreFreezeBackgroundMemoryTrimmer::UnregisterMemoryMetricInternal( metrics_.erase(metrics_.begin() + index); } -SelfCompactionManager::CompactionState::CompactionState( - scoped_refptr task_runner, - base::TimeTicks triggered_at, - uint64_t max_bytes) - : task_runner_(std::move(task_runner)), - triggered_at_(triggered_at), - max_bytes_(max_bytes) {} - -SelfCompactionManager::CompactionState::~CompactionState() = default; - -void SelfCompactionManager::CompactionState::MaybeReadProcMaps() { - DCHECK(regions_.empty()); - auto did_read_proc_maps = ReadProcMaps::kSuccess; - if (IsFeatureEnabled()) { - std::string proc_maps; - if (!debug::ReadProcMaps(&proc_maps) || - !ParseProcMaps(proc_maps, ®ions_)) { - did_read_proc_maps = ReadProcMaps::kFailed; - } else if (regions_.size() == 0) { - did_read_proc_maps = ReadProcMaps::kEmpty; - } - } - - UmaHistogramEnumeration(GetMetricName("ReadProcMaps"), did_read_proc_maps); -} - // static void PreFreezeBackgroundMemoryTrimmer::OnPreFreeze() { // If we have scheduled a self compaction task, cancel it, since App Freezer @@ -495,6 +364,13 @@ void PreFreezeBackgroundMemoryTrimmer::OnPreFreezeInternal() { RunPreFreezeTasks(); } +void PreFreezeBackgroundMemoryTrimmer::PostMetricsTasksIfModern() { + if (!SupportsModernTrim()) { + return; + } + PostMetricsTask(); +} + // static void PreFreezeBackgroundMemoryTrimmer::UnregisterBackgroundTask( BackgroundTask* task) { @@ -653,44 +529,4 @@ PreFreezeBackgroundMemoryTrimmer::PreFreezeMetric::PreFreezeMetric( PreFreezeBackgroundMemoryTrimmer::PreFreezeMetric::~PreFreezeMetric() = default; -SelfCompactionManager::CompactionMetric::CompactionMetric( - const std::string& name, - base::TimeTicks triggered_at, - base::TimeTicks started_at) - : name_(name), - compaction_triggered_at_(triggered_at), - compaction_started_at_(started_at) {} -SelfCompactionManager::CompactionMetric::~CompactionMetric() = default; - -std::string SelfCompactionManager::CompactionMetric::GetMetricName( - std::string_view name) const { - return StrCat({name_, name}); -} - -std::string SelfCompactionManager::CompactionMetric::GetMetricName( - std::string_view name, - std::string_view suffix) const { - return StrCat({name_, name, ".", suffix}); -} - -void SelfCompactionManager::CompactionMetric::RecordBeforeMetrics() { - RecordSmapsRollup(&smaps_before_); -} - -void SelfCompactionManager::CompactionMetric::RecordDelayedMetrics() { - RecordSmapsRollup(&smaps_after_); - RecordSmapsRollupWithDelay(&smaps_after_1s_, base::Seconds(1)); - RecordSmapsRollupWithDelay(&smaps_after_10s_, base::Seconds(10)); - RecordSmapsRollupWithDelay(&smaps_after_60s_, base::Seconds(60)); -} - -void SelfCompactionManager::CompactionMetric::RecordTimeMetrics( - base::TimeTicks last_finished, - base::TimeTicks last_cancelled) { - UmaHistogramMediumTimes(GetMetricName("SelfCompactionTime"), - last_finished - compaction_started_at_); - UmaHistogramMediumTimes(GetMetricName("TimeSinceLastCancel"), - last_finished - last_cancelled); -} - } // namespace base::android diff --git a/naiveproxy/src/base/android/robolectric_jni_onload.cc b/naiveproxy/src/base/android/robolectric_jni_onload.cc index ba537e6316..c4ba987d8e 100644 --- a/naiveproxy/src/base/android/robolectric_jni_onload.cc +++ b/naiveproxy/src/base/android/robolectric_jni_onload.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include -#include "base/android/base_jni_onload.h" +#include "base/android/base_jni_init.h" #include "base/android/jni_android.h" extern "C" JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { diff --git a/naiveproxy/src/base/android/scoped_java_ref.h b/naiveproxy/src/base/android/scoped_java_ref.h index 2e5cf817a6..eb71538751 100644 --- a/naiveproxy/src/base/android/scoped_java_ref.h +++ b/naiveproxy/src/base/android/scoped_java_ref.h @@ -11,18 +11,16 @@ namespace base { namespace android { using ScopedJavaLocalFrame = jni_zero::ScopedJavaLocalFrame; -template +template using JavaRef = jni_zero::JavaRef; -template +template using JavaObjectArrayReader = jni_zero::JavaObjectArrayReader; -template +template using JavaParamRef = jni_zero::JavaParamRef; -template +template using ScopedJavaLocalRef = jni_zero::ScopedJavaLocalRef; -template +template using ScopedJavaGlobalRef = jni_zero::ScopedJavaGlobalRef; -template -using JavaObjectArrayReader = jni_zero::JavaObjectArrayReader; } // namespace android } // namespace base diff --git a/naiveproxy/src/base/android/self_compaction_manager.cc b/naiveproxy/src/base/android/self_compaction_manager.cc index 433f77efdc..c999720db3 100644 --- a/naiveproxy/src/base/android/self_compaction_manager.cc +++ b/naiveproxy/src/base/android/self_compaction_manager.cc @@ -51,6 +51,11 @@ BASE_FEATURE_PARAM(size_t, namespace { +// These values are logged to UMA. Entries should not be renumbered and +// numeric values should never be reused. Please keep in sync with +// "PreFreezeReadProcMapsType" in tools/metrics/histograms/enums.xml. +enum class ReadProcMaps { kFailed, kEmpty, kSuccess, kMaxValue = kSuccess }; + bool IsMadvisePageoutSupported() { static bool supported = []() -> bool { #if defined(MADV_PAGEOUT) @@ -78,6 +83,10 @@ bool IsMadvisePageoutSupported() { // be more than enough. constexpr base::TimeDelta kCompactionTimeout = base::Seconds(10); +uint64_t BytesToMiB(uint64_t v) { + return v / 1024 / 1024; +} + uint64_t MiBToBytes(uint64_t v) { return v * 1024 * 1024; } @@ -169,7 +178,7 @@ SelfCompactionManager& SelfCompactionManager::Instance() { // static void SelfCompactionManager::SetOnStartSelfCompactionCallback( base::RepeatingCallback callback) { - base::AutoLock locker(PreFreezeBackgroundMemoryTrimmer::lock()); + base::AutoLock locker(lock()); Instance().on_self_compact_callback_ = callback; } @@ -434,11 +443,170 @@ std::optional SelfCompactionManager::CompactMemory( return total_bytes_processed; } -void PreFreezeBackgroundMemoryTrimmer::PostMetricsTasksIfModern() { - if (!SupportsModernTrim()) { +SelfCompactionManager::CompactionMetric::CompactionMetric( + const std::string& name, + base::TimeTicks triggered_at, + base::TimeTicks started_at) + : name_(name), + compaction_triggered_at_(triggered_at), + compaction_started_at_(started_at) {} +SelfCompactionManager::CompactionMetric::~CompactionMetric() = default; + +std::string SelfCompactionManager::CompactionMetric::GetMetricName( + std::string_view name) const { + return StrCat({name_, name}); +} + +std::string SelfCompactionManager::CompactionMetric::GetMetricName( + std::string_view name, + std::string_view suffix) const { + return StrCat({name_, name, ".", suffix}); +} + +void SelfCompactionManager::CompactionMetric::RecordBeforeMetrics() { + RecordSmapsRollup(&smaps_before_); +} + +void SelfCompactionManager::CompactionMetric::RecordDelayedMetrics() { + RecordSmapsRollup(&smaps_after_); + RecordSmapsRollupWithDelay(&smaps_after_1s_, base::Seconds(1)); + RecordSmapsRollupWithDelay(&smaps_after_10s_, base::Seconds(10)); + RecordSmapsRollupWithDelay(&smaps_after_60s_, base::Seconds(60)); +} + +void SelfCompactionManager::CompactionMetric::RecordTimeMetrics( + base::TimeTicks last_finished, + base::TimeTicks last_cancelled) { + UmaHistogramMediumTimes(GetMetricName("SelfCompactionTime"), + last_finished - compaction_started_at_); + UmaHistogramMediumTimes(GetMetricName("TimeSinceLastCancel"), + last_finished - last_cancelled); +} + +void SelfCompactionManager::CompactionMetric::MaybeRecordCompactionMetrics() { + // If we did not record smaps_rollup for any reason, such as returning to + // foreground, being frozen by App Freezer, or failing to read + // /proc/self/smaps_rollup, skip emitting metrics. + if (!smaps_before_.has_value() || !smaps_after_.has_value() || + !smaps_after_1s_.has_value() || !smaps_after_10s_.has_value() || + !smaps_after_60s_.has_value()) { return; } - PostMetricsTask(); + + if (!ShouldContinueCompaction(compaction_triggered_at_)) { + return; + } + + // Record absolute values of each metric. + RecordCompactionMetrics(*smaps_before_, "Before"); + RecordCompactionMetrics(*smaps_after_, "After"); + RecordCompactionMetrics(*smaps_after_1s_, "After1s"); + RecordCompactionMetrics(*smaps_after_10s_, "After10s"); + RecordCompactionMetrics(*smaps_after_60s_, "After60s"); + + // Record diff of before and after to see how much memory was compacted. + RecordCompactionDiffMetrics(*smaps_before_, *smaps_after_, "BeforeAfter"); + + // Record diff after a delay, so we can see if any memory comes back after + // compaction. + RecordCompactionDiffMetrics(*smaps_after_, *smaps_after_1s_, "After1s"); + RecordCompactionDiffMetrics(*smaps_after_, *smaps_after_10s_, "After10s"); + RecordCompactionDiffMetrics(*smaps_after_, *smaps_after_60s_, "After60s"); +} + +void SelfCompactionManager::CompactionMetric::RecordCompactionMetric( + size_t value_bytes, + std::string_view metric_name, + std::string_view suffix) { + UmaHistogramMemoryMB(GetMetricName(metric_name, suffix), + static_cast(BytesToMiB(value_bytes))); +} + +void SelfCompactionManager::CompactionMetric::RecordCompactionMetrics( + const debug::SmapsRollup& value, + std::string_view suffix) { + RecordCompactionMetric(value.rss, "Rss", suffix); + RecordCompactionMetric(value.pss, "Pss", suffix); + RecordCompactionMetric(value.pss_anon, "PssAnon", suffix); + RecordCompactionMetric(value.pss_file, "PssFile", suffix); + RecordCompactionMetric(value.swap_pss, "SwapPss", suffix); +} + +void SelfCompactionManager::CompactionMetric::RecordCompactionDiffMetric( + size_t before_value_bytes, + size_t after_value_bytes, + std::string_view name, + std::string_view suffix) { + size_t diff_non_negative = std::max(before_value_bytes, after_value_bytes) - + std::min(before_value_bytes, after_value_bytes); + const std::string full_suffix = StrCat( + {"Diff.", suffix, ".", + before_value_bytes < after_value_bytes ? "Increase" : "Decrease"}); + RecordCompactionMetric(diff_non_negative, name, full_suffix); +} + +void SelfCompactionManager::CompactionMetric::RecordCompactionDiffMetrics( + const debug::SmapsRollup& before, + const debug::SmapsRollup& after, + std::string_view suffix) { + RecordCompactionDiffMetric(before.rss, after.rss, "Rss", suffix); + RecordCompactionDiffMetric(before.pss, after.pss, "Pss", suffix); + RecordCompactionDiffMetric(before.pss_anon, after.pss_anon, "PssAnon", + suffix); + RecordCompactionDiffMetric(before.pss_file, after.pss_file, "PssFile", + suffix); + RecordCompactionDiffMetric(before.swap_pss, after.swap_pss, "SwapPss", + suffix); +} + +void SelfCompactionManager::CompactionMetric::RecordSmapsRollup( + std::optional* target) { + if (!ShouldContinueCompaction(compaction_triggered_at_)) { + return; + } + + *target = debug::ReadAndParseSmapsRollup(); + + MaybeRecordCompactionMetrics(); +} + +void SelfCompactionManager::CompactionMetric::RecordSmapsRollupWithDelay( + std::optional* target, + base::TimeDelta delay) { + base::ThreadPool::PostDelayedTask( + FROM_HERE, {base::TaskPriority::BEST_EFFORT, MayBlock()}, + base::BindOnce( + &SelfCompactionManager::CompactionMetric::RecordSmapsRollup, + // |target| is a member a of |this|, so it's lifetime is + // always ok here. + this, base::Unretained(target)), + delay); +} + +SelfCompactionManager::CompactionState::CompactionState( + scoped_refptr task_runner, + base::TimeTicks triggered_at, + uint64_t max_bytes) + : task_runner_(std::move(task_runner)), + triggered_at_(triggered_at), + max_bytes_(max_bytes) {} + +SelfCompactionManager::CompactionState::~CompactionState() = default; + +void SelfCompactionManager::CompactionState::MaybeReadProcMaps() { + DCHECK(regions_.empty()); + auto did_read_proc_maps = ReadProcMaps::kSuccess; + if (IsFeatureEnabled()) { + std::string proc_maps; + if (!debug::ReadProcMaps(&proc_maps) || + !ParseProcMaps(proc_maps, ®ions_)) { + did_read_proc_maps = ReadProcMaps::kFailed; + } else if (regions_.size() == 0) { + did_read_proc_maps = ReadProcMaps::kEmpty; + } + } + + UmaHistogramEnumeration(GetMetricName("ReadProcMaps"), did_read_proc_maps); } // static diff --git a/naiveproxy/src/base/android/shared_preferences/shared_preferences_manager.h b/naiveproxy/src/base/android/shared_preferences/shared_preferences_manager.h index eb6dc7b9d0..a3fc46a13f 100644 --- a/naiveproxy/src/base/android/shared_preferences/shared_preferences_manager.h +++ b/naiveproxy/src/base/android/shared_preferences/shared_preferences_manager.h @@ -15,7 +15,7 @@ namespace base::android { // with uniqueness key checking. class BASE_EXPORT SharedPreferencesManager { public: - explicit SharedPreferencesManager(const JavaRef& jobj, JNIEnv* env); + SharedPreferencesManager(const JavaRef& jobj, JNIEnv* env); SharedPreferencesManager(const SharedPreferencesManager&); SharedPreferencesManager& operator=(const SharedPreferencesManager&) = delete; ~SharedPreferencesManager(); diff --git a/naiveproxy/src/base/android/task_scheduler/task_runner_android.cc b/naiveproxy/src/base/android/task_scheduler/task_runner_android.cc index a38220f615..9b2656bb5f 100644 --- a/naiveproxy/src/base/android/task_scheduler/task_runner_android.cc +++ b/naiveproxy/src/base/android/task_scheduler/task_runner_android.cc @@ -100,6 +100,8 @@ std::unique_ptr TaskRunnerAndroid::Create( case ::TaskTraits::UI_USER_VISIBLE: [[fallthrough]]; case ::TaskTraits::UI_USER_BLOCKING: + [[fallthrough]]; + case ::TaskTraits::UI_STARTUP: use_thread_pool = false; break; } diff --git a/naiveproxy/src/base/android/task_scheduler/task_runner_android.h b/naiveproxy/src/base/android/task_scheduler/task_runner_android.h index e077cf3d2a..e1b3c75ffd 100644 --- a/naiveproxy/src/base/android/task_scheduler/task_runner_android.h +++ b/naiveproxy/src/base/android/task_scheduler/task_runner_android.h @@ -22,8 +22,7 @@ enum class TaskRunnerType { BASE, SEQUENCED, SINGLE_THREAD }; // a C++ TaskRunner. class BASE_EXPORT TaskRunnerAndroid { public: - explicit TaskRunnerAndroid(scoped_refptr task_runner, - TaskRunnerType type); + TaskRunnerAndroid(scoped_refptr task_runner, TaskRunnerType type); TaskRunnerAndroid(const TaskRunnerAndroid&) = delete; TaskRunnerAndroid& operator=(const TaskRunnerAndroid&) = delete; diff --git a/naiveproxy/src/base/android/task_scheduler/task_traits_android.h b/naiveproxy/src/base/android/task_scheduler/task_traits_android.h index 589de243a9..5f81f19472 100644 --- a/naiveproxy/src/base/android/task_scheduler/task_traits_android.h +++ b/naiveproxy/src/base/android/task_scheduler/task_traits_android.h @@ -40,7 +40,12 @@ enum TaskTraits { UI_USER_VISIBLE = UI_TRAITS_START + 1, UI_USER_BLOCKING = UI_TRAITS_START + 2, UI_DEFAULT = UI_USER_VISIBLE, - UI_TRAITS_END = UI_USER_BLOCKING + // Tasks that are critical for an embedder's startup performance. While other + // tasks may also run during the startup phase, this queue allows an embedder + // to apply certain constraints on other task queues until these critical + // startup tasks are finished. + UI_STARTUP = UI_TRAITS_START + 3, + UI_TRAITS_END = UI_STARTUP }; #endif // BASE_ANDROID_TASK_SCHEDULER_TASK_TRAITS_ANDROID_H_ diff --git a/naiveproxy/src/base/android/trace_event_binding.cc b/naiveproxy/src/base/android/trace_event_binding.cc index cf659b086f..5406902975 100644 --- a/naiveproxy/src/base/android/trace_event_binding.cc +++ b/naiveproxy/src/base/android/trace_event_binding.cc @@ -11,6 +11,7 @@ #include "base/android/jni_string.h" #include "base/compiler_specific.h" #include "base/metrics/histogram_macros.h" +#include "base/no_destructor.h" #include "base/trace_event/trace_event_impl.h" // no-presubmit-check #include "base/trace_event/trace_id_helper.h" #include "base/trace_event/typed_macros.h" @@ -97,7 +98,7 @@ static jboolean JNI_TraceEvent_ViewHierarchyDumpEnabled(JNIEnv* env) { static void JNI_TraceEvent_InitViewHierarchyDump( JNIEnv* env, jlong id, - const JavaParamRef& obj) { + const base::android::JavaParamRef& obj) { TRACE_EVENT( kAndroidViewHierarchyTraceCategory, kAndroidViewHierarchyEventName, perfetto::TerminatingFlow::ProcessScoped(static_cast(id)), @@ -109,9 +110,10 @@ static void JNI_TraceEvent_InitViewHierarchyDump( }); } -static jlong JNI_TraceEvent_StartActivityDump(JNIEnv* env, - const JavaParamRef& name, - jlong dump_proto_ptr) { +static jlong JNI_TraceEvent_StartActivityDump( + JNIEnv* env, + const base::android::JavaParamRef& name, + jlong dump_proto_ptr) { auto* dump = reinterpret_cast( dump_proto_ptr); auto* activity = dump->add_activity(); @@ -125,8 +127,8 @@ static void JNI_TraceEvent_AddViewDump( jint parent_id, jboolean is_shown, jboolean is_dirty, - const JavaParamRef& class_name, - const JavaParamRef& resource_name, + const base::android::JavaParamRef& class_name, + const base::android::JavaParamRef& resource_name, jlong activity_proto_ptr) { auto* activity = reinterpret_cast( activity_proto_ptr); @@ -144,8 +146,9 @@ namespace { // Boilerplate for safely converting Java data to TRACE_EVENT data. class TraceEventDataConverter { public: - TraceEventDataConverter(JNIEnv* env, jstring jarg) - : has_arg_(jarg != nullptr), + TraceEventDataConverter(JNIEnv* env, + const base::android::JavaParamRef& jarg) + : has_arg_(!jarg.is_null()), arg_(jarg ? ConvertJavaStringToUTF8(env, jarg) : "") {} TraceEventDataConverter(const TraceEventDataConverter&) = delete; @@ -164,9 +167,10 @@ class TraceEventDataConverter { } // namespace -static void JNI_TraceEvent_Instant(JNIEnv* env, - const JavaParamRef& jname, - const JavaParamRef& jarg) { +static void JNI_TraceEvent_Instant( + JNIEnv* env, + const base::android::JavaParamRef& jname, + const base::android::JavaParamRef& jarg) { TraceEventDataConverter converter(env, jarg); if (converter.arg_name()) { @@ -184,9 +188,10 @@ static void JNI_TraceEvent_Instant(JNIEnv* env, } } -static void JNI_TraceEvent_InstantAndroidIPC(JNIEnv* env, - const JavaParamRef& jname, - jlong jdur) { +static void JNI_TraceEvent_InstantAndroidIPC( + JNIEnv* env, + const base::android::JavaParamRef& jname, + jlong jdur) { TRACE_EVENT_INSTANT( internal::kJavaTraceCategory, "AndroidIPC", [&](perfetto::EventContext ctx) { @@ -225,8 +230,7 @@ static void JNI_TraceEvent_InstantAndroidToolbar(JNIEnv* env, static void JNI_TraceEvent_WebViewStartupTotalFactoryInit(JNIEnv* env, jlong start_time_ms, jlong duration_ms) { - auto t = perfetto::Track::ThreadScoped( - reinterpret_cast(trace_event::GetNextGlobalTraceId())); + auto t = perfetto::ThreadTrack::Current(); TRACE_EVENT_BEGIN("android_webview.timeline", "WebView.Startup.CreationTime.TotalFactoryInitTime", t, TimeTicks() + Milliseconds(start_time_ms)); @@ -237,8 +241,7 @@ static void JNI_TraceEvent_WebViewStartupTotalFactoryInit(JNIEnv* env, static void JNI_TraceEvent_WebViewStartupStage1(JNIEnv* env, jlong start_time_ms, jlong duration_ms) { - auto t = perfetto::Track::ThreadScoped( - reinterpret_cast(trace_event::GetNextGlobalTraceId())); + auto t = perfetto::ThreadTrack::Current(); TRACE_EVENT_BEGIN("android_webview.timeline", "WebView.Startup.CreationTime.Stage1.FactoryInit", t, TimeTicks() + Milliseconds(start_time_ms)); @@ -251,8 +254,7 @@ static void JNI_TraceEvent_WebViewStartupFirstInstance( jlong start_time_ms, jlong duration_ms, jboolean included_global_startup) { - auto t = perfetto::Track::ThreadScoped( - reinterpret_cast(trace_event::GetNextGlobalTraceId())); + auto t = perfetto::ThreadTrack::Current(); if (included_global_startup) { TRACE_EVENT_BEGIN( "android_webview.timeline", @@ -272,8 +274,7 @@ static void JNI_TraceEvent_WebViewStartupFirstInstance( static void JNI_TraceEvent_WebViewStartupNotFirstInstance(JNIEnv* env, jlong start_time_ms, jlong duration_ms) { - auto t = perfetto::Track::ThreadScoped( - reinterpret_cast(trace_event::GetNextGlobalTraceId())); + auto t = perfetto::ThreadTrack::Current(); TRACE_EVENT_BEGIN("android_webview.timeline", "WebView.Startup.CreationTime.NotFirstInstance", t, TimeTicks() + Milliseconds(start_time_ms)); @@ -288,8 +289,7 @@ static void JNI_TraceEvent_WebViewStartupStartChromiumLocked( jint start_call_site, jint finish_call_site, jint startup_mode) { - auto t = perfetto::Track::ThreadScoped( - reinterpret_cast(trace_event::GetNextGlobalTraceId())); + auto t = perfetto::ThreadTrack::Current(); TRACE_EVENT_BEGIN( "android_webview.timeline", "WebView.Startup.CreationTime.StartChromiumLocked", t, @@ -422,9 +422,10 @@ static void JNI_TraceEvent_StartupTimeToFirstVisibleContent2( TimeTicks() + Milliseconds(start_time_ms + duration_ms)); } -static void JNI_TraceEvent_Begin(JNIEnv* env, - const JavaParamRef& jname, - const JavaParamRef& jarg) { +static void JNI_TraceEvent_Begin( + JNIEnv* env, + const base::android::JavaParamRef& jname, + const base::android::JavaParamRef& jarg) { TraceEventDataConverter converter(env, jarg); if (converter.arg_name()) { TRACE_EVENT_BEGIN( @@ -441,9 +442,10 @@ static void JNI_TraceEvent_Begin(JNIEnv* env, } } -static void JNI_TraceEvent_BeginWithIntArg(JNIEnv* env, - const JavaParamRef& jname, - jint jarg) { +static void JNI_TraceEvent_BeginWithIntArg( + JNIEnv* env, + const base::android::JavaParamRef& jname, + jint jarg) { TRACE_EVENT_BEGIN( internal::kJavaTraceCategory, nullptr, "arg", jarg, [&](::perfetto::EventContext& ctx) { @@ -452,7 +454,7 @@ static void JNI_TraceEvent_BeginWithIntArg(JNIEnv* env, } static void JNI_TraceEvent_End(JNIEnv* env, - const JavaParamRef& jarg, + const base::android::JavaParamRef& jarg, jlong jflow) { TraceEventDataConverter converter(env, jarg); bool has_arg = converter.arg_name(); @@ -473,8 +475,9 @@ static void JNI_TraceEvent_End(JNIEnv* env, } } -static void JNI_TraceEvent_BeginToplevel(JNIEnv* env, - const JavaParamRef& jtarget) { +static void JNI_TraceEvent_BeginToplevel( + JNIEnv* env, + const base::android::JavaParamRef& jtarget) { TRACE_EVENT_BEGIN( internal::kToplevelTraceCategory, nullptr, [&](::perfetto::EventContext& ctx) { @@ -486,9 +489,10 @@ static void JNI_TraceEvent_EndToplevel(JNIEnv* env) { TRACE_EVENT_END(internal::kToplevelTraceCategory); } -static void JNI_TraceEvent_StartAsync(JNIEnv* env, - const JavaParamRef& jname, - jlong jid) { +static void JNI_TraceEvent_StartAsync( + JNIEnv* env, + const base::android::JavaParamRef& jname, + jlong jid) { TRACE_EVENT_BEGIN( internal::kJavaTraceCategory, nullptr, perfetto::Track(static_cast(jid)), diff --git a/naiveproxy/src/base/android/virtual_document_path.cc b/naiveproxy/src/base/android/virtual_document_path.cc new file mode 100644 index 0000000000..b4a2349b82 --- /dev/null +++ b/naiveproxy/src/base/android/virtual_document_path.cc @@ -0,0 +1,53 @@ +// Copyright 2025 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/virtual_document_path.h" + +#include + +#include "base/android/jni_android.h" +#include "base/android/jni_array.h" +#include "base/android/jni_string.h" + +namespace base::files_internal { + +VirtualDocumentPath::VirtualDocumentPath( + const base::android::JavaRef& obj) { + obj_.Reset(obj); +} + +VirtualDocumentPath::VirtualDocumentPath(const VirtualDocumentPath& path) = + default; +VirtualDocumentPath& VirtualDocumentPath::operator=( + const VirtualDocumentPath& path) = default; + +VirtualDocumentPath::~VirtualDocumentPath() = default; + +std::optional VirtualDocumentPath::Parse( + const std::string& path) { + return std::nullopt; +} + +std::optional VirtualDocumentPath::ResolveToContentUri() const { + return std::nullopt; +} + +std::string VirtualDocumentPath::ToString() const { + return {}; +} + +bool VirtualDocumentPath::Mkdir(mode_t mode) const { + return false; +} + +bool VirtualDocumentPath::WriteFile(span data) const { + return false; +} + +std::optional> VirtualDocumentPath::CreateOrOpen() + const { + return std::nullopt; +} + +} // namespace base::files_internal diff --git a/naiveproxy/src/base/android/virtual_document_path.h b/naiveproxy/src/base/android/virtual_document_path.h new file mode 100644 index 0000000000..7947dcb3af --- /dev/null +++ b/naiveproxy/src/base/android/virtual_document_path.h @@ -0,0 +1,125 @@ +// Copyright 2025 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_VIRTUAL_DOCUMENT_PATH_H_ +#define BASE_ANDROID_VIRTUAL_DOCUMENT_PATH_H_ + +#include + +#include +#include + +#include "base/android/scoped_java_ref.h" +#include "base/containers/span.h" + +namespace base::files_internal { + +// Represents and operates on a virtual path for Android's Storage Access +// Framework (SAF). +// +// `base::FilePath` can store path-like strings, including `content://` URIs. +// However, applying string manipulations (like `Append`) to a `FilePath` +// that holds a `content://` URI often results in an invalid URI, as these +// URIs are not simple hierarchical paths. +// +// To address this, the `/SAF/...` virtual path format was introduced. This +// format is specifically designed to be safely manipulated by `FilePath`'s +// string operations. The path can represent both file and directory paths. +// +// This class, `VirtualDocumentPath`, is an object representation of a +// complete and immutable virtual document path. It is created by parsing a +// `/SAF/...` string. The class itself does not support path manipulation; its +// role is to interpret the virtual document path and execute operations against +// it, such as resolving it to a content URI (`ResolveToContentUri`) or +// performing file I/O (`WriteFile`). +// +// The virtual path format it parses is: +// /SAF//tree// +// +// USAGE +// +// This class is primarily intended for internal use within the `//base/files` +// file API implementation. +// +// Code outside of `//base/files` should remain unaware of +// `VirtualDocumentPath`. Path construction should be done using +// `base::FilePath`. The resulting `FilePath` can then be passed to +// `//base/files` helper functions which, internally, may use +// `VirtualDocumentPath::Parse()` to interpret the path and perform an +// operation. +// +// EXAMPLE (for //base/files developers) +// +// To operate on a SAF path, first construct the full path using +// `base::FilePath`, then parse it into a `VirtualDocumentPath` object. +// +// Convert the `FilePath` storing a document tree URI to a `FilePath` storing +// a virtual document path: +// +// base::FilePath dir( +// "content://com.android.externalstorage.documents/tree/primary:A%2FB"); +// base::FilePath dir_vp = *dir.ResolveToVirtualDocumentPath(); +// +// Construct the full path string using FilePath: +// +// base::FilePath file_vp = dir_vp.Append("c.txt"); +// +// Parse the virtual document path string into a VirtualDocumentPath object: +// +// VirtualDocumentPath file_vpath = *VirtualDocumentPath::Parse( +// file_vp.value()); +// +// Use the object to perform an operation: +// +// file_vpath->WriteFile(some_data); +// +// To perform I/O via other Android APIs, the virtual path can be resolved to +// a `content://` URI using `ResolveToContentUri()`: +// +// base::FilePath file(*file_vpath.ResolveToContentUri()); +class VirtualDocumentPath { + public: + VirtualDocumentPath(const VirtualDocumentPath& path); + VirtualDocumentPath& operator=(const VirtualDocumentPath& path); + ~VirtualDocumentPath(); + + // Parses virtual path "/SAF/..." to `VirtualDocumentPath` or resolves a tree + // URI (a content URI that represents a document tree) into + // `VirtualDocumentPath`. + // See + // https://developer.android.com/reference/android/provider/DocumentsContract + // for more about document tree URIs. + static std::optional Parse(const std::string& path); + // Resolves it to a content URI. If the file does not exist, it will return + // nullopt. If it returns a value, it will not be an empty string. + std::optional ResolveToContentUri() const; + // Returns string representation of the instance. See the class level comment + // for details. + std::string ToString() const; + + // Makes directory represented by the virtual path. + // It returns whether the directory has been successfully created. If the file + // already exists, it does nothing and returns false. + bool Mkdir(mode_t mode) const; + + // Writes data to the file represented by the virtual path. If the file + // already exists its content is truncated first. It returns true if the data + // has been successfully written, and false otherwise. + bool WriteFile(span data) const; + + // Creates an empty file if it does not exist and its parent directory exists. + // If the file exists or created, it returns a pair of two values where the + // first value is the content URI, and the second is a bool which is true if + // the file has been created and false if the file already existed. + std::optional> CreateOrOpen() const; + + private: + explicit VirtualDocumentPath(const base::android::JavaRef& obj); + + base::android::ScopedJavaGlobalRef obj_; +}; + +} // namespace base::files_internal + +#endif // BASE_ANDROID_VIRTUAL_DOCUMENT_PATH_H_ diff --git a/naiveproxy/src/base/android/yield_to_looper_checker.cc b/naiveproxy/src/base/android/yield_to_looper_checker.cc new file mode 100644 index 0000000000..fba1712b19 --- /dev/null +++ b/naiveproxy/src/base/android/yield_to_looper_checker.cc @@ -0,0 +1,25 @@ +// Copyright 2025 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/yield_to_looper_checker.h" + +namespace base::android { + +void YieldToLooperChecker::SetStartupRunning(bool is_startup_running) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + is_startup_running_ = is_startup_running; +} + +bool YieldToLooperChecker::ShouldYield() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + return is_startup_running_; +} + +// static +YieldToLooperChecker& YieldToLooperChecker::GetInstance() { + static NoDestructor checker; + return *checker.get(); +} + +} // namespace base::android diff --git a/naiveproxy/src/base/android/yield_to_looper_checker.h b/naiveproxy/src/base/android/yield_to_looper_checker.h new file mode 100644 index 0000000000..914acb88a5 --- /dev/null +++ b/naiveproxy/src/base/android/yield_to_looper_checker.h @@ -0,0 +1,39 @@ +// Copyright 2025 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_YIELD_TO_LOOPER_CHECKER_H_ +#define BASE_ANDROID_YIELD_TO_LOOPER_CHECKER_H_ + +#include "base/base_export.h" +#include "base/no_destructor.h" +#include "base/threading/thread_checker.h" + +namespace base::android { + +// A class to track specific scenarios in which the UI message_pump should yield +// to the looper. Currently yields if an embedder's startup is running. +// Must be constructed on UI thread. All public methods must be called on the UI +// thread. +class BASE_EXPORT YieldToLooperChecker { + public: + static YieldToLooperChecker& GetInstance(); + + // Update the checker on the startup status. + void SetStartupRunning(bool is_startup_running); + // Returns true if startup is running. + bool ShouldYield(); + + private: + YieldToLooperChecker() = default; + ~YieldToLooperChecker() = default; + + bool is_startup_running_ = false; + THREAD_CHECKER(thread_checker_); + + friend class base::NoDestructor; +}; + +} // namespace base::android + +#endif // BASE_ANDROID_YIELD_TO_LOOPER_CHECKER_H_ diff --git a/naiveproxy/src/base/atomicops.h b/naiveproxy/src/base/atomicops.h index 1dc900be37..e7a2bcd268 100644 --- a/naiveproxy/src/base/atomicops.h +++ b/naiveproxy/src/base/atomicops.h @@ -63,9 +63,7 @@ typedef int32_t Atomic32; #ifdef ARCH_CPU_64_BITS // We need to be able to go between Atomic64 and AtomicWord implicitly. This // means Atomic64 and AtomicWord should be the same type on 64-bit. -#if defined(__ILP32__) || BUILDFLAG(IS_NACL) -// NaCl's intptr_t is not actually 64-bits on 64-bit! -// http://code.google.com/p/nativeclient/issues/detail?id=1162 +#if defined(__ILP32__) typedef int64_t Atomic64; #else typedef intptr_t Atomic64; diff --git a/naiveproxy/src/base/barrier_callback.h b/naiveproxy/src/base/barrier_callback.h index c8f51d116c..0d50154bdd 100644 --- a/naiveproxy/src/base/barrier_callback.h +++ b/naiveproxy/src/base/barrier_callback.h @@ -105,10 +105,10 @@ RepeatingCallback BarrierCallback( CallbackType done_callback) { if (num_callbacks == 0) { std::move(done_callback).Run({}); - return BindRepeating(&internal::ShouldNeverRun); + return base::BindRepeating(&internal::ShouldNeverRun); } - return BindRepeating( + return base::BindRepeating( &internal::BarrierCallbackInfo::Run, std::make_unique>( num_callbacks, std::move(done_callback))); diff --git a/naiveproxy/src/base/base_switches.cc b/naiveproxy/src/base/base_switches.cc index 29a40cc850..4cfa537261 100644 --- a/naiveproxy/src/base/base_switches.cc +++ b/naiveproxy/src/base/base_switches.cc @@ -162,6 +162,10 @@ const char kDefaultCountryCodeAtInstall[] = "default-country-code"; // Adds additional thread idle time information into the trace event output. const char kEnableIdleTracing[] = "enable-idle-tracing"; +// Forces the DeviceInfo.isDesktop() check to return true. Can be used to enable +// desktop-only features on other form factors. +const char kForceDesktopAndroid[] = "force-desktop-android"; + // When we retrieve the package name within the SDK Runtime, we need to use // a bit of a hack to do this by taking advantage of the fact that the pid // is the same pid as the application's pid + 10000. diff --git a/naiveproxy/src/base/base_switches.h b/naiveproxy/src/base/base_switches.h index 4e94725fcc..ec3e19ef39 100644 --- a/naiveproxy/src/base/base_switches.h +++ b/naiveproxy/src/base/base_switches.h @@ -53,6 +53,7 @@ extern const char kEnableCrashReporterForTesting[]; extern const char kAndroidSkipChildServiceInitForTesting[]; extern const char kDefaultCountryCodeAtInstall[]; extern const char kEnableIdleTracing[]; +extern const char kForceDesktopAndroid[]; extern const char kHostPackageName[]; extern const char kHostPackageLabel[]; extern const char kHostVersionCode[]; diff --git a/naiveproxy/src/base/byte_count.h b/naiveproxy/src/base/byte_count.h new file mode 100644 index 0000000000..8f7f43d7e8 --- /dev/null +++ b/naiveproxy/src/base/byte_count.h @@ -0,0 +1,176 @@ +// Copyright 2025 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_BYTE_COUNT_H_ +#define BASE_BYTE_COUNT_H_ + +#include +#include +#include + +#include "base/numerics/checked_math.h" +#include "base/numerics/safe_conversions.h" + +namespace base { + +// Represents an integral number of bytes. Supports arithmetic operations and +// conversions to/from KiB, MiB and GiB. Any operation that overflows will +// result in a crash and thus this should only be used for trusted inputs. +// +// Sample usage: +// +// // Share unit conversion code. +// constexpr ByteCount kBufferSize = MiB(1); +// std::vector buffer(kBufferSize.InBytesUnsigned()); +// +// // Enforce that correct units are used across APIs at compile time. +// ByteCount quota = GetQuota(); +// SetMetadataSize(base::KiB(10)); +// SetDatabaseSize(quota - base::KiB(10)); +// +// KiB(), MiB() and GiB() can take float parameters. This will return the +// nearest integral number of bytes, rounding towards zero. +class ByteCount { + public: + constexpr ByteCount() = default; + + constexpr explicit ByteCount(int64_t bytes) : bytes_(bytes) {} + + ~ByteCount() = default; + + ByteCount(const ByteCount&) = default; + ByteCount& operator=(const ByteCount&) = default; + + static constexpr ByteCount FromUnsigned(uint64_t bytes) { + return ByteCount(checked_cast(bytes)); + } + + static constexpr ByteCount FromChecked( + const CheckedNumeric& checked_bytes) { + return ByteCount(checked_bytes.ValueOrDie()); + } + + constexpr bool is_zero() const { return bytes_ == 0; } + + // Conversion to integral values. + constexpr int64_t InBytes() const { return bytes_; } + constexpr int64_t InKiB() const { return bytes_ / 1024; } + constexpr int64_t InMiB() const { return bytes_ / 1024 / 1024; } + constexpr int64_t InGiB() const { return bytes_ / 1024 / 1024 / 1024; } + + // Conversion to floating point values. + constexpr double InBytesF() const { return bytes_; } + constexpr double InKiBF() const { return bytes_ / 1024.0; } + constexpr double InMiBF() const { return bytes_ / 1024.0 / 1024.0; } + constexpr double InGiBF() const { return bytes_ / 1024.0 / 1024.0 / 1024.0; } + + // Conversion to an unsigned amount of bytes. Only use when it is guaranteed + // that the value is positive. Fails if the value is negative. + constexpr uint64_t InBytesUnsigned() const { + return checked_cast(bytes_); + } + + // Math operations. + + constexpr ByteCount& operator+=(const ByteCount& other) { + *this = + ByteCount::FromChecked(CheckedNumeric(bytes_) + other.bytes_); + return *this; + } + + friend constexpr ByteCount operator+(ByteCount left, const ByteCount& right) { + left += right; + return left; + } + + constexpr ByteCount& operator-=(const ByteCount& other) { + *this = + ByteCount::FromChecked(CheckedNumeric(bytes_) - other.bytes_); + return *this; + } + + friend constexpr ByteCount operator-(ByteCount left, const ByteCount& right) { + left -= right; + return left; + } + + template + constexpr ByteCount& operator*=(const T& value) { + *this = ByteCount::FromChecked(CheckedNumeric(bytes_) * value); + return *this; + } + + template + friend constexpr ByteCount operator*(ByteCount left, const T& right) { + left *= right; + return left; + } + + template + constexpr ByteCount& operator/=(const T& value) { + *this = ByteCount::FromChecked(CheckedNumeric(bytes_) / value); + return *this; + } + + template + friend constexpr ByteCount operator/(ByteCount left, const T& right) { + left /= right; + return left; + } + + constexpr friend bool operator==(const ByteCount& a, + const ByteCount& b) = default; + constexpr friend auto operator<=>(const ByteCount& a, + const ByteCount& b) = default; + + private: + int64_t bytes_ = 0; +}; + +// Templated functions to construct from various types. Note that integers must +// be converted to CheckedNumeric BEFORE multiplying to detect +// overflows, while floats must be converted AFTER multiplying to avoid +// premature truncation. + +template + requires std::is_integral_v +constexpr ByteCount KiB(T kib) { + return ByteCount::FromChecked(CheckedNumeric(kib) * 1024); +} + +template + requires std::is_floating_point_v +constexpr ByteCount KiB(T kib) { + return ByteCount::FromChecked(CheckedNumeric(kib * 1024.0)); +} + +template + requires std::is_integral_v +constexpr ByteCount MiB(T mib) { + return ByteCount::FromChecked(CheckedNumeric(mib) * 1024 * 1024); +} + +template + requires std::is_floating_point_v +constexpr ByteCount MiB(T mib) { + return ByteCount::FromChecked(CheckedNumeric(mib * 1024.0 * 1024.0)); +} + +template + requires std::is_integral_v +constexpr ByteCount GiB(T gib) { + return ByteCount::FromChecked(CheckedNumeric(gib) * 1024 * 1024 * + 1024); +} + +template + requires std::is_floating_point_v +constexpr ByteCount GiB(T gib) { + return ByteCount::FromChecked( + CheckedNumeric(gib * 1024.0 * 1024.0 * 1024.0)); +} + +} // namespace base + +#endif // BASE_BYTE_COUNT_H_ diff --git a/naiveproxy/src/base/callback_list.h b/naiveproxy/src/base/callback_list.h index 6fe1a0276f..82cb11dc0e 100644 --- a/naiveproxy/src/base/callback_list.h +++ b/naiveproxy/src/base/callback_list.h @@ -132,10 +132,6 @@ class CallbackListBase { using CallbackType = typename CallbackListTraits::CallbackType; - // TODO(crbug.com/40139093): Update references to use this directly and by - // value, then remove. - using Subscription = CallbackListSubscription; - CallbackListBase() = default; CallbackListBase(const CallbackListBase&) = delete; CallbackListBase& operator=(const CallbackListBase&) = delete; diff --git a/naiveproxy/src/base/check.cc b/naiveproxy/src/base/check.cc index fa5f814ec8..8c274fef09 100644 --- a/naiveproxy/src/base/check.cc +++ b/naiveproxy/src/base/check.cc @@ -14,16 +14,7 @@ #include "base/thread_annotations.h" #include "base/types/cxx23_to_underlying.h" #include "build/build_config.h" - -#if BUILDFLAG(IS_NACL) -// Forward declaring this ptr for code simplicity below, we'll never dereference -// it under NaCl. -namespace base::debug { -class CrashKeyString; -} // namespace base::debug -#else #include "base/debug/crash_logging.h" -#endif // !BUILDFLAG(IS_NACL) namespace logging { @@ -57,53 +48,37 @@ LogSeverity GetCheckSeverity(base::NotFatalUntil fatal_milestone) { } base::debug::CrashKeyString* GetNotReachedCrashKey() { -#if BUILDFLAG(IS_NACL) - return nullptr; -#else static auto* const key = ::base::debug::AllocateCrashKeyString( "Logging-NOTREACHED_MESSAGE", base::debug::CrashKeySize::Size1024); return key; -#endif // BUILDFLAG(IS_NACL) } base::debug::CrashKeyString* GetDCheckCrashKey() { -#if BUILDFLAG(IS_NACL) - return nullptr; -#else static auto* const key = ::base::debug::AllocateCrashKeyString( "Logging-DCHECK_MESSAGE", base::debug::CrashKeySize::Size1024); return key; -#endif // BUILDFLAG(IS_NACL) } base::debug::CrashKeyString* GetDumpWillBeCheckCrashKey() { -#if BUILDFLAG(IS_NACL) - return nullptr; -#else static auto* const key = ::base::debug::AllocateCrashKeyString( "Logging-DUMP_WILL_BE_CHECK_MESSAGE", base::debug::CrashKeySize::Size1024); return key; -#endif // BUILDFLAG(IS_NACL) } -#if !BUILDFLAG(IS_NACL) base::debug::CrashKeyString* GetFatalMilestoneCrashKey() { static auto* const key = ::base::debug::AllocateCrashKeyString( "Logging-FATAL_MILESTONE", base::debug::CrashKeySize::Size32); return key; } -#endif // BUILDFLAG(IS_NACL) void MaybeSetFatalMilestoneCrashKey(base::NotFatalUntil fatal_milestone) { -#if !BUILDFLAG(IS_NACL) if (fatal_milestone == base::NotFatalUntil::NoSpecifiedMilestoneInternal) { return; } base::debug::SetCrashKeyString( GetFatalMilestoneCrashKey(), base::NumberToString(base::to_underlying(fatal_milestone))); -#endif // BUILDFLAG(IS_NACL) } void DumpWithoutCrashing(base::debug::CrashKeyString* message_key, @@ -111,12 +86,10 @@ void DumpWithoutCrashing(base::debug::CrashKeyString* message_key, const base::Location& location, base::NotFatalUntil fatal_milestone) { const std::string crash_string = log_message->BuildCrashString(); -#if !BUILDFLAG(IS_NACL) base::debug::ScopedCrashKeyString scoped_message_key(message_key, crash_string); MaybeSetFatalMilestoneCrashKey(fatal_milestone); -#endif // !BUILDFLAG(IS_NACL) // Copy the crash message to stack memory to make sure it can be recovered in // crash dumps. This is easier to recover in minidumps than crash keys during // local debugging. @@ -127,9 +100,7 @@ void DumpWithoutCrashing(base::debug::CrashKeyString* message_key, // repeat reports for the same bug. base::debug::DumpWithoutCrashing(location, base::Days(30)); -#if !BUILDFLAG(IS_NACL) base::debug::ClearCrashKeyString(GetFatalMilestoneCrashKey()); -#endif // !BUILDFLAG(IS_NACL) } void HandleCheckErrorLogMessage(base::debug::CrashKeyString* message_key, diff --git a/naiveproxy/src/base/check_op.cc b/naiveproxy/src/base/check_op.cc index c7fbcc2ebb..2196299941 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/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "base/check_op.h" #include @@ -15,6 +10,7 @@ #include #include +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/logging.h" #include "base/strings/cstring_view.h" @@ -24,43 +20,43 @@ namespace logging { char* CheckOpValueStr(int v) { char buf[50]; snprintf(buf, sizeof(buf), "%d", v); - return strdup(buf); + return UNSAFE_TODO(strdup(buf)); } char* CheckOpValueStr(unsigned v) { char buf[50]; snprintf(buf, sizeof(buf), "%u", v); - return strdup(buf); + return UNSAFE_TODO(strdup(buf)); } char* CheckOpValueStr(long v) { char buf[50]; snprintf(buf, sizeof(buf), "%ld", v); - return strdup(buf); + return UNSAFE_TODO(strdup(buf)); } char* CheckOpValueStr(unsigned long v) { char buf[50]; snprintf(buf, sizeof(buf), "%lu", v); - return strdup(buf); + return UNSAFE_TODO(strdup(buf)); } char* CheckOpValueStr(long long v) { char buf[50]; snprintf(buf, sizeof(buf), "%lld", v); - return strdup(buf); + return UNSAFE_TODO(strdup(buf)); } char* CheckOpValueStr(unsigned long long v) { char buf[50]; snprintf(buf, sizeof(buf), "%llu", v); - return strdup(buf); + return UNSAFE_TODO(strdup(buf)); } char* CheckOpValueStr(const void* v) { char buf[50]; snprintf(buf, sizeof(buf), "%p", v); - return strdup(buf); + return UNSAFE_TODO(strdup(buf)); } char* CheckOpValueStr(std::nullptr_t v) { @@ -68,7 +64,7 @@ char* CheckOpValueStr(std::nullptr_t v) { } char* CheckOpValueStr(const std::string& v) { - return strdup(v.c_str()); + return UNSAFE_TODO(strdup(v.c_str())); } char* CheckOpValueStr(std::string_view v) { @@ -86,20 +82,20 @@ char* CheckOpValueStr(std::string_view v) { } char* CheckOpValueStr(base::cstring_view v) { - return strdup(v.c_str()); + return UNSAFE_TODO(strdup(v.c_str())); } char* CheckOpValueStr(double v) { char buf[50]; snprintf(buf, sizeof(buf), "%.6lf", v); - return strdup(buf); + return UNSAFE_TODO(strdup(buf)); } char* StreamValToStr(const void* v, void (*stream_func)(std::ostream&, const void*)) { std::stringstream ss; stream_func(ss, v); - return strdup(ss.str().c_str()); + return UNSAFE_TODO(strdup(ss.str().c_str())); } char* CreateCheckOpLogMessageString(const char* expr_str, @@ -109,7 +105,7 @@ char* CreateCheckOpLogMessageString(const char* expr_str, ss << expr_str << " (" << v1_str << " vs. " << v2_str << ")"; free(v1_str); free(v2_str); - return strdup(ss.str().c_str()); + return UNSAFE_TODO(strdup(ss.str().c_str())); } } // namespace logging diff --git a/naiveproxy/src/base/compiler_specific.h b/naiveproxy/src/base/compiler_specific.h index 923632cef8..6e6a641697 100644 --- a/naiveproxy/src/base/compiler_specific.h +++ b/naiveproxy/src/base/compiler_specific.h @@ -296,7 +296,7 @@ // // initialized `T`. // MSAN_UNPOISON(ptr, sizeof(T)); // ``` -#if defined(MEMORY_SANITIZER) && !BUILDFLAG(IS_NACL) +#if defined(MEMORY_SANITIZER) #include #define MSAN_UNPOISON(p, size) __msan_unpoison(p, size) #else @@ -319,7 +319,7 @@ // // not point to an initialized `T`. // MSAN_CHECK_MEM_IS_INITIALIZED(ptr, sizeof(T)); // ``` -#if defined(MEMORY_SANITIZER) && !BUILDFLAG(IS_NACL) +#if defined(MEMORY_SANITIZER) #define MSAN_CHECK_MEM_IS_INITIALIZED(p, size) \ __msan_check_mem_is_initialized(p, size) #else diff --git a/naiveproxy/src/base/containers/auto_spanification_helper.h b/naiveproxy/src/base/containers/auto_spanification_helper.h index 7a8d67765a..984ada7b87 100644 --- a/naiveproxy/src/base/containers/auto_spanification_helper.h +++ b/naiveproxy/src/base/containers/auto_spanification_helper.h @@ -12,6 +12,57 @@ namespace base { +// SpanificationArray{Begin,End,CBegin,CEnd} were introduced temporarily in +// order to help the auto spanification tool (//tools/clang/spanify), and not +// meant to be used widely. +template +constexpr span SpanificationArrayBegin( + Element (&array LIFETIME_BOUND)[N]) { + return span(array); +} + +template +constexpr span SpanificationArrayEnd( + Element (&array LIFETIME_BOUND)[N]) { + return span(array).last(0u); +} + +template +constexpr span SpanificationArrayCBegin( + const Element (&array LIFETIME_BOUND)[N]) { + return span(array); +} + +template +constexpr span SpanificationArrayCEnd( + const Element (&array LIFETIME_BOUND)[N]) { + return span(array).last(0u); +} + +template +constexpr span SpanificationArrayBegin( + std::array& array LIFETIME_BOUND) { + return span(array); +} + +template +constexpr span SpanificationArrayEnd( + std::array& array LIFETIME_BOUND) { + return span(array).last(0u); +} + +template +constexpr span SpanificationArrayCBegin( + const std::array& array LIFETIME_BOUND) { + return span(array); +} + +template +constexpr span SpanificationArrayCEnd( + const std::array& array LIFETIME_BOUND) { + return span(array).last(0u); +} + // SpanificationSizeofForStdArray was introduced temporarily in order to help // the auto spanification tool (//tools/clang/spanify), and not meant to be // used widely. @@ -24,19 +75,6 @@ constexpr size_t SpanificationSizeofForStdArray(const std::array&) { return sizeof(Element) * N; } -// This helper is used to rewrite code that passes the address of a single -// variable or object member (e.g. `&my_var` or `&obj.member`) to a function -// that expects a `span` representing a single element. -// -// WARNING: This function should only be used by the auto-spanification tool. -// Do not use this helper outside of the tool. -template -span SpanFromSingleElement(T& ref) { - // This is a single element and the address is always valid as long as the - // reference is valid. - return UNSAFE_TODO(span(&ref, 1u)); -} - // Modifies the input span by removing its first element (if not empty) // and returns the modified span. // Used to rewrite pre-increment (++ptr). diff --git a/naiveproxy/src/base/containers/flat_tree.h b/naiveproxy/src/base/containers/flat_tree.h index 9a98af6d3d..5422e464e2 100644 --- a/naiveproxy/src/base/containers/flat_tree.h +++ b/naiveproxy/src/base/containers/flat_tree.h @@ -18,7 +18,6 @@ #include "base/check.h" #include "base/compiler_specific.h" -#include "base/containers/span.h" #include "base/memory/raw_ptr_exclusion.h" namespace base { @@ -27,7 +26,7 @@ namespace base { // flat_tree in case the underlying container is already sorted and has no // duplicate elements. struct sorted_unique_t { - constexpr explicit sorted_unique_t() = default; + constexpr sorted_unique_t() = default; }; inline constexpr sorted_unique_t sorted_unique; @@ -250,12 +249,6 @@ class flat_tree { requires(std::input_iterator) void insert(InputIterator first, InputIterator last); - // PRECONDITIONS: `first` and `last` must be iterators into the - // same object, with `first` less than or equal to `last`. - template - UNSAFE_BUFFER_USAGE void insert(InputIteratorPtr* first, - InputIteratorPtr* last); - // Inserts the all values from the `range` into the current tree. template requires(std::ranges::input_range) @@ -758,19 +751,6 @@ auto flat_tree::insert( .first; } -// PRECONDITIONS: `first` and `last` must be iterators into the -// same object, with `first` less than or equal to `last`. -template -template -UNSAFE_BUFFER_USAGE void -flat_tree::insert( - InputIteratorPtr* input_begin, - InputIteratorPtr* input_end) { - // SAFETY: The caller must ensure the pointers are a valid pair. - auto s = UNSAFE_BUFFERS(base::span(input_begin, input_end)); - insert(s.begin(), s.end()); -} - template template requires(std::input_iterator) @@ -820,8 +800,7 @@ template requires(std::ranges::input_range) void flat_tree::insert_range( Range&& range) { - // SAFETY: A range should return a valid begin/end even if they are pointers. - UNSAFE_BUFFERS(insert(std::ranges::begin(range), std::ranges::end(range))); + insert(std::ranges::begin(range), std::ranges::end(range)); } template diff --git a/naiveproxy/src/base/containers/heap_array_nocompile.nc b/naiveproxy/src/base/containers/heap_array_nocompile.nc index 03d73ffffe..05a4be12e2 100644 --- a/naiveproxy/src/base/containers/heap_array_nocompile.nc +++ b/naiveproxy/src/base/containers/heap_array_nocompile.nc @@ -27,6 +27,7 @@ void WontCompileUninithNonTrivialClass() { void WontCompileWithSizeConstructorRequiresArgs() { auto vec = HeapArray::WithSize(2u); // expected-error {{constraints not satisfied}} + // expected-error@*:* 0-1 {{no matching constructor for initialization}} } void WontCompileUninitConstructorRequiresArgs() { diff --git a/naiveproxy/src/base/containers/lru_cache.h b/naiveproxy/src/base/containers/lru_cache.h index 85754764cf..fe6cd39bf9 100644 --- a/naiveproxy/src/base/containers/lru_cache.h +++ b/naiveproxy/src/base/containers/lru_cache.h @@ -124,7 +124,9 @@ class LRUCacheBase { // Retrieves the contents of the given key, or end() if not found. This method // has the side effect of moving the requested item to the front of the // recency list. - iterator Get(const key_type& key) { + template + requires requires(KeyIndex index, K key) { index.find(key); } + iterator Get(const K& key) { typename KeyIndex::iterator index_iter = index_.find(key); if (index_iter == index_.end()) { return end(); @@ -138,7 +140,9 @@ class LRUCacheBase { // Retrieves the item associated with a given key and returns it via // result without affecting the ordering (unlike Get()). - iterator Peek(const key_type& key) { + template + requires requires(KeyIndex index, K key) { index.find(key); } + iterator Peek(const K& key) { typename KeyIndex::const_iterator index_iter = index_.find(key); if (index_iter == index_.end()) { return end(); @@ -146,7 +150,9 @@ class LRUCacheBase { return index_iter->second; } - const_iterator Peek(const key_type& key) const { + template + requires requires(KeyIndex index, K key) { index.find(key); } + const_iterator Peek(const K& key) const { typename KeyIndex::const_iterator index_iter = index_.find(key); if (index_iter == index_.end()) { return end(); @@ -246,9 +252,7 @@ class LRUCacheBase { const LruCacheType&); ValueList ordering_; - // TODO(crbug.com/40069408): Remove annotation once crbug.com/1472363 is - // fixed. - __attribute__((annotate("blink_gc_plugin_ignore"))) KeyIndex index_; + KeyIndex index_; size_type max_size_; }; diff --git a/naiveproxy/src/base/containers/span.h b/naiveproxy/src/base/containers/span.h index 9b3e03d4bd..4cd8d825a6 100644 --- a/naiveproxy/src/base/containers/span.h +++ b/naiveproxy/src/base/containers/span.h @@ -302,7 +302,7 @@ inline constexpr bool kCanSafelyConvertToByteSpan> = // Type tag to provide to byte span conversion functions to bypass // `std::has_unique_object_representations_v<>` check. struct allow_nonunique_obj_t { - explicit allow_nonunique_obj_t() = default; + allow_nonunique_obj_t() = default; }; inline constexpr allow_nonunique_obj_t allow_nonunique_obj{}; @@ -454,8 +454,7 @@ class GSL_POINTER span { requires(internal::CompatibleIter) // PRECONDITIONS: `first` must point to the first of at least `count` // contiguous valid elements. - UNSAFE_BUFFER_USAGE constexpr explicit span(It first, - StrictNumeric count) + UNSAFE_BUFFER_USAGE constexpr span(It first, StrictNumeric count) : data_(to_address(first)) { CHECK(size_type{count} == extent); @@ -471,7 +470,7 @@ class GSL_POINTER span { !std::is_convertible_v) // PRECONDITIONS: `first` and `last` must be for the same allocation and all // elements in the range [first, last) must be valid. - UNSAFE_BUFFER_USAGE constexpr explicit span(It first, End last) + UNSAFE_BUFFER_USAGE constexpr span(It first, End last) // SAFETY: The caller must guarantee that `first` and `last` point into // the same allocation. In this case, the extent will be the number of // elements between the iterators and thus a valid size for the pointer to diff --git a/naiveproxy/src/base/containers/span_rust.h b/naiveproxy/src/base/containers/span_rust.h index 9ea606c710..b8e01ad6aa 100644 --- a/naiveproxy/src/base/containers/span_rust.h +++ b/naiveproxy/src/base/containers/span_rust.h @@ -11,10 +11,6 @@ #include "build/build_config.h" #include "third_party/rust/cxx/v1/cxx.h" -#if BUILDFLAG(IS_NACL) -#error "span_rust.h included under IS_NACL" -#endif - namespace base { // Creates a Rust slice from a span. diff --git a/naiveproxy/src/base/containers/vector_buffer.h b/naiveproxy/src/base/containers/vector_buffer.h index f4efb13cf6..65890f62ba 100644 --- a/naiveproxy/src/base/containers/vector_buffer.h +++ b/naiveproxy/src/base/containers/vector_buffer.h @@ -47,7 +47,7 @@ class VectorBuffer { public: constexpr VectorBuffer() = default; -#if defined(__clang__) && !defined(__native_client__) +#if defined(__clang__) // This constructor converts an uninitialized void* to a T* which triggers // clang Control Flow Integrity. Since this is as-designed, disable. __attribute__((no_sanitize("cfi-unrelated-cast", "vptr"))) @@ -146,7 +146,8 @@ class VectorBuffer { if constexpr (is_trivially_copyable_or_relocatable) { // 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()); + // TODO(https://crbug.com/432507886): find a way to remove the void* cast + memcpy(static_cast(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 { diff --git a/naiveproxy/src/base/critical_closure.h b/naiveproxy/src/base/critical_closure.h index cf2a53a90b..d90331a6b9 100644 --- a/naiveproxy/src/base/critical_closure.h +++ b/naiveproxy/src/base/critical_closure.h @@ -30,8 +30,7 @@ namespace internal { // |ios::ScopedCriticalAction|. class ImmediateCriticalClosure { public: - explicit ImmediateCriticalClosure(std::string_view task_name, - OnceClosure closure); + ImmediateCriticalClosure(std::string_view task_name, OnceClosure closure); ImmediateCriticalClosure(const ImmediateCriticalClosure&) = delete; ImmediateCriticalClosure& operator=(const ImmediateCriticalClosure&) = delete; ~ImmediateCriticalClosure(); @@ -46,8 +45,7 @@ class ImmediateCriticalClosure { // is started when the action runs, not when the CriticalAction is created. class PendingCriticalClosure { public: - explicit PendingCriticalClosure(std::string_view task_name, - OnceClosure closure); + PendingCriticalClosure(std::string_view task_name, OnceClosure closure); PendingCriticalClosure(const PendingCriticalClosure&) = delete; PendingCriticalClosure& operator=(const PendingCriticalClosure&) = delete; ~PendingCriticalClosure(); diff --git a/naiveproxy/src/base/debug/debugger_posix.cc b/naiveproxy/src/base/debug/debugger_posix.cc index 58d436c43e..17ff94cccd 100644 --- a/naiveproxy/src/base/debug/debugger_posix.cc +++ b/naiveproxy/src/base/debug/debugger_posix.cc @@ -278,11 +278,6 @@ void VerifyDebugger() {} #if defined(NDEBUG) && !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_ANDROID) #define DEBUG_BREAK() abort() -#elif BUILDFLAG(IS_NACL) -// The NaCl verifier doesn't let use use int3. For now, we call abort(). We -// should ask for advice from some NaCl experts about the optimum thing here. -// http://code.google.com/p/nativeclient/issues/detail?id=645 -#define DEBUG_BREAK() abort() #elif !BUILDFLAG(IS_APPLE) // Though Android has a "helpful" process called debuggerd to catch native // signals on the general assumption that they are fatal errors. If no debugger diff --git a/naiveproxy/src/base/debug/dump_without_crashing.cc b/naiveproxy/src/base/debug/dump_without_crashing.cc index 22dc925b58..1841722998 100644 --- a/naiveproxy/src/base/debug/dump_without_crashing.cc +++ b/naiveproxy/src/base/debug/dump_without_crashing.cc @@ -63,7 +63,6 @@ bool DumpWithoutCrashing(const base::Location& location, TRACE_EVENT0("base", "DumpWithoutCrashing"); if (dump_without_crashing_function_ && ShouldDumpWithoutCrashWithLocation(location, time_between_dumps)) { -#if !BUILDFLAG(IS_NACL) // Record the location file and line so that in the case of corrupt stacks // we're still getting accurate file/line information. See // crbug.com/324771555. @@ -71,7 +70,7 @@ bool DumpWithoutCrashing(const base::Location& location, location.file_name()); SCOPED_CRASH_KEY_NUMBER("DumpWithoutCrashing", "line", location.line_number()); -#endif + (*dump_without_crashing_function_)(); base::UmaHistogramEnumeration("Stability.DumpWithoutCrashingStatus", DumpWithoutCrashingStatus::kUploaded); diff --git a/naiveproxy/src/base/debug/leak_annotations.h b/naiveproxy/src/base/debug/leak_annotations.h index 3ac742dd43..13fa31bf97 100644 --- a/naiveproxy/src/base/debug/leak_annotations.h +++ b/naiveproxy/src/base/debug/leak_annotations.h @@ -18,7 +18,7 @@ // ANNOTATE_LEAKING_OBJECT_PTR(X): the heap object referenced by pointer X will // be annotated as a leak. -#if defined(LEAK_SANITIZER) && !BUILDFLAG(IS_NACL) +#if defined(LEAK_SANITIZER) #include diff --git a/naiveproxy/src/base/debug/proc_maps_linux.h b/naiveproxy/src/base/debug/proc_maps_linux.h index 700db87a5a..41791accbf 100644 --- a/naiveproxy/src/base/debug/proc_maps_linux.h +++ b/naiveproxy/src/base/debug/proc_maps_linux.h @@ -101,6 +101,7 @@ BASE_EXPORT bool ReadProcMaps(std::string* proc_maps); BASE_EXPORT bool ParseProcMaps(const std::string& input, std::vector* regions); +// All values are in bytes. struct SmapsRollup { size_t rss = 0; size_t pss = 0; diff --git a/naiveproxy/src/base/debug/stack_trace.h b/naiveproxy/src/base/debug/stack_trace.h index 5630ade025..a9129db48a 100644 --- a/naiveproxy/src/base/debug/stack_trace.h +++ b/naiveproxy/src/base/debug/stack_trace.h @@ -19,9 +19,7 @@ #include "build/build_config.h" #if BUILDFLAG(IS_POSIX) -#if !BUILDFLAG(IS_NACL) #include -#endif #include #endif @@ -43,7 +41,7 @@ namespace base::debug { // done in official builds because it has security implications). BASE_EXPORT bool EnableInProcessStackDumping(); -#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL) +#if BUILDFLAG(IS_POSIX) // Sets a first-chance callback for the stack dump signal handler. This callback // is called at the beginning of the signal handler to handle special kinds of // signals, like out-of-bounds memory accesses in WebAssembly (WebAssembly Trap diff --git a/naiveproxy/src/base/debug/stack_trace_posix.cc b/naiveproxy/src/base/debug/stack_trace_posix.cc index eedb30510a..b2b3c074c7 100644 --- a/naiveproxy/src/base/debug/stack_trace_posix.cc +++ b/naiveproxy/src/base/debug/stack_trace_posix.cc @@ -104,9 +104,7 @@ namespace { volatile sig_atomic_t in_signal_handler = 0; -#if !BUILDFLAG(IS_NACL) bool (*try_handle_signal)(int, siginfo_t*, void*) = nullptr; -#endif #if defined(DEMANGLE_SYMBOLS) // The prefix used for mangled symbols, per the Itanium C++ ABI: @@ -355,7 +353,6 @@ void StackDumpSignalHandler(int signal, siginfo_t* info, void* void_context) { // NOTE: This code MUST be async-signal safe. // NO malloc or stdio is allowed here. -#if !BUILDFLAG(IS_NACL) // Give a registered callback a chance to recover from this signal // // V8 uses guard regions to guarantee memory safety in WebAssembly. This means @@ -376,7 +373,6 @@ void StackDumpSignalHandler(int signal, siginfo_t* info, void* void_context) { sigaction(signal, &action, nullptr); return; } -#endif // Do not take the "in signal handler" code path on Mac in a DCHECK-enabled // build, as this prevents seeing a useful (symbolized) stack trace on a crash @@ -1021,7 +1017,6 @@ bool EnableInProcessStackDumping() { return success; } -#if !BUILDFLAG(IS_NACL) bool SetStackDumpFirstChanceCallback(bool (*handler)(int, siginfo_t*, void*)) { DCHECK(try_handle_signal == nullptr || handler == nullptr); try_handle_signal = handler; @@ -1042,7 +1037,6 @@ bool SetStackDumpFirstChanceCallback(bool (*handler)(int, siginfo_t*, void*)) { #endif return true; } -#endif size_t CollectStackTrace(span trace) { // NOTE: This code MUST be async-signal safe (it's used by in-process diff --git a/naiveproxy/src/base/files/file.cc b/naiveproxy/src/base/files/file.cc index d9e2b9f3af..09206eae9c 100644 --- a/naiveproxy/src/base/files/file.cc +++ b/naiveproxy/src/base/files/file.cc @@ -28,11 +28,9 @@ File::Info::~Info() = default; File::File() = default; -#if !BUILDFLAG(IS_NACL) File::File(const FilePath& path, uint32_t flags) : error_details_(FILE_OK) { Initialize(path, flags); } -#endif File::File(ScopedPlatformFile platform_file) : File(std::move(platform_file), false) {} @@ -85,7 +83,6 @@ File& File::operator=(File&& other) { return *this; } -#if !BUILDFLAG(IS_NACL) void File::Initialize(const FilePath& path, uint32_t flags) { if (path.ReferencesParent()) { #if BUILDFLAG(IS_WIN) @@ -98,17 +95,12 @@ void File::Initialize(const FilePath& path, uint32_t flags) { error_details_ = FILE_ERROR_ACCESS_DENIED; return; } - if (FileTracing::IsCategoryEnabled() -#if BUILDFLAG(IS_ANDROID) - || path.IsContentUri() -#endif - ) { + if (FileTracing::IsCategoryEnabled()) { path_ = path; } SCOPED_FILE_TRACE("Initialize"); DoInitialize(path, flags); } -#endif std::optional File::Read(int64_t offset, span data) { span chars = base::as_writable_chars(data); diff --git a/naiveproxy/src/base/files/file.h b/naiveproxy/src/base/files/file.h index 020a33a469..c7d25ec1b9 100644 --- a/naiveproxy/src/base/files/file.h +++ b/naiveproxy/src/base/files/file.h @@ -6,6 +6,7 @@ #define BASE_FILES_FILE_H_ #include +#include #include #include @@ -417,6 +418,8 @@ class BASE_EXPORT File { static int Fstat(int fd, stat_wrapper_t* sb); // Wrapper for lstat(). static int Lstat(const FilePath& path, stat_wrapper_t* sb); + // Wrapper for mkdir(). + static int Mkdir(const FilePath& path, mode_t mode); #endif // This function can be used to augment `flags` with the correct flags @@ -454,6 +457,9 @@ class BASE_EXPORT File { // Platform path to `file_`. Set if `this` wraps a file from an Android // content provider (i.e. a content URI) or if tracing is enabled in // `Initialize()`. + // On Android it could be a content URI, but never a virtual document path. + // path_ will be empty if content URI cannot be opened making the file + // invalid. FilePath path_; // Object tied to the lifetime of |this| that enables/disables tracing. diff --git a/naiveproxy/src/base/files/file_android.cc b/naiveproxy/src/base/files/file_android.cc new file mode 100644 index 0000000000..a2f892b4e8 --- /dev/null +++ b/naiveproxy/src/base/files/file_android.cc @@ -0,0 +1,108 @@ +// Copyright 2025 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/files/file_android.h" + +#include "base/android/content_uri_utils.h" +#include "base/android/scoped_java_ref.h" +#include "base/android/virtual_document_path.h" +#include "base/check.h" +#include "base/files/file_util.h" + +namespace { + +struct OpenContentUriResult { + int fd; + base::android::ScopedJavaGlobalRef java_parcel_file_desciptor; +}; + +base::expected OpenContentUriAndGetFd( + const base::FilePath& path, + uint32_t flags) { + CHECK(path.IsContentUri()); + + OpenContentUriResult result; + + result.java_parcel_file_desciptor = + base::internal::OpenContentUri(path, flags); + + result.fd = + base::internal::ContentUriGetFd(result.java_parcel_file_desciptor); + if (result.fd < 0) { + return base::unexpected(base::File::Error::FILE_ERROR_FAILED); + } + return result; +} + +} // namespace + +namespace base::files_internal { + +OpenAndroidFileResult::OpenAndroidFileResult( + base::FilePath content_uri, + int fd, + base::android::ScopedJavaGlobalRef java_parcel_file_descriptor, + bool created) + : content_uri(content_uri), + fd(fd), + java_parcel_file_descriptor(java_parcel_file_descriptor), + created(created) {} + +OpenAndroidFileResult::OpenAndroidFileResult(OpenAndroidFileResult&&) = default; +OpenAndroidFileResult& OpenAndroidFileResult::operator=( + OpenAndroidFileResult&&) = default; + +OpenAndroidFileResult::~OpenAndroidFileResult() = default; + +base::expected OpenAndroidFile( + const base::FilePath& path, + uint32_t flags) { + CHECK(path.IsContentUri() || path.IsVirtualDocumentPath()); + + auto cu = ResolveToContentUri(path); + if (cu) { + if ((flags & File::Flags::FLAG_CREATE)) { + return base::unexpected(File::Error::FILE_ERROR_EXISTS); + } + + bool created = flags & File::Flags::FLAG_CREATE_ALWAYS; + if (auto r = OpenContentUriAndGetFd(*cu, flags); r.has_value()) { + return OpenAndroidFileResult(*cu, r->fd, r->java_parcel_file_desciptor, + created); + } else { + return base::unexpected(r.error()); + } + } + + // `path` was not resolved to a content URI, meaning it is a virtual document + // path that does not exist. + CHECK(path.IsVirtualDocumentPath()); + + // If the flags don't instruct file creation, return an error. + if (!(flags & (File::Flags::FLAG_CREATE | File::Flags::FLAG_CREATE_ALWAYS | + File::Flags::FLAG_OPEN_ALWAYS))) { + return base::unexpected(File::Error::FILE_ERROR_NOT_FOUND); + } + + std::optional vp = + VirtualDocumentPath::Parse(path.value()); + CHECK(vp); + + std::optional> create_result = + vp->CreateOrOpen(); + if (!create_result) { + return base::unexpected(File::Error::FILE_ERROR_NOT_A_DIRECTORY); + } + base::FilePath content_uri(create_result->first); + bool created = create_result->second; + + if (auto r = OpenContentUriAndGetFd(content_uri, flags); r.has_value()) { + return OpenAndroidFileResult(content_uri, r->fd, + r->java_parcel_file_desciptor, created); + } else { + return base::unexpected(r.error()); + } +} + +} // namespace base::files_internal diff --git a/naiveproxy/src/base/files/file_android.h b/naiveproxy/src/base/files/file_android.h new file mode 100644 index 0000000000..b8496d306b --- /dev/null +++ b/naiveproxy/src/base/files/file_android.h @@ -0,0 +1,49 @@ +// Copyright 2025 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_FILES_FILE_ANDROID_H_ +#define BASE_FILES_FILE_ANDROID_H_ + +#include "base/android/scoped_java_ref.h" +#include "base/files/file.h" +#include "base/files/file_path.h" +#include "base/types/expected.h" + +namespace base::files_internal { + +struct OpenAndroidFileResult { + OpenAndroidFileResult( + base::FilePath content_uri, + int fd, + base::android::ScopedJavaGlobalRef java_parcel_file_descriptor, + bool created); + + OpenAndroidFileResult(const OpenAndroidFileResult&) = delete; + OpenAndroidFileResult& operator=(const OpenAndroidFileResult&) = delete; + OpenAndroidFileResult(OpenAndroidFileResult&&); + OpenAndroidFileResult& operator=(OpenAndroidFileResult&&); + + ~OpenAndroidFileResult(); + + // The content URI of the file that was opened. + base::FilePath content_uri; + // The file descriptor. The caller gains ownership of it through the + // `java_parcel_file_descriptor` below. When it is closed (in + // `File::Close()`), the file descriptor is essentially closed. + int fd; + // The corresponding Java ParcelFileDescriptor object. + base::android::ScopedJavaGlobalRef java_parcel_file_descriptor; + // Set to true if the file was created or truncated. + bool created; +}; + +// Open an android file (i.e. content URI or a virtual document path) with given +// File::Flag. +base::expected OpenAndroidFile( + const base::FilePath& path, + uint32_t flags); + +} // namespace base::files_internal + +#endif // BASE_FILES_FILE_ANDROID_H_ diff --git a/naiveproxy/src/base/files/file_enumerator_posix.cc b/naiveproxy/src/base/files/file_enumerator_posix.cc index 76a84bf524..ad148d16b0 100644 --- a/naiveproxy/src/base/files/file_enumerator_posix.cc +++ b/naiveproxy/src/base/files/file_enumerator_posix.cc @@ -41,25 +41,21 @@ bool GetStat(const FilePath& path, bool show_links, stat_wrapper_t* st) { return true; } +bool ShouldShowSymLinks(int file_type) { #if BUILDFLAG(IS_FUCHSIA) -bool ShouldShowSymLinks(int file_type) { return false; -} #else -bool ShouldShowSymLinks(int file_type) { return file_type & FileEnumerator::SHOW_SYM_LINKS; -} #endif // BUILDFLAG(IS_FUCHSIA) +} +bool ShouldTrackVisitedDirectories(int file_type) { #if BUILDFLAG(IS_FUCHSIA) -bool ShouldTrackVisitedDirectories(int file_type) { return false; -} #else -bool ShouldTrackVisitedDirectories(int file_type) { return !(file_type & FileEnumerator::SHOW_SYM_LINKS); -} #endif // BUILDFLAG(IS_FUCHSIA) +} } // namespace @@ -70,8 +66,8 @@ FileEnumerator::FileInfo::FileInfo() { } #if BUILDFLAG(IS_ANDROID) -FileEnumerator::FileInfo::FileInfo(base::FilePath content_uri, - base::FilePath filename, +FileEnumerator::FileInfo::FileInfo(FilePath content_uri, + FilePath filename, bool is_directory, off_t size, Time time) @@ -96,7 +92,7 @@ int64_t FileEnumerator::FileInfo::GetSize() const { } base::Time FileEnumerator::FileInfo::GetLastModifiedTime() const { - return base::Time::FromTimeT(stat_.st_mtime); + return Time::FromTimeT(stat_.st_mtime); } // FileEnumerator -------------------------------------------------------------- @@ -168,7 +164,7 @@ FileEnumerator::FileEnumerator(const FilePath& root_path, } if (recursive && ShouldTrackVisitedDirectories(file_type_)) { - if (stat_wrapper_t st; GetStat(root_path, false, &st)) { + if (stat_wrapper_t st; GetStat(root_path, /*show_links=*/false, &st)) { MarkVisited(st); } } diff --git a/naiveproxy/src/base/files/file_path.cc b/naiveproxy/src/base/files/file_path.cc index 8a97119694..207f84e83f 100644 --- a/naiveproxy/src/base/files/file_path.cc +++ b/naiveproxy/src/base/files/file_path.cc @@ -27,6 +27,10 @@ #include "base/strings/utf_string_conversions.h" #include "base/trace_event/trace_event.h" +#if BUILDFLAG(IS_ANDROID) +#include "base/android/virtual_document_path.h" +#endif + #if BUILDFLAG(IS_APPLE) #include "base/apple/scoped_cftyperef.h" #include "base/third_party/icu/icu_utf.h" @@ -1625,6 +1629,11 @@ FilePath FilePath::NormalizePathSeparatorsTo(CharType separator) const { bool FilePath::IsContentUri() const { return StartsWith(path_, "content://", base::CompareCase::INSENSITIVE_ASCII); } -#endif + +bool FilePath::IsVirtualDocumentPath() const { + return path_ == "/SAF" || path_.starts_with("/SAF/"); +} + +#endif // BUILDFLAG(IS_ANDROID) } // namespace base diff --git a/naiveproxy/src/base/files/file_path.h b/naiveproxy/src/base/files/file_path.h index 3a675baeda..a04fec3677 100644 --- a/naiveproxy/src/base/files/file_path.h +++ b/naiveproxy/src/base/files/file_path.h @@ -518,6 +518,14 @@ class BASE_EXPORT FilePath { // to access it. // Returns true if the path is a content uri, or false otherwise. bool IsContentUri() const; + + // Checks whether this path looks like a virtual document path. It is a quick + // check by a string matching, meaning that returning true does not guarantee + // that resolving it to a content URI will succeed. A virtual document path is + // a //base abstraction to transparently represent files and directories + // managed by Android's Storage Access Framework (SAF). See + // //base/android/virtual_document_path.h for details. + bool IsVirtualDocumentPath() const; #endif // NOTE: When adding a new public method, consider adding it to diff --git a/naiveproxy/src/base/files/file_path_watcher_inotify.cc b/naiveproxy/src/base/files/file_path_watcher_inotify.cc index 85d70a085f..07ab540ca0 100644 --- a/naiveproxy/src/base/files/file_path_watcher_inotify.cc +++ b/naiveproxy/src/base/files/file_path_watcher_inotify.cc @@ -31,12 +31,12 @@ #include "base/files/file_util.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" -#include "base/lazy_instance.h" #include "base/location.h" #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" +#include "base/no_destructor.h" #include "base/posix/eintr_wrapper.h" #include "base/synchronization/lock.h" #include "base/task/sequenced_task_runner.h" @@ -56,7 +56,7 @@ namespace { constexpr char kInotifyMaxUserWatchesPath[] = "/proc/sys/fs/inotify/max_user_watches"; -// This is a soft limit. If there are more than |kExpectedFilePathWatches| +// This is a soft limit. If there are more than `kExpectedFilePathWatches` // FilePathWatchers for a user, than they might affect each other's inotify // watchers limit. constexpr size_t kExpectedFilePathWatchers = 16u; @@ -68,7 +68,6 @@ constexpr size_t kDefaultInotifyMaxUserWatches = 8192u; #endif // !BUILDFLAG(IS_FUCHSIA) class FilePathWatcherImpl; -class InotifyReader; // Used by test to override inotify watcher limit. size_t g_override_max_inotify_watches = 0u; @@ -127,11 +126,14 @@ class InotifyReader { InotifyReader(const InotifyReader&) = delete; InotifyReader& operator=(const InotifyReader&) = delete; - // Watch directory |path| for changes. |watcher| will be notified on each - // change. Returns |kInvalidWatch| on failure. + // No destructor since it's a singleton that's never destroyed. + ~InotifyReader() = delete; + + // Watch directory `path` for changes. `watcher` will be notified on each + // change. Returns `kInvalidWatch` on failure. Watch AddWatch(const FilePath& path, FilePathWatcherImpl* watcher); - // Remove |watch| if it's valid. + // Remove `watch` if it's valid. void RemoveWatch(Watch watch, FilePathWatcherImpl* watcher); // Invoked on "inotify_reader" thread to notify relevant watchers. @@ -141,12 +143,9 @@ class InotifyReader { bool HasWatches(); private: - friend struct LazyInstanceTraitsBase; + friend class base::NoDestructor; InotifyReader(); - // There is no destructor because |g_inotify_reader| is a - // base::LazyInstace::Leaky object. Having a destructor causes build - // issues with GCC 6 (http://crbug.com/636346). // Returns true on successful thread creation. bool StartThread(); @@ -177,12 +176,12 @@ class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate { ~FilePathWatcherImpl() override; // Called for each event coming from the watch on the original thread. - // |fired_watch| identifies the watch that fired, |child| indicates what has - // changed, and is relative to the currently watched path for |fired_watch|. + // `fired_watch` identifies the watch that fired, `child` indicates what has + // changed, and is relative to the currently watched path for `fired_watch`. // - // |change_info| includes information about the change. - // |created| is true if the object appears. - // |deleted| is true if the object disappears. + // `change_info` includes information about the change. + // `created` is true if the object appears. + // `deleted` is true if the object disappears. void OnFilePathChanged(InotifyReader::Watch fired_watch, const FilePath::StringType& child, FilePathWatcher::ChangeInfo change_info, @@ -197,13 +196,13 @@ class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate { InotifyReader::WatcherEntry GetWatcherEntry(); private: - // Start watching |path| for changes and notify |delegate| on each change. - // Returns true if watch for |path| has been added successfully. + // Start watching `path` for changes and notify `delegate` on each change. + // Returns true if watch for `path` has been added successfully. bool Watch(const FilePath& path, Type type, const FilePathWatcher::Callback& callback) override; - // A generalized version. It extends |Type|. + // A generalized version. It extends `Type`. bool WatchWithOptions(const FilePath& path, const WatchOptions& flags, const FilePathWatcher::Callback& callback) override; @@ -216,12 +215,12 @@ class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate { // Cancel the watch. This unregisters the instance with InotifyReader. void Cancel() override; - // Inotify watches are installed for all directory components of |target_|. + // Inotify watches are installed for all directory components of `target_`. // A WatchEntry instance holds: - // - |watch|: the watch descriptor for a component. - // - |subdir|: the subdirectory that identifies the next component. + // - `watch`: the watch descriptor for a component. + // - `subdir`: the subdirectory that identifies the next component. // - For the last component, there is no next component, so it is empty. - // - |linkname|: the target of the symlink. + // - `linkname`: the target of the symlink. // - Only if the target being watched is a symbolic link. struct WatchEntry { explicit WatchEntry(const FilePath::StringType& dirname) @@ -232,35 +231,35 @@ class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate { FilePath::StringType linkname; }; - // Reconfigure to watch for the most specific parent directory of |target_| + // Reconfigure to watch for the most specific parent directory of `target_` // that exists. Also calls UpdateRecursiveWatches() below. Returns true if // watch limit is not hit. Otherwise, returns false. [[nodiscard]] bool UpdateWatches(); - // Reconfigure to recursively watch |target_| and all its sub-directories. + // Reconfigure to recursively watch `target_` and all its sub-directories. // - This is a no-op if the watch is not recursive. - // - If |target_| does not exist, then clear all the recursive watches. - // - Assuming |target_| exists, passing kInvalidWatch as |fired_watch| forces - // addition of recursive watches for |target_|. - // - Otherwise, only the directory associated with |fired_watch| and its + // - If `target_` does not exist, then clear all the recursive watches. + // - Assuming `target_` exists, passing kInvalidWatch as `fired_watch` forces + // addition of recursive watches for `target_`. + // - Otherwise, only the directory associated with `fired_watch` and its // sub-directories will be reconfigured. // Returns true if watch limit is not hit. Otherwise, returns false. [[nodiscard]] bool UpdateRecursiveWatches(InotifyReader::Watch fired_watch, bool is_dir); - // Enumerate recursively through |path| and add / update watches. + // Enumerate recursively through `path` and add / update watches. // Returns true if watch limit is not hit. Otherwise, returns false. [[nodiscard]] bool UpdateRecursiveWatchesForPath(const FilePath& path); - // Do internal bookkeeping to update mappings between |watch| and its - // associated full path |path|. + // Do internal bookkeeping to update mappings between `watch` and its + // associated full path `path`. void TrackWatchForRecursion(InotifyReader::Watch watch, const FilePath& path); // Remove all the recursive watches. void RemoveRecursiveWatches(); - // |path| is a symlink to a non-existent target. Attempt to add a watch to - // the link target's parent directory. Update |watch_entry| on success. + // `path` is a symlink to a non-existent target. Attempt to add a watch to + // the link target's parent directory. Update `watch_entry` on success. // Returns true if watch limit is not hit. Otherwise, returns false. [[nodiscard]] bool AddWatchForBrokenSymlink(const FilePath& path, WatchEntry* watch_entry); @@ -278,7 +277,7 @@ class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate { // The vector of watches and next component names for all path components, // starting at the root directory. The last entry corresponds to the watch for - // |target_| and always stores an empty next component name in |subdir|. + // `target_` and always stores an empty next component name in `subdir`. std::vector watches_; std::unordered_map recursive_paths_by_watch_; @@ -287,7 +286,10 @@ class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate { WeakPtrFactory weak_factory_{this}; }; -LazyInstance::Leaky g_inotify_reader = LAZY_INSTANCE_INITIALIZER; +InotifyReader& GetInotifyReader() { + static NoDestructor instance; + return *instance; +} void InotifyReaderThreadDelegate::ThreadMain() { PlatformThread::SetName("inotify_reader"); @@ -325,7 +327,7 @@ void InotifyReaderThreadDelegate::ThreadMain() { inotify_event* event = reinterpret_cast(&buffer[i]); size_t event_size = sizeof(inotify_event) + event->len; DUMP_WILL_BE_CHECK_LE(i + event_size, static_cast(bytes_read)); - g_inotify_reader.Get().OnInotifyEvent(event); + GetInotifyReader().OnInotifyEvent(event); i += event_size; } } @@ -346,8 +348,7 @@ InotifyReader::InotifyReader() } bool InotifyReader::StartThread() { - // This object is LazyInstance::Leaky, so thread_delegate_ will outlive the - // thread. + // This object is never deleted, so thread_delegate_ will outlive the thread. return PlatformThread::CreateNonJoinable(0, &thread_delegate_); } @@ -473,46 +474,46 @@ void FilePathWatcherImpl::OnFilePathChanged( // Whether kWatchLimitExceeded is encountered during update. bool exceeded_limit = false; - // Find the entries in |watches_| that correspond to |fired_watch|. + // Find the entries in `watches_` that correspond to `fired_watch`. for (size_t i = 0; i < watches_.size(); ++i) { const WatchEntry& watch_entry = watches_[i]; if (fired_watch != watch_entry.watch) { continue; } - // Check whether a path component of |target_| changed. + // Check whether a path component of `target_` changed. bool change_on_target_path = child.empty() || (child == watch_entry.linkname) || (child == watch_entry.subdir); - // Check if the change references |target_| or a direct child of |target_|. + // Check if the change references `target_` or a direct child of `target_`. bool target_changed; if (watch_entry.subdir.empty()) { // The fired watch is for a WatchEntry without a subdir. Thus for a given - // |target_| = "/path/to/foo", this is for "foo". Here, check either: + // `target_` = "/path/to/foo", this is for "foo". Here, check either: // - the target has no symlink: it is the target and it changed. - // - the target has a symlink, and it matches |child|. + // - the target has a symlink, and it matches `child`. target_changed = (watch_entry.linkname.empty() || child == watch_entry.linkname); } else { // The fired watch is for a WatchEntry with a subdir. Thus for a given - // |target_| = "/path/to/foo", this is for {"/", "/path", "/path/to"}. + // `target_` = "/path/to/foo", this is for {"/", "/path", "/path/to"}. // So we can safely access the next WatchEntry since we have not reached - // the end yet. Check |watch_entry| is for "/path/to", i.e. the next + // the end yet. Check `watch_entry` is for "/path/to", i.e. the next // element is "foo". bool next_watch_may_be_for_target = watches_[i + 1].subdir.empty(); if (next_watch_may_be_for_target) { - // The current |watch_entry| is for "/path/to", so check if the |child| + // The current `watch_entry` is for "/path/to", so check if the `child` // that changed is "foo". target_changed = watch_entry.subdir == child; } else { - // The current |watch_entry| is not for "/path/to", so the next entry - // cannot be "foo". Thus |target_| has not changed. + // The current `watch_entry` is not for "/path/to", so the next entry + // cannot be "foo". Thus `target_` has not changed. target_changed = false; } } - // Update watches if a directory component of the |target_| path + // Update watches if a directory component of the `target_` path // (dis)appears. Note that we don't add the additional restriction of // checking the event mask to see if it is for a directory here as changes // to symlinks on the target path will not have IN_ISDIR set in the event @@ -664,8 +665,9 @@ void FilePathWatcherImpl::Cancel() { set_cancelled(); callback_.Reset(); + InotifyReader& reader = GetInotifyReader(); for (const auto& watch : watches_) { - g_inotify_reader.Get().RemoveWatch(watch.watch, this); + reader.RemoveWatch(watch.watch, this); } watches_.clear(); target_.clear(); @@ -684,7 +686,7 @@ bool FilePathWatcherImpl::UpdateWatches() { InotifyReader::Watch old_watch = watch_entry.watch; watch_entry.watch = InotifyReader::kInvalidWatch; watch_entry.linkname.clear(); - watch_entry.watch = g_inotify_reader.Get().AddWatch(path, this); + watch_entry.watch = GetInotifyReader().AddWatch(path, this); if (watch_entry.watch == InotifyReader::kWatchLimitExceeded) { return false; } @@ -700,7 +702,7 @@ bool FilePathWatcherImpl::UpdateWatches() { } } if (old_watch != watch_entry.watch) { - g_inotify_reader.Get().RemoveWatch(old_watch, this); + GetInotifyReader().RemoveWatch(old_watch, this); } path = path.Append(watch_entry.subdir); } @@ -722,14 +724,14 @@ bool FilePathWatcherImpl::UpdateRecursiveWatches( return true; } - // Check to see if this is a forced update or if some component of |target_| - // has changed. For these cases, redo the watches for |target_| and below. + // Check to see if this is a forced update or if some component of `target_` + // has changed. For these cases, redo the watches for `target_` and below. if (!Contains(recursive_paths_by_watch_, fired_watch) && fired_watch != watches_.back().watch) { return UpdateRecursiveWatchesForPath(target_); } - // Underneath |target_|, only directory changes trigger watch updates. + // Underneath `target_`, only directory changes trigger watch updates. if (!is_dir) { return true; } @@ -751,17 +753,17 @@ bool FilePathWatcherImpl::UpdateRecursiveWatches( // a dir with Chrome OS file manager open for the dir). In such case, // `cur_dir` under `changed_dir` could exist in this loop but not in // the FileEnumerator loop in the upcoming UpdateRecursiveWatchesForPath(), - // As a result, `g_inotify_reader` would have an entry in its `watchers_` + // As a result, `GetInotifyReader()` would have an entry in its `watchers_` // pointing to `this` but `this` is no longer aware of that. Crash in // http://crbug/990004 could happen later. // // Remove the watcher of `cur_path` regardless of whether it exists - // or not to keep `this` and `g_inotify_reader` consistent even when the + // or not to keep `this` and `GetInotifyReader()` consistent even when the // race happens. The watcher will be added back if `cur_path` exists in // the FileEnumerator loop in UpdateRecursiveWatchesForPath(). - g_inotify_reader.Get().RemoveWatch(end_it->second, this); + GetInotifyReader().RemoveWatch(end_it->second, this); - // Keep it in sync with |recursive_watches_by_path_| crbug.com/995196. + // Keep it in sync with `recursive_watches_by_path_` crbug.com/995196. recursive_paths_by_watch_.erase(end_it->second); } recursive_watches_by_path_.erase(start_it, end_it); @@ -778,13 +780,16 @@ bool FilePathWatcherImpl::UpdateRecursiveWatches( bool FilePathWatcherImpl::UpdateRecursiveWatchesForPath(const FilePath& path) { DUMP_WILL_BE_CHECK_EQ(type_, Type::kRecursive); DUMP_WILL_BE_CHECK(!path.empty()); - DUMP_WILL_BE_CHECK(DirectoryExists(path)); // Note: SHOW_SYM_LINKS exposes symlinks as symlinks, so they are ignored // rather than followed. Following symlinks can easily lead to the undesirable // situation where the entire file system is being watched. + // + // Note: Even though callers have checked `path` exists, it still may + // disappear if there is a race with another process that is changing the file + // system. FileEnumerator enumerator( - path, true /* recursive enumeration */, + path, /*recursive=*/true, FileEnumerator::DIRECTORIES | FileEnumerator::SHOW_SYM_LINKS); for (FilePath current = enumerator.Next(); !current.empty(); current = enumerator.Next()) { @@ -794,8 +799,7 @@ bool FilePathWatcherImpl::UpdateRecursiveWatchesForPath(const FilePath& path) { // needs to be an add or update operation. if (!Contains(recursive_watches_by_path_, current)) { // Try to add new watches. - InotifyReader::Watch watch = - g_inotify_reader.Get().AddWatch(current, this); + InotifyReader::Watch watch = GetInotifyReader().AddWatch(current, this); if (watch == InotifyReader::kWatchLimitExceeded) { return false; } @@ -812,13 +816,12 @@ bool FilePathWatcherImpl::UpdateRecursiveWatchesForPath(const FilePath& path) { // Update existing watches. InotifyReader::Watch old_watch = recursive_watches_by_path_[current]; DUMP_WILL_BE_CHECK_NE(InotifyReader::kInvalidWatch, old_watch); - InotifyReader::Watch watch = - g_inotify_reader.Get().AddWatch(current, this); + InotifyReader::Watch watch = GetInotifyReader().AddWatch(current, this); if (watch == InotifyReader::kWatchLimitExceeded) { return false; } if (watch != old_watch) { - g_inotify_reader.Get().RemoveWatch(old_watch, this); + GetInotifyReader().RemoveWatch(old_watch, this); recursive_paths_by_watch_.erase(old_watch); recursive_watches_by_path_.erase(current); TrackWatchForRecursion(watch, current); @@ -849,8 +852,9 @@ void FilePathWatcherImpl::RemoveRecursiveWatches() { return; } + InotifyReader& reader = GetInotifyReader(); for (const auto& it : recursive_paths_by_watch_) { - g_inotify_reader.Get().RemoveWatch(it.first, this); + reader.RemoveWatch(it.first, this); } recursive_paths_by_watch_.clear(); @@ -875,7 +879,7 @@ bool FilePathWatcherImpl::AddWatchForBrokenSymlink(const FilePath& path, // changes to a component "/" which is harmless so no special treatment of // this case is required. InotifyReader::Watch watch = - g_inotify_reader.Get().AddWatch(link->DirName(), this); + GetInotifyReader().AddWatch(link->DirName(), this); if (watch == InotifyReader::kWatchLimitExceeded) { return false; } @@ -946,7 +950,7 @@ FilePathWatcher::FilePathWatcher() // static bool FilePathWatcher::HasWatchesForTest() { - return g_inotify_reader.Get().HasWatches(); + return GetInotifyReader().HasWatches(); } #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) diff --git a/naiveproxy/src/base/files/file_posix.cc b/naiveproxy/src/base/files/file_posix.cc index cdaf8053eb..364b9fbe42 100644 --- a/naiveproxy/src/base/files/file_posix.cc +++ b/naiveproxy/src/base/files/file_posix.cc @@ -9,8 +9,6 @@ #include "base/files/file.h" -#include "base/notimplemented.h" - // The only 32-bit platform that uses this file is Android. On Android APIs // >= 21, this standard define is the right way to express that you want a // 64-bit offset in struct stat, and the stat64 struct and functions aren't @@ -31,7 +29,6 @@ static_assert(sizeof(base::stat_wrapper_t::st_size) >= 8); #include "base/check_op.h" #include "base/feature_list.h" #include "base/metrics/field_trial_params.h" -#include "base/notimplemented.h" #include "base/notreached.h" #include "base/numerics/safe_conversions.h" #include "base/posix/eintr_wrapper.h" @@ -41,9 +38,16 @@ static_assert(sizeof(base::stat_wrapper_t::st_size) >= 8); #if BUILDFLAG(IS_ANDROID) #include "base/android/content_uri_utils.h" +#include "base/android/virtual_document_path.h" +#include "base/files/file_android.h" +#include "base/files/file_util.h" #include "base/os_compat_android.h" #endif +#if BUILDFLAG(IS_AIX) +#include "base/notimplemented.h" +#endif + namespace base { // Make sure our Whence mappings match the system headers. @@ -75,17 +79,32 @@ std::atomic g_mac_file_flush_mechanism{ MacFileFlushMechanism::kFullFsync}; #endif // BUILDFLAG(IS_APPLE) -// NaCl doesn't provide the following system calls, so either simulate them or +#if BUILDFLAG(IS_ANDROID) +#define OffsetType off64_t +#else +#define OffsetType off_t +#endif + +static_assert(sizeof(int64_t) == sizeof(OffsetType)); + +bool IsReadWriteRangeValid(int64_t offset, int size) { + if (size < 0 || !CheckAdd(offset, size - 1).IsValid() || + !IsValueInRangeForNumericType(offset + size - 1)) { + return false; + } + + return true; +} + +// AIX doesn't provide the following system calls, so either simulate them or // wrap them in order to minimize the number of #ifdef's in this file. -#if !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_AIX) +#if !BUILDFLAG(IS_AIX) bool IsOpenAppend(PlatformFile file) { return (fcntl(file, F_GETFL) & O_APPEND) != 0; } int CallFtruncate(PlatformFile file, int64_t length) { #if BUILDFLAG(IS_BSD) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_FUCHSIA) - static_assert(sizeof(off_t) >= sizeof(int64_t), - "off_t is not a 64-bit integer"); return HANDLE_EINTR(ftruncate(file, length)); #else return HANDLE_EINTR(ftruncate64(file, length)); @@ -140,31 +159,31 @@ File::Error CallFcntlFlock(PlatformFile file, } #endif -#else // BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_AIX) +#else // !BUILDFLAG(IS_AIX) bool IsOpenAppend(PlatformFile file) { - // NaCl doesn't implement fcntl. Since NaCl's write conforms to the POSIX + // AIX doesn't implement fcntl. Since AIX's write conforms to the POSIX // standard and always appends if the file is opened with O_APPEND, just // return false here. return false; } int CallFtruncate(PlatformFile file, int64_t length) { - NOTIMPLEMENTED(); // NaCl doesn't implement ftruncate. + NOTIMPLEMENTED(); // AIX doesn't implement ftruncate. return 0; } int CallFutimes(PlatformFile file, const struct timeval times[2]) { - NOTIMPLEMENTED(); // NaCl doesn't implement futimes. + NOTIMPLEMENTED(); // AIX doesn't implement futimes. return 0; } File::Error CallFcntlFlock(PlatformFile file, std::optional mode) { - NOTIMPLEMENTED(); // NaCl doesn't implement flock struct. + NOTIMPLEMENTED(); // AIX doesn't implement flock struct. return File::FILE_ERROR_INVALID_OPERATION; } -#endif // BUILDFLAG(IS_NACL) +#endif // BUILDFLAG(IS_AIX) #if BUILDFLAG(IS_ANDROID) bool GetContentUriInfo(const base::FilePath& path, File::Info* info) { @@ -275,11 +294,9 @@ int64_t File::Seek(Whence whence, int64_t offset) { SCOPED_FILE_TRACE_WITH_SIZE("Seek", offset); #if BUILDFLAG(IS_ANDROID) - static_assert(sizeof(int64_t) == sizeof(off64_t), "off64_t must be 64 bits"); return lseek64(file_.get(), static_cast(offset), static_cast(whence)); #else - static_assert(sizeof(int64_t) == sizeof(off_t), "off_t must be 64 bits"); return lseek(file_.get(), static_cast(offset), static_cast(whence)); #endif @@ -288,7 +305,7 @@ int64_t File::Seek(Whence whence, int64_t offset) { int File::Read(int64_t offset, char* data, int size) { ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK); DCHECK(IsValid()); - if (size < 0 || !IsValueInRangeForNumericType(offset + size - 1)) { + if (!IsReadWriteRangeValid(offset, size)) { return -1; } @@ -297,9 +314,17 @@ int File::Read(int64_t offset, char* data, int size) { int bytes_read = 0; long rv; do { +#if BUILDFLAG(IS_ANDROID) + // In case __USE_FILE_OFFSET64 is not used, we need to call pread64() + // instead of pread(). + rv = HANDLE_EINTR(pread64(file_.get(), data + bytes_read, + static_cast(size - bytes_read), + static_cast(offset + bytes_read))); +#else rv = HANDLE_EINTR(pread(file_.get(), data + bytes_read, static_cast(size - bytes_read), static_cast(offset + bytes_read))); +#endif if (rv <= 0) { break; } @@ -367,7 +392,7 @@ int File::Write(int64_t offset, const char* data, int size) { } DCHECK(IsValid()); - if (size < 0) { + if (!IsReadWriteRangeValid(offset, size)) { return -1; } @@ -379,15 +404,13 @@ int File::Write(int64_t offset, const char* data, int size) { #if BUILDFLAG(IS_ANDROID) // In case __USE_FILE_OFFSET64 is not used, we need to call pwrite64() // instead of pwrite(). - static_assert(sizeof(int64_t) == sizeof(off64_t), - "off64_t must be 64 bits"); rv = HANDLE_EINTR(pwrite64(file_.get(), data + bytes_written, static_cast(size - bytes_written), - offset + bytes_written)); + static_cast(offset + bytes_written))); #else rv = HANDLE_EINTR(pwrite(file_.get(), data + bytes_written, static_cast(size - bytes_written), - offset + bytes_written)); + static_cast(offset + bytes_written))); #endif if (rv <= 0) { break; @@ -553,9 +576,7 @@ File::Error File::OSErrorToFileError(int saved_errno) { case EPERM: return FILE_ERROR_ACCESS_DENIED; case EBUSY: -#if !BUILDFLAG(IS_NACL) // ETXTBSY not defined by NaCl. case ETXTBSY: -#endif return FILE_ERROR_IN_USE; case EEXIST: return FILE_ERROR_EXISTS; @@ -579,8 +600,6 @@ File::Error File::OSErrorToFileError(int saved_errno) { } } -// NaCl doesn't implement system calls to open files directly. -#if !BUILDFLAG(IS_NACL) // TODO(erikkay): does it make sense to support FLAG_EXCLUSIVE_* here? void File::DoInitialize(const FilePath& path, uint32_t flags) { ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK); @@ -639,20 +658,20 @@ void File::DoInitialize(const FilePath& path, uint32_t flags) { #endif #if BUILDFLAG(IS_ANDROID) - if (path.IsContentUri()) { - java_parcel_file_descriptor_ = internal::OpenContentUri(path, flags); - int fd = internal::ContentUriGetFd(java_parcel_file_descriptor_); - if (fd < 0) { - error_details_ = FILE_ERROR_FAILED; + if (path.IsContentUri() || path.IsVirtualDocumentPath()) { + auto result = files_internal::OpenAndroidFile(path, flags); + if (!result.has_value()) { + error_details_ = result.error(); return; } // Save path for any call to GetInfo(). - path_ = path; - created_ = (flags & (FLAG_CREATE_ALWAYS | FLAG_CREATE)); + path_ = result->content_uri; + file_.reset(result->fd); + java_parcel_file_descriptor_ = result->java_parcel_file_descriptor; + created_ = result->created; async_ = (flags & FLAG_ASYNC); error_details_ = FILE_OK; - file_.reset(fd); return; } #endif @@ -686,17 +705,13 @@ void File::DoInitialize(const FilePath& path, uint32_t flags) { error_details_ = FILE_OK; file_.reset(descriptor); } -#endif // !BUILDFLAG(IS_NACL) bool File::Flush() { ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK); DCHECK(IsValid()); SCOPED_FILE_TRACE("Flush"); -#if BUILDFLAG(IS_NACL) - NOTIMPLEMENTED(); // NaCl doesn't implement fsync. - return true; -#elif BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || \ +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || \ BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_LINUX) return !HANDLE_EINTR(fdatasync(file_.get())); #elif BUILDFLAG(IS_APPLE) @@ -757,10 +772,15 @@ File::Error File::GetLastFileError() { int File::Stat(const FilePath& path, stat_wrapper_t* sb) { ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK); #if BUILDFLAG(IS_ANDROID) - if (path.IsContentUri()) { + if (path.IsContentUri() || path.IsVirtualDocumentPath()) { + std::optional p = base::ResolveToContentUri(path); + if (!p) { + errno = ENOENT; + return -1; + } // Attempt to open the file and call GetInfo(), otherwise call Java code // with the path which is required for dirs. - File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ); + File file(*p, base::File::FLAG_OPEN | base::File::FLAG_READ); Info info; if ((file.IsValid() && file.GetInfo(&info)) || GetContentUriInfo(path, &info)) { @@ -793,4 +813,19 @@ int File::Lstat(const FilePath& path, stat_wrapper_t* sb) { return lstat(path.value().c_str(), sb); } +int File::Mkdir(const FilePath& path, mode_t mode) { +#if BUILDFLAG(IS_ANDROID) + if (path.IsVirtualDocumentPath()) { + std::optional vp = + files_internal::VirtualDocumentPath::Parse(path.value()); + if (!vp) { + errno = ENOENT; + return -1; + } + return vp->Mkdir(mode) ? 0 : -1; + } +#endif + return mkdir(path.value().c_str(), mode); +} + } // namespace base diff --git a/naiveproxy/src/base/files/file_util.h b/naiveproxy/src/base/files/file_util.h index 29571c52b3..9c46ee2c82 100644 --- a/naiveproxy/src/base/files/file_util.h +++ b/naiveproxy/src/base/files/file_util.h @@ -488,12 +488,9 @@ BASE_EXPORT OnceCallback()> GetFileSizeCallback( const FilePath& path); // Sets |real_path| to |path| with symbolic links and junctions expanded. -// On Windows, the function ensures that the resulting |real_path| starts with a -// drive letter. // // The |path| parameter can reference either a file or a directory. The function -// will fail if |path| points to a nonexistent path or to a volume that isn't -// mapped to a drive letter on Windows. +// will fail if |path| points to a nonexistent path. // // In addition, on Windows this function will fail if the resulting |real_path| // would exceed 'MAX_PATH' characters in length. @@ -501,6 +498,11 @@ BASE_EXPORT bool NormalizeFilePath(const FilePath& path, FilePath* real_path); #if BUILDFLAG(IS_WIN) +// Removes the Windows extended-length path prefix from a prefixed path. +// Exported for testing. Refer to the function implementation for details. +BASE_EXPORT FilePath +RemoveWindowsExtendedPathPrefixForTesting(std::wstring_view prefixed_path); + // Given a path in NT native form ("\Device\HarddiskVolumeXX\..."), // return in |drive_letter_path| the equivalent path that starts with // a drive letter ("C:\..."). Return false if no such path exists. @@ -730,6 +732,19 @@ BASE_EXPORT int GetMaximumPathComponentLength(const base::FilePath& path); BASE_EXPORT bool GetShmemTempDir(bool executable, FilePath* path); #endif +#if BUILDFLAG(IS_ANDROID) +// Resolves this FilePath to a content URI if it represents a virtual +// document path or is already a content URI. Returns std::nullopt otherwise. +BASE_EXPORT std::optional ResolveToContentUri(const FilePath& path); + +// Resolves this FilePath to a virtual document path if it's a content URI +// representing a document tree or is already a virtual document path. Returns +// std::nullopt otherwise. +BASE_EXPORT std::optional ResolveToVirtualDocumentPath( + const FilePath& path); + +#endif + // Internal -------------------------------------------------------------------- namespace internal { diff --git a/naiveproxy/src/base/files/file_util_android.cc b/naiveproxy/src/base/files/file_util_android.cc index d2ba684201..8c5eaabe3f 100644 --- a/naiveproxy/src/base/files/file_util_android.cc +++ b/naiveproxy/src/base/files/file_util_android.cc @@ -4,6 +4,8 @@ #include "base/files/file_util.h" +#include "base/android/jni_string.h" +#include "base/android/virtual_document_path.h" #include "base/files/file_path.h" #include "base/path_service.h" @@ -13,4 +15,35 @@ bool GetShmemTempDir(bool executable, base::FilePath* path) { return PathService::Get(base::DIR_CACHE, path); } +std::optional ResolveToContentUri(const base::FilePath& path) { + if (path.IsContentUri()) { + return path; + } + if (!path.IsVirtualDocumentPath()) { + return std::nullopt; + } + + std::optional vp = + files_internal::VirtualDocumentPath::Parse(path.value()); + if (!vp) { + return std::nullopt; + } + + std::optional uri = vp->ResolveToContentUri(); + if (!uri) { + return std::nullopt; + } + + return FilePath(*uri); +} + +std::optional ResolveToVirtualDocumentPath(const FilePath& path) { + std::optional vp = + files_internal::VirtualDocumentPath::Parse(path.value()); + if (!vp) { + return std::nullopt; + } + return FilePath(vp->ToString()); +} + } // namespace base diff --git a/naiveproxy/src/base/files/file_util_posix.cc b/naiveproxy/src/base/files/file_util_posix.cc index 76681ad43f..7ea5784936 100644 --- a/naiveproxy/src/base/files/file_util_posix.cc +++ b/naiveproxy/src/base/files/file_util_posix.cc @@ -73,6 +73,7 @@ #if BUILDFLAG(IS_ANDROID) #include "base/android/content_uri_utils.h" +#include "base/android/virtual_document_path.h" #include "base/os_compat_android.h" #endif @@ -467,6 +468,11 @@ bool IsVisibleToUser(const FilePath& path) { } // namespace FilePath MakeAbsoluteFilePath(const FilePath& input) { +#if BUILDFLAG(IS_ANDROID) + if (input.IsContentUri() || input.IsVirtualDocumentPath()) { + return input; + } +#endif ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK); char full_path[PATH_MAX]; if (realpath(input.value().c_str(), full_path) == nullptr) { @@ -632,8 +638,9 @@ bool RemoveCloseOnExec(int fd) { bool PathExists(const FilePath& path) { ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK); #if BUILDFLAG(IS_ANDROID) - if (path.IsContentUri()) { - return internal::ContentUriExists(path); + if (path.IsContentUri() || path.IsVirtualDocumentPath()) { + std::optional content_uri = base::ResolveToContentUri(path); + return content_uri && internal::ContentUriExists(*content_uri); } #endif return access(path.value().c_str(), F_OK) == 0; @@ -962,7 +969,7 @@ bool CreateDirectoryAndGetError(const FilePath& full_path, File::Error* error) { } #endif // BUILDFLAG(IS_CHROMEOS) - if (mkdir(subpath.value().c_str(), mode) == 0) { + if (File::Mkdir(subpath, mode) == 0) { continue; } // Mkdir failed, but it might have failed with EEXIST, or some other error @@ -1053,6 +1060,21 @@ FILE* OpenFile(const FilePath& filename, const char* mode) { (strchr(mode, ',') != nullptr && strchr(mode, 'e') > strchr(mode, ','))); ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK); FILE* result = nullptr; +#if BUILDFLAG(IS_ANDROID) + if (filename.IsContentUri() || filename.IsVirtualDocumentPath()) { + std::optional content_uri = base::ResolveToContentUri(filename); + if (!content_uri) { + return nullptr; + } + // TODO(crbug.com/428129200): use mode. + int fd = internal::ContentUriGetFd(internal::OpenContentUri( + *content_uri, File::FLAG_OPEN | File::FLAG_READ)); + if (fd < 0) { + return nullptr; + } + return fdopen(fd, mode); + } +#endif #if BUILDFLAG(IS_APPLE) // macOS does not provide a mode character to set O_CLOEXEC; see // https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man3/fopen.3.html. @@ -1074,7 +1096,6 @@ FILE* OpenFile(const FilePath& filename, const char* mode) { } // NaCl doesn't implement system calls to open files directly. -#if !BUILDFLAG(IS_NACL) FILE* FileToFILE(File file, const char* mode) { PlatformFile unowned = file.GetPlatformFile(); FILE* stream = fdopen(file.TakePlatformFile(), mode); @@ -1097,7 +1118,6 @@ File FILEToFile(FILE* file_stream) { } return File(std::move(other_fd)); } -#endif // !BUILDFLAG(IS_NACL) std::optional ReadFile(const FilePath& filename, span buffer) { ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK); @@ -1124,6 +1144,14 @@ std::optional ReadFile(const FilePath& filename, span buffer) { bool WriteFile(const FilePath& filename, span data) { ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK); +#if BUILDFLAG(IS_ANDROID) + if (filename.IsVirtualDocumentPath()) { + std::optional vp = + files_internal::VirtualDocumentPath::Parse(filename.value()); + return vp && vp->WriteFile(data); + } +#endif + int fd = HANDLE_EINTR(creat(filename.value().c_str(), 0666)); if (fd < 0) { return false; diff --git a/naiveproxy/src/base/files/file_util_win.cc b/naiveproxy/src/base/files/file_util_win.cc index 042e1aa53b..5d57b315aa 100644 --- a/naiveproxy/src/base/files/file_util_win.cc +++ b/naiveproxy/src/base/files/file_util_win.cc @@ -413,6 +413,32 @@ bool IsUserDefaultAdmin() { return elevation_type == TokenElevationTypeDefault; } +// This function removes the Windows extended-length path prefix from a prefixed +// path. It supports both the native UNC prefix and the native local path +// prefix. If the prefix is not recognized, it logs a warning and returns an +// empty FilePath. +// +// Examples: +// \\?\UNC\server\share\path -> \\server\share\path +// \\?\C:\path\to\file -> C:\path\to\file +FilePath RemoveWindowsExtendedPathPrefix(std::wstring_view prefixed_path) { + constexpr std::wstring_view kPrefixNativeUNC = L"\\\\?\\UNC\\"; + if (prefixed_path.starts_with(kPrefixNativeUNC)) { + std::wstring normalized_path = L"\\\\"; + normalized_path.append(prefixed_path.substr(kPrefixNativeUNC.length())); + return FilePath(normalized_path); + } + + constexpr std::wstring_view kPrefixNativeLocalPath = L"\\\\?\\"; + if (prefixed_path.starts_with(kPrefixNativeLocalPath)) { + return FilePath(prefixed_path.substr(kPrefixNativeLocalPath.length())); + } + + // Other prefixes are not supported. + DLOG(WARNING) << "Unsupported prefix for path " << prefixed_path; + return FilePath(); +} + // This function verifies that no code is attempting to set an ACL on a file // that is outside of 'safe' paths. A 'safe' path is defined as one that is // within the user data dir, or the temporary directory. This is explicitly to @@ -832,32 +858,34 @@ bool NormalizeFilePath(const FilePath& path, FilePath* real_path) { return false; } - // The expansion of `path` into a full path may make it longer. Since - // '\Device\HarddiskVolume1' is 23 characters long, we can add 30 characters. - constexpr int kMaxPathLength = MAX_PATH + 30; - wchar_t native_file_path[kMaxPathLength]; + // Add space for the `\\?\` or `\\?\UNC\` prefix. + constexpr int kMaxPathLength = MAX_PATH + 16; + wchar_t prefixed_file_path_buffer[kMaxPathLength]; // On success, `used_wchars` returns the number of written characters, not // including the trailing '\0'. Thus, failure is indicated by returning 0 or // >= kMaxPathLength. DWORD used_wchars = ::GetFinalPathNameByHandle( - file.GetPlatformFile(), native_file_path, kMaxPathLength, - FILE_NAME_NORMALIZED | VOLUME_NAME_NT); + file.GetPlatformFile(), prefixed_file_path_buffer, kMaxPathLength, + FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); if (used_wchars >= kMaxPathLength || used_wchars == 0) { return false; } - // With `VOLUME_NAME_NT` flag, GetFinalPathNameByHandle() returns the path - // with the volume device path and existing code expects we return a path - // starting 'X:\' so we need to call DevicePathToDriveLetterPath. - if (!DevicePathToDriveLetterPath( - FilePath(FilePath::StringViewType(native_file_path, used_wchars)), - real_path)) { - return false; - } + std::wstring_view prefixed_file_path(prefixed_file_path_buffer, used_wchars); + *real_path = RemoveWindowsExtendedPathPrefix(prefixed_file_path); // `real_path` can be longer than MAX_PATH and we should only return paths // that are less than MAX_PATH. - return real_path->value().size() <= MAX_PATH; + if (real_path->value().size() >= MAX_PATH) { + real_path->clear(); + } + + return !real_path->empty(); +} + +FilePath RemoveWindowsExtendedPathPrefixForTesting( + std::wstring_view prefixed_path) { + return RemoveWindowsExtendedPathPrefix(prefixed_path); } bool DevicePathToDriveLetterPath(const FilePath& nt_device_path, diff --git a/naiveproxy/src/base/files/memory_mapped_file.cc b/naiveproxy/src/base/files/memory_mapped_file.cc index 5cb10665d1..d1e0d86254 100644 --- a/naiveproxy/src/base/files/memory_mapped_file.cc +++ b/naiveproxy/src/base/files/memory_mapped_file.cc @@ -21,7 +21,6 @@ MemoryMappedFile::~MemoryMappedFile() { CloseHandles(); } -#if !BUILDFLAG(IS_NACL) bool MemoryMappedFile::Initialize(const FilePath& file_name, Access access) { if (IsValid()) { return false; @@ -142,6 +141,5 @@ void MemoryMappedFile::CalculateVMAlignedBoundaries(int64_t start, *aligned_size = (size + static_cast(*offset) + static_cast(mask)) & ~mask; } -#endif // !BUILDFLAG(IS_NACL) } // namespace base diff --git a/naiveproxy/src/base/files/memory_mapped_file_posix.cc b/naiveproxy/src/base/files/memory_mapped_file_posix.cc index 3e59997ed2..48f8680c78 100644 --- a/naiveproxy/src/base/files/memory_mapped_file_posix.cc +++ b/naiveproxy/src/base/files/memory_mapped_file_posix.cc @@ -21,7 +21,6 @@ namespace base { MemoryMappedFile::MemoryMappedFile() = default; -#if !BUILDFLAG(IS_NACL) bool MemoryMappedFile::MapFileRegionToMemory( const MemoryMappedFile::Region& region, Access access) { @@ -129,7 +128,6 @@ bool MemoryMappedFile::MapFileRegionToMemory( bytes_ = UNSAFE_BUFFERS(base::span(ptr + data_offset, byte_size)); return true; } -#endif void MemoryMappedFile::CloseHandles() { ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK); diff --git a/naiveproxy/src/base/functional/bind_internal.h b/naiveproxy/src/base/functional/bind_internal.h index eb2eec8cb8..674de37e97 100644 --- a/naiveproxy/src/base/functional/bind_internal.h +++ b/naiveproxy/src/base/functional/bind_internal.h @@ -1143,9 +1143,9 @@ struct BindState final : BindStateBase { template requires CancellationTraits::is_cancellable - explicit BindState(BindStateBase::InvokeFuncStorage invoke_func, - ForwardFunctor&& functor, - ForwardBoundArgs&&... bound_args) + BindState(BindStateBase::InvokeFuncStorage invoke_func, + ForwardFunctor&& functor, + ForwardBoundArgs&&... bound_args) : BindStateBase(invoke_func, &Destroy, &QueryCancellationTraits), functor_(std::forward(functor)), bound_args_(std::forward(bound_args)...) { @@ -1154,9 +1154,9 @@ struct BindState final : BindStateBase { template requires(!CancellationTraits::is_cancellable) - explicit BindState(BindStateBase::InvokeFuncStorage invoke_func, - ForwardFunctor&& functor, - ForwardBoundArgs&&... bound_args) + BindState(BindStateBase::InvokeFuncStorage invoke_func, + ForwardFunctor&& functor, + ForwardBoundArgs&&... bound_args) : BindStateBase(invoke_func, &Destroy), functor_(std::forward(functor)), bound_args_(std::forward(bound_args)...) { diff --git a/naiveproxy/src/base/functional/callback.h b/naiveproxy/src/base/functional/callback.h index d85057e232..b5f076b193 100644 --- a/naiveproxy/src/base/functional/callback.h +++ b/naiveproxy/src/base/functional/callback.h @@ -498,11 +498,12 @@ auto ToDoNothingCallback( return std::apply( [](auto&&... args) { if constexpr (is_once) { - return BindOnce([](TransformToUnwrappedType..., - UnboundArgs...) {}, - std::move(args)...); + return base::BindOnce( + [](TransformToUnwrappedType..., + UnboundArgs...) {}, + std::move(args)...); } else { - return BindRepeating( + return base::BindRepeating( [](TransformToUnwrappedType..., UnboundArgs...) {}, std::move(args)...); diff --git a/naiveproxy/src/base/hash/md5.cc b/naiveproxy/src/base/hash/md5.cc index 7d68475a27..f799898ec0 100644 --- a/naiveproxy/src/base/hash/md5.cc +++ b/naiveproxy/src/base/hash/md5.cc @@ -15,22 +15,6 @@ #include "third_party/boringssl/src/include/openssl/md5.h" namespace base { -void MD5Init(MD5Context* context) { - MD5_Init(context); -} - -void MD5Update(MD5Context* context, std::string_view data) { - MD5Update(context, base::as_byte_span(data)); -} - -void MD5Update(MD5Context* context, base::span data) { - MD5_Update(context, data.data(), data.size()); -} - -void MD5Final(MD5Digest* digest, MD5Context* context) { - MD5_Final(digest->a.data(), context); -} - std::string MD5DigestToBase16(const MD5Digest& digest) { return ToLowerASCII(HexEncode(digest.a)); } diff --git a/naiveproxy/src/base/hash/md5.h b/naiveproxy/src/base/hash/md5.h index c9050eb9c2..5add382a7a 100644 --- a/naiveproxy/src/base/hash/md5.h +++ b/naiveproxy/src/base/hash/md5.h @@ -13,8 +13,6 @@ #include "base/base_export.h" #include "base/containers/span.h" -#include "build/build_config.h" -#include "third_party/boringssl/src/include/openssl/md5.h" // MD5 stands for Message Digest algorithm 5. // @@ -31,47 +29,13 @@ // NEW USES OF THIS API ARE FORBIDDEN FOR ANY PURPOSE. INSTEAD, YOU MUST USE // //crypto/obsolete/md5.h. -// These functions perform MD5 operations. The simplest call is MD5Sum() to -// generate the MD5 sum of the given data. -// -// You can also compute the MD5 sum of data incrementally by making multiple -// calls to MD5Update(): -// MD5Context ctx; // intermediate MD5 data: do not use -// MD5Init(&ctx); -// MD5Update(&ctx, data1, length1); -// MD5Update(&ctx, data2, length2); -// ... -// -// MD5Digest digest; // the result of the computation -// MD5Final(&digest, &ctx); -// -// You can call MD5DigestToBase16() to generate a string of the digest. - namespace base { // The output of an MD5 operation. struct MD5Digest { - std::array a; + std::array a; }; -// Used for storing intermediate data during an MD5 computation. Callers -// should not access the data. -using MD5Context = MD5_CTX; - -// Initializes the given MD5 context structure for subsequent calls to -// MD5Update(). -BASE_EXPORT void MD5Init(MD5Context* context); - -// For the given buffer of |data| as a std::string_view or span, updates the -// given MD5 context with the sum of the data. You can call this any number of -// times during the computation, except that MD5Init() must have been called -// first. -BASE_EXPORT void MD5Update(MD5Context* context, std::string_view data); -BASE_EXPORT void MD5Update(MD5Context* context, base::span data); - -// Finalizes the MD5 operation and fills the buffer with the digest. -BASE_EXPORT void MD5Final(MD5Digest* digest, MD5Context* context); - // Converts a digest into human-readable hexadecimal. BASE_EXPORT std::string MD5DigestToBase16(const MD5Digest& digest); diff --git a/naiveproxy/src/base/hash/sha1.cc b/naiveproxy/src/base/hash/sha1.cc index a6bd3c920e..d169a73303 100644 --- a/naiveproxy/src/base/hash/sha1.cc +++ b/naiveproxy/src/base/hash/sha1.cc @@ -4,14 +4,11 @@ #include "base/hash/sha1.h" -#include - -#include +#include #include #include #include "base/containers/span.h" -#include "base/hash/sha1.h" #include "third_party/boringssl/src/include/openssl/sha.h" namespace base { @@ -31,18 +28,4 @@ std::string SHA1HashString(std::string_view str) { return digest; } -// These functions allow streaming SHA-1 operations. -void SHA1Init(SHA1Context& context) { - SHA1_Init(&context); -} - -void SHA1Update(std::string_view data, SHA1Context& context) { - SHA1_Update(&context, data.data(), data.size()); -} - -void SHA1Final(SHA1Context& context, SHA1Digest& digest) { - SHA1Context ctx(context); - SHA1_Final(digest.data(), &ctx); -} - } // namespace base diff --git a/naiveproxy/src/base/hash/sha1.h b/naiveproxy/src/base/hash/sha1.h index edb521aa60..9f4c9e05ec 100644 --- a/naiveproxy/src/base/hash/sha1.h +++ b/naiveproxy/src/base/hash/sha1.h @@ -5,25 +5,16 @@ #ifndef BASE_HASH_SHA1_H_ #define BASE_HASH_SHA1_H_ -#include -#include - #include +#include #include #include #include "base/base_export.h" -#include "base/compiler_specific.h" #include "base/containers/span.h" -#include "build/build_config.h" -#include "third_party/boringssl/src/include/openssl/sha.h" namespace base { -// Used for storing intermediate data during an SHA1 computation. Callers -// should not access the data. -using SHA1Context = SHA_CTX; - enum { kSHA1Length = 20 }; // Length in bytes of a SHA-1 hash. // The output of an SHA-1 operation. @@ -36,10 +27,6 @@ BASE_EXPORT SHA1Digest SHA1Hash(span data); // hash. BASE_EXPORT std::string SHA1HashString(std::string_view str); -// These functions allow streaming SHA-1 operations. -BASE_EXPORT void SHA1Init(SHA1Context& context); -BASE_EXPORT void SHA1Update(std::string_view data, SHA1Context& context); -BASE_EXPORT void SHA1Final(SHA1Context& context, SHA1Digest& digest); } // namespace base #endif // BASE_HASH_SHA1_H_ diff --git a/naiveproxy/src/base/i18n/break_iterator.cc b/naiveproxy/src/base/i18n/break_iterator.cc index 4cce46f308..739a383150 100644 --- a/naiveproxy/src/base/i18n/break_iterator.cc +++ b/naiveproxy/src/base/i18n/break_iterator.cc @@ -9,9 +9,9 @@ #include #include -#include "base/check.h" -#include "base/lazy_instance.h" +#include "base/check_op.h" #include "base/memory/raw_ptr.h" +#include "base/no_destructor.h" #include "base/notreached.h" #include "base/synchronization/lock.h" #include "third_party/icu/source/common/unicode/ubrk.h" @@ -27,7 +27,7 @@ namespace { // also optimize to not create break iterator many time. For each kind of break // iterator (character, word, line and sentence, but NOT rule), we keep one of // them in the main_ and lease it out. If some other code request a lease -// before |main_| is returned, we create a new instance of the iterator. +// before `main_` is returned, we create a new instance of the iterator. // This will keep at most 4 break iterators (one for each kind) unreleased until // the program destruction time. template @@ -80,14 +80,25 @@ class DefaultLocaleBreakIteratorCache { Lock lock_; }; -static LazyInstance>::Leaky - char_break_cache = LAZY_INSTANCE_INITIALIZER; -static LazyInstance>::Leaky - word_break_cache = LAZY_INSTANCE_INITIALIZER; -static LazyInstance>::Leaky - sentence_break_cache = LAZY_INSTANCE_INITIALIZER; -static LazyInstance>::Leaky - line_break_cache = LAZY_INSTANCE_INITIALIZER; +DefaultLocaleBreakIteratorCache& GetCharBreakCache() { + static NoDestructor> cache; + return *cache; +} + +DefaultLocaleBreakIteratorCache& GetWordBreakCache() { + static NoDestructor> cache; + return *cache; +} + +DefaultLocaleBreakIteratorCache& GetSentenceBreakCache() { + static NoDestructor> cache; + return *cache; +} + +DefaultLocaleBreakIteratorCache& GetLineBreakCache() { + static NoDestructor> cache; + return *cache; +} } // namespace @@ -109,17 +120,17 @@ BreakIterator::~BreakIterator() { case RULE_BASED: return; case BREAK_CHARACTER: - char_break_cache.Pointer()->Return(std::move(iter_)); + GetCharBreakCache().Return(std::move(iter_)); return; case BREAK_WORD: - word_break_cache.Pointer()->Return(std::move(iter_)); + GetWordBreakCache().Return(std::move(iter_)); return; case BREAK_SENTENCE: - sentence_break_cache.Pointer()->Return(std::move(iter_)); + GetSentenceBreakCache().Return(std::move(iter_)); return; case BREAK_LINE: case BREAK_NEWLINE: - line_break_cache.Pointer()->Return(std::move(iter_)); + GetLineBreakCache().Return(std::move(iter_)); return; } } @@ -129,17 +140,17 @@ bool BreakIterator::Init() { UParseError parse_error; switch (break_type_) { case BREAK_CHARACTER: - iter_ = char_break_cache.Pointer()->Lease(status); + iter_ = GetCharBreakCache().Lease(status); break; case BREAK_WORD: - iter_ = word_break_cache.Pointer()->Lease(status); + iter_ = GetWordBreakCache().Lease(status); break; case BREAK_SENTENCE: - iter_ = sentence_break_cache.Pointer()->Lease(status); + iter_ = GetSentenceBreakCache().Lease(status); break; case BREAK_LINE: case BREAK_NEWLINE: - iter_ = line_break_cache.Pointer()->Lease(status); + iter_ = GetLineBreakCache().Lease(status); break; case RULE_BASED: iter_ = UBreakIteratorPtr( diff --git a/naiveproxy/src/base/i18n/char_iterator.cc b/naiveproxy/src/base/i18n/char_iterator.cc index 7c5798c22c..b01c9b195d 100644 --- a/naiveproxy/src/base/i18n/char_iterator.cc +++ b/naiveproxy/src/base/i18n/char_iterator.cc @@ -2,16 +2,12 @@ // 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/i18n/char_iterator.h" #include #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/third_party/icu/icu_utf.h" namespace base::i18n { @@ -21,7 +17,7 @@ namespace base::i18n { UTF8CharIterator::UTF8CharIterator(std::string_view str) : str_(str), array_pos_(0), next_pos_(0), char_pos_(0), char_(0) { if (!str_.empty()) { - CBU8_NEXT(str_.data(), next_pos_, str_.length(), char_); + UNSAFE_TODO(CBU8_NEXT(str_.data(), next_pos_, str_.length(), char_)); } } @@ -35,7 +31,7 @@ bool UTF8CharIterator::Advance() { array_pos_ = next_pos_; char_pos_++; if (next_pos_ < str_.length()) { - CBU8_NEXT(str_.data(), next_pos_, str_.length(), char_); + UNSAFE_TODO(CBU8_NEXT(str_.data(), next_pos_, str_.length(), char_)); } return true; @@ -57,7 +53,7 @@ UTF16CharIterator& UTF16CharIterator::operator=(UTF16CharIterator&& to_move) = UTF16CharIterator UTF16CharIterator::LowerBound(std::u16string_view str, size_t array_index) { DCHECK_LE(array_index, str.length()); - CBU16_SET_CP_START(str.data(), 0, array_index); + UNSAFE_TODO(CBU16_SET_CP_START(str.data(), 0, array_index)); return UTF16CharIterator(str, array_index); } @@ -65,7 +61,7 @@ UTF16CharIterator UTF16CharIterator::LowerBound(std::u16string_view str, UTF16CharIterator UTF16CharIterator::UpperBound(std::u16string_view str, size_t array_index) { DCHECK_LE(array_index, str.length()); - CBU16_SET_CP_LIMIT(str.data(), 0, array_index, str.length()); + UNSAFE_TODO(CBU16_SET_CP_LIMIT(str.data(), 0, array_index, str.length())); return UTF16CharIterator(str, array_index); } @@ -75,7 +71,7 @@ int32_t UTF16CharIterator::NextCodePoint() const { } base_icu::UChar32 c; - CBU16_GET(str_.data(), 0, next_pos_, str_.length(), c); + UNSAFE_TODO(CBU16_GET(str_.data(), 0, next_pos_, str_.length(), c)); return c; } @@ -86,7 +82,7 @@ int32_t UTF16CharIterator::PreviousCodePoint() const { uint32_t pos = array_pos_; base_icu::UChar32 c; - CBU16_PREV(str_.data(), 0, pos, c); + UNSAFE_TODO(CBU16_PREV(str_.data(), 0, pos, c)); return c; } @@ -111,7 +107,7 @@ bool UTF16CharIterator::Rewind() { next_pos_ = array_pos_; char_offset_--; - CBU16_PREV(str_.data(), 0, array_pos_, char_); + UNSAFE_TODO(CBU16_PREV(str_.data(), 0, array_pos_, char_)); return true; } @@ -130,7 +126,7 @@ UTF16CharIterator::UTF16CharIterator(std::u16string_view str, void UTF16CharIterator::ReadChar() { // This is actually a huge macro, so is worth having in a separate function. - CBU16_NEXT(str_.data(), next_pos_, str_.length(), char_); + UNSAFE_TODO(CBU16_NEXT(str_.data(), next_pos_, str_.length(), char_)); } } // namespace base::i18n diff --git a/naiveproxy/src/base/i18n/icu_util.cc b/naiveproxy/src/base/i18n/icu_util.cc index dcf3569650..a52dcbe8ec 100644 --- a/naiveproxy/src/base/i18n/icu_util.cc +++ b/naiveproxy/src/base/i18n/icu_util.cc @@ -59,7 +59,6 @@ namespace base::i18n { -#if !BUILDFLAG(IS_NACL) namespace { #if DCHECK_IS_ON() @@ -177,7 +176,8 @@ void LazyInitIcuDataFile() { return; } #endif // !BUILDFLAG(IS_APPLE) - File file(data_path, File::FLAG_OPEN | File::FLAG_READ); + File file(data_path, + File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WIN_SHARE_DELETE); if (file.IsValid()) { // TODO(brucedawson): http://crbug.com/445616. g_debug_icu_pf_last_error = 0; @@ -429,6 +429,4 @@ void AllowMultipleInitializeCallsForTesting() { #endif } -#endif // !BUILDFLAG(IS_NACL) - } // namespace base::i18n diff --git a/naiveproxy/src/base/i18n/icu_util.h b/naiveproxy/src/base/i18n/icu_util.h index acecaefdcf..4036f33f7d 100644 --- a/naiveproxy/src/base/i18n/icu_util.h +++ b/naiveproxy/src/base/i18n/icu_util.h @@ -16,7 +16,6 @@ namespace base::i18n { -#if !BUILDFLAG(IS_NACL) // Call this function to load ICU's data tables for the current process. This // function should be called before ICU is used. BASE_I18N_EXPORT bool InitializeICU(); @@ -46,7 +45,6 @@ BASE_I18N_EXPORT void SetIcuTimeZoneDataDirForTesting(const char* dir); // In a test binary, initialize functions might be called twice. BASE_I18N_EXPORT void AllowMultipleInitializeCallsForTesting(); -#endif // !BUILDFLAG(IS_NACL) } // namespace base::i18n diff --git a/naiveproxy/src/base/i18n/rtl.cc b/naiveproxy/src/base/i18n/rtl.cc index a8eacf3f39..17d654c5be 100644 --- a/naiveproxy/src/base/i18n/rtl.cc +++ b/naiveproxy/src/base/i18n/rtl.cc @@ -139,8 +139,9 @@ std::string GetConfiguredLocale() { } // Convert the ICU canonicalized locale to a string. -std::string GetCanonicalLocale(const std::string& locale) { - return GetLocaleString(icu::Locale::createCanonical(locale.c_str())); +std::string GetCanonicalLocale(std::string_view locale) { + return GetLocaleString( + icu::Locale::createCanonical(std::string(locale).c_str())); } void SetICUDefaultLocale(std::string_view locale_string) { diff --git a/naiveproxy/src/base/i18n/rtl.h b/naiveproxy/src/base/i18n/rtl.h index 0ccac052c9..71a8679e1e 100644 --- a/naiveproxy/src/base/i18n/rtl.h +++ b/naiveproxy/src/base/i18n/rtl.h @@ -39,7 +39,7 @@ enum TextDirection { BASE_I18N_EXPORT std::string GetConfiguredLocale(); // Canonicalize a string (eg. a POSIX locale string) to a Chrome locale name. -BASE_I18N_EXPORT std::string GetCanonicalLocale(const std::string& locale); +BASE_I18N_EXPORT std::string GetCanonicalLocale(std::string_view locale); // Sets the default locale of ICU. // Once the application locale of Chrome in GetApplicationLocale is determined, diff --git a/naiveproxy/src/base/i18n/streaming_utf8_validator.cc b/naiveproxy/src/base/i18n/streaming_utf8_validator.cc index 4e71be9d61..c91e6beb1b 100644 --- a/naiveproxy/src/base/i18n/streaming_utf8_validator.cc +++ b/naiveproxy/src/base/i18n/streaming_utf8_validator.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 - // This implementation doesn't use ICU. The ICU macros are oriented towards // character-at-a-time processing, whereas byte-at-a-time processing is easier // with streaming input. @@ -14,6 +9,7 @@ #include "base/i18n/streaming_utf8_validator.h" #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/i18n/utf8_validator_tables.h" namespace base { @@ -21,7 +17,7 @@ namespace { uint8_t StateTableLookup(uint8_t offset) { DCHECK_LT(offset, internal::kUtf8ValidatorTablesSize); - return internal::kUtf8ValidatorTables[offset]; + return UNSAFE_TODO(internal::kUtf8ValidatorTables[offset]); } } // namespace diff --git a/naiveproxy/src/base/i18n/string_search.h b/naiveproxy/src/base/i18n/string_search.h index 4ddc2f6a96..44260236e9 100644 --- a/naiveproxy/src/base/i18n/string_search.h +++ b/naiveproxy/src/base/i18n/string_search.h @@ -55,8 +55,7 @@ bool StringSearch(std::u16string find_this, // argument, and precomputation for searching is done only at that time. class BASE_I18N_EXPORT GSL_POINTER FixedPatternStringSearch { public: - explicit FixedPatternStringSearch(std::u16string find_this, - bool case_sensitive); + FixedPatternStringSearch(std::u16string find_this, bool case_sensitive); ~FixedPatternStringSearch(); // Returns true if |in_this| contains |find_this|. If |match_index| or diff --git a/naiveproxy/src/base/immediate_crash.h b/naiveproxy/src/base/immediate_crash.h index ee1035f319..1ba59b0856 100644 --- a/naiveproxy/src/base/immediate_crash.h +++ b/naiveproxy/src/base/immediate_crash.h @@ -58,13 +58,7 @@ extern "C" int __attribute__((weak)) __llvm_profile_write_file(void); #if defined(COMPILER_GCC) -#if BUILDFLAG(IS_NACL) - -// Crash report accuracy is not guaranteed on NaCl. -#define TRAP_SEQUENCE1_() __builtin_trap() -#define TRAP_SEQUENCE2_() asm volatile("") - -#elif defined(ARCH_CPU_X86_FAMILY) +#if defined(ARCH_CPU_X86_FAMILY) // TODO(crbug.com/40625592): In theory, it should be possible to use just // int3. However, there are a number of crashes with SIGILL as the exception diff --git a/naiveproxy/src/base/json/json_perftest_decodebench.cc b/naiveproxy/src/base/json/json_perftest_decodebench.cc index 0b44084617..ff31bdf592 100644 --- a/naiveproxy/src/base/json/json_perftest_decodebench.cc +++ b/naiveproxy/src/base/json/json_perftest_decodebench.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/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - // This program measures the time taken to decode the given JSON files (the // command line arguments). It is for manual benchmarking. // diff --git a/naiveproxy/src/base/json/json_value_converter.h b/naiveproxy/src/base/json/json_value_converter.h index 7b42f96715..1761bde470 100644 --- a/naiveproxy/src/base/json/json_value_converter.h +++ b/naiveproxy/src/base/json/json_value_converter.h @@ -119,9 +119,9 @@ class ValueConverter { template class FieldConverter : public FieldConverterBase { public: - explicit FieldConverter(const std::string& path, - FieldType StructType::*field, - ValueConverter* converter) + FieldConverter(const std::string& path, + FieldType StructType::* field, + ValueConverter* converter) : FieldConverterBase(path), field_pointer_(field), value_converter_(converter) {} diff --git a/naiveproxy/src/base/location.cc b/naiveproxy/src/base/location.cc index f4ce27180a..b0ccf6c58a 100644 --- a/naiveproxy/src/base/location.cc +++ b/naiveproxy/src/base/location.cc @@ -4,6 +4,8 @@ #include "base/location.h" +#include + #include "base/compiler_specific.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" @@ -17,30 +19,24 @@ namespace base { namespace { -// Returns the length of the given null terminated c-string. -constexpr size_t StrLen(const char* str) { - size_t str_len = 0; - for (str_len = 0; UNSAFE_TODO(str[str_len]) != '\0'; ++str_len) - ; - return str_len; -} +#if defined(__clang__) && defined(_MSC_VER) +constexpr std::string_view kThisFilePath = "base\\location.cc"; +#else +constexpr std::string_view kThisFilePath = "base/location.cc"; +#endif // Finds the length of the build folder prefix from the file path. // TODO(ssid): Strip prefixes from stored strings in the binary. This code only // skips the prefix while reading the file name strings at runtime. constexpr size_t StrippedFilePathPrefixLength() { - constexpr char path[] = __FILE__; + constexpr std::string_view kPath = __FILE__; // Only keep the file path starting from the src directory. -#if defined(__clang__) && defined(_MSC_VER) - constexpr char stripped[] = "base\\location.cc"; -#else - constexpr char stripped[] = "base/location.cc"; -#endif - constexpr size_t path_len = StrLen(path); - constexpr size_t stripped_len = StrLen(stripped); - static_assert(path_len >= stripped_len, + + constexpr size_t kPathLen = kPath.size(); + constexpr size_t kStrippedLen = kThisFilePath.size(); + static_assert(kPathLen >= kStrippedLen, "Invalid file path for base/location.cc."); - return path_len - stripped_len; + return kPathLen - kStrippedLen; } constexpr size_t kStrippedPrefixLength = StrippedFilePathPrefixLength(); @@ -49,29 +45,14 @@ constexpr size_t kStrippedPrefixLength = StrippedFilePathPrefixLength(); // and the suffix matches the |expected| string. // TODO(ssid): With C++20 we can make base::EndsWith() constexpr and use it // instead. -constexpr bool StrEndsWith(const char* name, +constexpr bool StrEndsWith(std::string_view name, size_t prefix_len, - const char* expected) { - const size_t name_len = StrLen(name); - const size_t expected_len = StrLen(expected); - if (name_len != prefix_len + expected_len) { - return false; - } - for (size_t i = 0; i < expected_len; ++i) { - if (UNSAFE_TODO(name[i + prefix_len] != expected[i])) { - return false; - } - } - return true; + std::string_view expected) { + return name.substr(prefix_len) == expected; } -#if defined(__clang__) && defined(_MSC_VER) -static_assert(StrEndsWith(__FILE__, kStrippedPrefixLength, "base\\location.cc"), +static_assert(StrEndsWith(__FILE__, kStrippedPrefixLength, kThisFilePath), "The file name does not match the expected prefix format."); -#else -static_assert(StrEndsWith(__FILE__, kStrippedPrefixLength, "base/location.cc"), - "The file name does not match the expected prefix format."); -#endif } // namespace @@ -91,15 +72,10 @@ Location::Location(const char* function_name, file_name_(file_name), line_number_(line_number), program_counter_(program_counter) { -#if !BUILDFLAG(IS_NACL) // The program counter should not be null except in a default constructed // (empty) Location object. This value is used for identity, so if it doesn't // uniquely identify a location, things will break. - // - // The program counter isn't supported in NaCl so location objects won't work - // properly in that context. DCHECK(program_counter); -#endif } std::string Location::ToString() const { @@ -119,7 +95,7 @@ void Location::WriteIntoTrace(perfetto::TracedValue context) const { #if defined(COMPILER_MSVC) #define RETURN_ADDRESS() _ReturnAddress() -#elif defined(COMPILER_GCC) && !BUILDFLAG(IS_NACL) +#elif defined(COMPILER_GCC) #define RETURN_ADDRESS() \ __builtin_extract_return_addr(__builtin_return_address(0)) #else diff --git a/naiveproxy/src/base/logging.cc b/naiveproxy/src/base/logging.cc index 1b44b7e945..4f0a186200 100644 --- a/naiveproxy/src/base/logging.cc +++ b/naiveproxy/src/base/logging.cc @@ -20,6 +20,7 @@ #include #include +#include "base/auto_reset.h" #include "base/base_export.h" #include "base/base_switches.h" #include "base/command_line.h" @@ -55,14 +56,9 @@ #include "third_party/abseil-cpp/absl/cleanup/cleanup.h" #include "third_party/perfetto/protos/perfetto/trace/track_event/log_message.pbzero.h" -#if !BUILDFLAG(IS_NACL) -#include "base/auto_reset.h" -#include "base/debug/crash_logging.h" -#endif // !BUILDFLAG(IS_NACL) - -#if defined(LEAK_SANITIZER) && !BUILDFLAG(IS_NACL) +#if defined(LEAK_SANITIZER) #include "base/debug/leak_annotations.h" -#endif // defined(LEAK_SANITIZER) && !BUILDFLAG(IS_NACL) +#endif // defined(LEAK_SANITIZER) #if BUILDFLAG(IS_WIN) #include @@ -97,10 +93,6 @@ typedef HANDLE FileHandle; #include "base/posix/safe_strerror.h" -#if BUILDFLAG(IS_NACL) -#include // timespec doesn't seem to be in -#endif - #define MAX_PATH PATH_MAX typedef FILE* FileHandle; #endif // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) @@ -169,7 +161,7 @@ std::unique_ptr VlogInfoFromCommandLine() { !command_line->HasSwitch(switches::kVModule)) { return nullptr; } -#if defined(LEAK_SANITIZER) && !BUILDFLAG(IS_NACL) +#if defined(LEAK_SANITIZER) // See comments on |g_vlog_info|. ScopedLeakSanitizerDisabler lsan_disabler; #endif // defined(LEAK_SANITIZER) @@ -264,10 +256,6 @@ uint64_t TickCount() { static_cast(base::Time::kNanosecondsPerMicrosecond)); #elif BUILDFLAG(IS_APPLE) return mach_absolute_time(); -#elif BUILDFLAG(IS_NACL) - // NaCl sadly does not have _POSIX_TIMERS enabled in sys/features.h - // So we have to use clock() for now. - return clock(); #elif BUILDFLAG(IS_POSIX) struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); @@ -282,8 +270,6 @@ uint64_t TickCount() { void DeleteFilePath(const PathString& log_name) { #if BUILDFLAG(IS_WIN) DeleteFile(log_name.c_str()); -#elif BUILDFLAG(IS_NACL) - // Do nothing; unlink() isn't supported on NaCl. #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) unlink(log_name.c_str()); #else @@ -439,7 +425,6 @@ void WriteToFd(int fd, const char* data, size_t length) { } void SetLogFatalCrashKey(LogMessage* log_message) { -#if !BUILDFLAG(IS_NACL) // In case of an out-of-memory condition, this code could be reentered when // constructing and storing the key. Using a static is not thread-safe, but if // multiple threads are in the process of a fatal crash at the same time, this @@ -456,8 +441,6 @@ void SetLogFatalCrashKey(LogMessage* log_message) { static auto* const crash_key = base::debug::AllocateCrashKeyString( "LOG_FATAL", base::debug::CrashKeySize::Size1024); base::debug::SetCrashKeyString(crash_key, log_message->BuildCrashString()); - -#endif // !BUILDFLAG(IS_NACL) } std::string BuildCrashString(const char* file, @@ -507,12 +490,6 @@ BASE_EXPORT logging::LogSeverity LOGGING_DCHECK = LOGGING_ERROR; std::ostream* g_swallow_stream; bool BaseInitLoggingImpl(const LoggingSettings& settings) { -#if BUILDFLAG(IS_NACL) - // Can log only to the system debug log and stderr. - CHECK_EQ(settings.logging_dest & ~(LOG_TO_SYSTEM_DEBUG_LOG | LOG_TO_STDERR), - 0u); -#endif - #if BUILDFLAG(IS_CHROMEOS) g_log_format = settings.log_format; #endif @@ -718,8 +695,7 @@ void LogMessage::Flush() { base::ScopedClearLastError scoped_clear_last_error; size_t stack_start = stream_.str().length(); -#if !defined(OFFICIAL_BUILD) && !BUILDFLAG(IS_NACL) && !defined(__UCLIBC__) && \ - !BUILDFLAG(IS_AIX) +#if !defined(OFFICIAL_BUILD) && !defined(__UCLIBC__) && !BUILDFLAG(IS_AIX) // Include a stack trace on a fatal, unless a debugger is attached. if (severity_ == LOGGING_FATAL && !base::debug::BeingDebugged()) { base::debug::StackTrace stack_trace; @@ -1328,7 +1304,7 @@ void ScopedVmoduleSwitches::InitWithSwitches( // Make sure we are only initialized once. CHECK(!scoped_vlog_info_); { -#if defined(LEAK_SANITIZER) && !BUILDFLAG(IS_NACL) +#if defined(LEAK_SANITIZER) // See comments on |g_vlog_info|. ScopedLeakSanitizerDisabler lsan_disabler; #endif // defined(LEAK_SANITIZER) diff --git a/naiveproxy/src/base/logging.h b/naiveproxy/src/base/logging.h index 262a86ef02..440fa5ebf3 100644 --- a/naiveproxy/src/base/logging.h +++ b/naiveproxy/src/base/logging.h @@ -198,7 +198,7 @@ enum : uint32_t { // On POSIX platforms, where it may not even be possible to locate the // executable on disk, use stderr. // On Fuchsia, use the Fuchsia logging service. -#if BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_NACL) +#if BUILDFLAG(IS_FUCHSIA) LOG_DEFAULT = LOG_TO_SYSTEM_DEBUG_LOG, #elif BUILDFLAG(IS_WIN) LOG_DEFAULT = LOG_TO_FILE, diff --git a/naiveproxy/src/base/mac/mac_util.h b/naiveproxy/src/base/mac/mac_util.h index 4421ac4230..fca3e45a35 100644 --- a/naiveproxy/src/base/mac/mac_util.h +++ b/naiveproxy/src/base/mac/mac_util.h @@ -135,6 +135,9 @@ enum class SystemSettingsPane { // Privacy & Security > Screen Recording kPrivacySecurity_ScreenRecording, + // Privacy & Security > Pasteboard + kPrivacySecurity_Pasteboard, + // Trackpad kTrackpad, }; diff --git a/naiveproxy/src/base/mac/mac_util.mm b/naiveproxy/src/base/mac/mac_util.mm index 343883c06f..f5ed1e0e11 100644 --- a/naiveproxy/src/base/mac/mac_util.mm +++ b/naiveproxy/src/base/mac/mac_util.mm @@ -335,19 +335,6 @@ int ParseOSProductVersion(const std::string_view& version) { // the "macOS 16" compatibility modes are engaged. CHECK(macos_version >= 10'00'00); CHECK(macos_version < 10'16'00 || macos_version >= 11'00'00); - - // When this code is built with an SDK earlier than the macOS 26 SDK, `sysctl` - // lies and returns the value of "kern.osproductversioncompat" (which claims - // this is macOS 16) when asked for "kern.osproductversion". Therefore, if a - // version of macOS 16 is seen, then this code is seeing compatibility mode, - // so adjust the version to match the real macOS version. - // - // TODO(https://crbug.com/423933062, https://crbug.com/424162749): Build with - // the macOS 26 SDK and remove this adjustment code. - if (macos_version >= 16'00'00 && macos_version < 17'00'00) { - macos_version += 10'00'00; - } - CHECK(macos_version < 16'00'00 || macos_version >= 26'00'00); return macos_version; @@ -588,6 +575,12 @@ void OpenSystemSettingsPane(SystemSettingsPane pane, pane_file = @"/System/Library/PreferencePanes/Trackpad.prefPane"; } break; + case SystemSettingsPane::kPrivacySecurity_Pasteboard: + // Pasteboard permissions were added in macOS 15. + DCHECK_GE(MacOSMajorVersion(), 15); + url = @"x-apple.systempreferences:com.apple.settings.PrivacySecurity." + @"extension?Privacy_Pasteboard"; + break; } DCHECK(url != nil ^ pane_file != nil); diff --git a/naiveproxy/src/base/memory/platform_shared_memory_mapper_android.cc b/naiveproxy/src/base/memory/platform_shared_memory_mapper_android.cc index 53d060ca17..36df982ee0 100644 --- a/naiveproxy/src/base/memory/platform_shared_memory_mapper_android.cc +++ b/naiveproxy/src/base/memory/platform_shared_memory_mapper_android.cc @@ -2,15 +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/40284755): Remove this and spanify to fix the errors. -#pragma allow_unsafe_buffers -#endif - #include "base/memory/platform_shared_memory_mapper.h" #include +#include "base/compiler_specific.h" #include "base/logging.h" #include "base/numerics/safe_conversions.h" @@ -33,7 +29,7 @@ std::optional> PlatformSharedMemoryMapper::Map( return std::nullopt; } - return span(static_cast(address), size); + return UNSAFE_TODO(span(static_cast(address), size)); } void PlatformSharedMemoryMapper::Unmap(span mapping) { diff --git a/naiveproxy/src/base/memory/platform_shared_memory_mapper_posix.cc b/naiveproxy/src/base/memory/platform_shared_memory_mapper_posix.cc index d6fcd243ed..c520a8b5f8 100644 --- a/naiveproxy/src/base/memory/platform_shared_memory_mapper_posix.cc +++ b/naiveproxy/src/base/memory/platform_shared_memory_mapper_posix.cc @@ -2,15 +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/40284755): Remove this and spanify to fix the errors. -#pragma allow_unsafe_buffers -#endif - #include "base/memory/platform_shared_memory_mapper.h" #include +#include "base/compiler_specific.h" #include "base/logging.h" #include "base/numerics/safe_conversions.h" @@ -30,7 +26,7 @@ std::optional> PlatformSharedMemoryMapper::Map( return std::nullopt; } - return span(static_cast(address), size); + return UNSAFE_TODO(span(static_cast(address), size)); } void PlatformSharedMemoryMapper::Unmap(span mapping) { diff --git a/naiveproxy/src/base/memory/ref_counted.h b/naiveproxy/src/base/memory/ref_counted.h index e380927906..9826eb4cc1 100644 --- a/naiveproxy/src/base/memory/ref_counted.h +++ b/naiveproxy/src/base/memory/ref_counted.h @@ -413,7 +413,7 @@ class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase { public: using RefCountPreferenceTag = subtle::StartRefCountFromZeroTag; - explicit RefCountedThreadSafe() + RefCountedThreadSafe() : subtle::RefCountedThreadSafeBase(subtle::GetRefCountPreference()) {} RefCountedThreadSafe(const RefCountedThreadSafe&) = delete; diff --git a/naiveproxy/src/base/memory/safe_ref.h b/naiveproxy/src/base/memory/safe_ref.h index f1f2507968..08c95198e9 100644 --- a/naiveproxy/src/base/memory/safe_ref.h +++ b/naiveproxy/src/base/memory/safe_ref.h @@ -152,7 +152,7 @@ class SafeRef { // Construction from a from a WeakPtr's internals. Will CHECK() if the WeakPtr // is already invalid. - explicit SafeRef(internal::WeakReference&& ref, T* ptr) + SafeRef(internal::WeakReference&& ref, T* ptr) : ref_(std::move(ref)), ptr_(ptr) { CHECK(ref_.IsValid()); } diff --git a/naiveproxy/src/base/memory/safety_checks.h b/naiveproxy/src/base/memory/safety_checks.h index 5373de4252..fd45631fbf 100644 --- a/naiveproxy/src/base/memory/safety_checks.h +++ b/naiveproxy/src/base/memory/safety_checks.h @@ -5,6 +5,8 @@ #ifndef BASE_MEMORY_SAFETY_CHECKS_H_ #define BASE_MEMORY_SAFETY_CHECKS_H_ +#include + #include #include @@ -337,6 +339,16 @@ class BASE_EXPORT ScopedSafetyChecksExclusion { #endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) }; +#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) +using base::allocator::SchedulerLoopQuarantineScanPolicyUpdater; +#else +class SchedulerLoopQuarantineScanPolicyUpdater { + public: + ALWAYS_INLINE void DisallowScanlessPurge() {} + ALWAYS_INLINE void AllowScanlessPurge() {} +}; +#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) + } // namespace base #endif // BASE_MEMORY_SAFETY_CHECKS_H_ diff --git a/naiveproxy/src/base/memory/shared_memory_mapping.cc b/naiveproxy/src/base/memory/shared_memory_mapping.cc index 4cc27a70b4..f00a738049 100644 --- a/naiveproxy/src/base/memory/shared_memory_mapping.cc +++ b/naiveproxy/src/base/memory/shared_memory_mapping.cc @@ -2,17 +2,13 @@ // 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/memory/shared_memory_mapping.h" #include #include #include "base/bits.h" +#include "base/compiler_specific.h" #include "base/logging.h" #include "base/memory/shared_memory_security_policy.h" #include "base/memory/shared_memory_tracker.h" @@ -75,7 +71,7 @@ void SharedMemoryMapping::Unmap() { size_t adjusted_size = mapped_span_.size() + static_cast(mapped_span_.data() - aligned_data); - mapper->Unmap(span(aligned_data, adjusted_size)); + mapper->Unmap(UNSAFE_TODO(span(aligned_data, adjusted_size))); } ReadOnlySharedMemoryMapping::ReadOnlySharedMemoryMapping() = default; diff --git a/naiveproxy/src/base/memory_coordinator/DIR_METADATA b/naiveproxy/src/base/memory_coordinator/DIR_METADATA new file mode 100644 index 0000000000..bf35951f81 --- /dev/null +++ b/naiveproxy/src/base/memory_coordinator/DIR_METADATA @@ -0,0 +1,6 @@ +monorail: { + component: "Internals>MemoryCoordinator" +} +buganizer_public: { + component_id: 1840922 +} diff --git a/naiveproxy/src/base/memory_coordinator/OWNERS b/naiveproxy/src/base/memory_coordinator/OWNERS new file mode 100644 index 0000000000..8310e62e9d --- /dev/null +++ b/naiveproxy/src/base/memory_coordinator/OWNERS @@ -0,0 +1,6 @@ +# Primary +pmonette@chromium.org + +# Secondary +fdoray@chromium.org +grt@chromium.org diff --git a/naiveproxy/src/base/memory_coordinator/async_memory_consumer_registration.cc b/naiveproxy/src/base/memory_coordinator/async_memory_consumer_registration.cc new file mode 100644 index 0000000000..467e1b5a51 --- /dev/null +++ b/naiveproxy/src/base/memory_coordinator/async_memory_consumer_registration.cc @@ -0,0 +1,91 @@ +// Copyright 2025 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/memory_coordinator/async_memory_consumer_registration.h" + +#include +#include + +#include "base/check.h" +#include "base/functional/bind.h" +#include "base/memory_coordinator/memory_consumer.h" +#include "base/task/sequenced_task_runner.h" +#include "base/task/single_thread_task_runner.h" +#include "base/threading/thread_checker.h" + +namespace base { + +// AsyncMemoryConsumerRegistration::MainThread --------------------------------- + +class AsyncMemoryConsumerRegistration::MainThread : public MemoryConsumer { + public: + MainThread(std::string observer_id, + MemoryConsumerTraits traits, + WeakPtr parent, + scoped_refptr consumer_task_runner) + : consumer_task_runner_(std::move(consumer_task_runner)), + parent_(std::move(parent)), + registration_(std::move(observer_id), traits, this) {} + + private: + // MemoryConsumer: + void OnUpdateMemoryLimit() override { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + consumer_task_runner_->PostTask( + FROM_HERE, + BindOnce(&AsyncMemoryConsumerRegistration::NotifyUpdateMemoryLimit, + parent_, memory_limit())); + } + void OnReleaseMemory() override { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + consumer_task_runner_->PostTask( + FROM_HERE, + BindOnce(&AsyncMemoryConsumerRegistration::NotifyReleaseMemory, + parent_)); + } + + // The task runner on which the off-sequence consumer lives. + scoped_refptr consumer_task_runner_ + GUARDED_BY_CONTEXT(thread_checker_); + + // A pointer to the consumer that lives on `consumer_task_runner_`. + WeakPtr parent_ + GUARDED_BY_CONTEXT(thread_checker_); + + // The registration with the MemoryConsumerRegistry. + ScopedMemoryConsumerRegistration registration_ + GUARDED_BY_CONTEXT(thread_checker_); + + THREAD_CHECKER(thread_checker_); +}; + +// AsyncMemoryConsumerRegistration --------------------------------------------- + +AsyncMemoryConsumerRegistration::AsyncMemoryConsumerRegistration( + scoped_refptr main_task_runner, + std::string_view consumer_id, + MemoryConsumerTraits traits, + MemoryConsumer* consumer) + : consumer_(consumer) { + DCHECK(!main_task_runner->BelongsToCurrentThread()); + main_thread_.emplace(std::move(main_task_runner), std::string(consumer_id), + traits, weak_ptr_factory_.GetWeakPtr(), + SequencedTaskRunner::GetCurrentDefault()); +} + +AsyncMemoryConsumerRegistration::~AsyncMemoryConsumerRegistration() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +void AsyncMemoryConsumerRegistration::NotifyUpdateMemoryLimit(int percentage) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + consumer_->UpdateMemoryLimit(percentage); +} + +void AsyncMemoryConsumerRegistration::NotifyReleaseMemory() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + consumer_->ReleaseMemory(); +} + +} // namespace base diff --git a/naiveproxy/src/base/memory_coordinator/async_memory_consumer_registration.h b/naiveproxy/src/base/memory_coordinator/async_memory_consumer_registration.h new file mode 100644 index 0000000000..4fa33b7806 --- /dev/null +++ b/naiveproxy/src/base/memory_coordinator/async_memory_consumer_registration.h @@ -0,0 +1,52 @@ +// Copyright 2025 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_MEMORY_COORDINATOR_ASYNC_MEMORY_CONSUMER_REGISTRATION_H_ +#define BASE_MEMORY_COORDINATOR_ASYNC_MEMORY_CONSUMER_REGISTRATION_H_ + +#include + +#include "base/base_export.h" +#include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/memory_coordinator/traits.h" +#include "base/sequence_checker.h" +#include "base/threading/sequence_bound.h" + +namespace base { + +class MemoryConsumer; +class SingleThreadTaskRunner; + +// Used to register a MemoryConsumer that does not live on the main thread, +// which means that the consumer will receive its notifications asynchronously. +class BASE_EXPORT AsyncMemoryConsumerRegistration { + public: + AsyncMemoryConsumerRegistration( + scoped_refptr main_thread_task_runner, + std::string_view consumer_id, + MemoryConsumerTraits traits, + MemoryConsumer* consumer); + ~AsyncMemoryConsumerRegistration(); + + private: + class MainThread; + + void NotifyUpdateMemoryLimit(int percentage); + void NotifyReleaseMemory(); + + // A pointer to the actual consumer. Must outlive `this`. + raw_ptr consumer_ GUARDED_BY_CONTEXT(sequence_checker_); + + // Parts of this class that lives on the main thread. + SequenceBound main_thread_ GUARDED_BY_CONTEXT(sequence_checker_); + + SEQUENCE_CHECKER(sequence_checker_); + + WeakPtrFactory weak_ptr_factory_{this}; +}; + +} // namespace base + +#endif // BASE_MEMORY_COORDINATOR_ASYNC_MEMORY_CONSUMER_REGISTRATION_H_ diff --git a/naiveproxy/src/base/memory_coordinator/memory_consumer.cc b/naiveproxy/src/base/memory_coordinator/memory_consumer.cc new file mode 100644 index 0000000000..b0b0e6fcb9 --- /dev/null +++ b/naiveproxy/src/base/memory_coordinator/memory_consumer.cc @@ -0,0 +1,42 @@ +// Copyright 2025 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/memory_coordinator/memory_consumer.h" + +#include "base/check_op.h" +#include "base/memory_coordinator/memory_consumer_registry.h" + +namespace base { + +// MemoryConsumer --------------------------------------------------- + +void MemoryConsumer::ReleaseMemory() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + OnReleaseMemory(); +} + +void MemoryConsumer::UpdateMemoryLimit(int percentage) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // The percentage can never be negative (but it can be higher than 100). + CHECK_GE(percentage, 0); + memory_limit_ = percentage; + OnUpdateMemoryLimit(); +} + +// ScopedMemoryConsumerRegistration --------------------------------- + +ScopedMemoryConsumerRegistration::ScopedMemoryConsumerRegistration( + std::string_view consumer_id, + MemoryConsumerTraits traits, + MemoryConsumer* consumer) + : consumer_id_(consumer_id), consumer_(consumer) { + MemoryConsumerRegistry::Get().AddMemoryConsumer(consumer_id, traits, + consumer_); +} + +ScopedMemoryConsumerRegistration::~ScopedMemoryConsumerRegistration() { + MemoryConsumerRegistry::Get().RemoveMemoryConsumer(consumer_id_, consumer_); +} + +} // namespace base diff --git a/naiveproxy/src/base/memory_coordinator/memory_consumer.h b/naiveproxy/src/base/memory_coordinator/memory_consumer.h new file mode 100644 index 0000000000..136d4b80d1 --- /dev/null +++ b/naiveproxy/src/base/memory_coordinator/memory_consumer.h @@ -0,0 +1,127 @@ +// Copyright 2025 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_MEMORY_COORDINATOR_MEMORY_CONSUMER_H_ +#define BASE_MEMORY_COORDINATOR_MEMORY_CONSUMER_H_ + +#include +#include + +#include "base/base_export.h" +#include "base/memory/raw_ptr.h" +#include "base/memory_coordinator/traits.h" +#include "base/sequence_checker.h" + +namespace base { + +// The MemoryConsumer is used to coordinate memory usage across all processes. +// By registering with the MemoryConsumerRegistry, instances of this class are +// notified when they should reduce or increase memory usage. +// +// Each consumer has a unique ID, and a set of traits. All registered consumers +// with the same unique ID are assumed to be equivalent and must have the exact +// same traits. +// +// Each consumer is assigned a memory usage limit; a percentage that indicates +// how much memory they are allowed to use. The memory coordinator policy does +// not prescribe what a 100% limit is. It is up to the implementer to determine +// what specific number should correspond to the 100% limit. +// +// For instance, if a developer determines that a cache size of 500 entries +// represents the optimal balance between performance and memory usage for a +// typical user on a standard machine, then a 100% memory limit would correspond +// to this size. A 50% memory limit would thus correspond to 250 entries. This +// example uses a linear interpolation, but this is not mandated. +// +// The percentage cannot be negative, but it is allowed to go over 100%, in +// which case the implementation should scale accordingly. +// +// Note that an implementation of `OnUpdateMemoryLimit()` should *not* release +// any memory. This function is intended to simply update an internal limit, and +// a consumer should wait for a subsequent call to `OnReleaseMemory()` to free +// any memory that exceeds that limit. +// +// Here is an example implementation for a consumer that manages a cache with a +// LRU eviction policy. +// +// class ExampleConsumer : public MemoryConsumer { +// public: +// // ... +// +// // MemoryConsumer: +// void OnUpdateMemoryLimit() override { +// // Update the maximum size of the cache, but don't decrease that maximum +// // size below its current size to avoid freeing memory. +// int new_max_size = +// std::max(cache_.size(), kDefaultCacheMaxSize * memory_limit() / 100); +// cache_.SetMaxSize(new_max_size); +// } +// void OnReleaseMemory() override { +// int new_max_size = kDefaultCacheMaxSize * memory_limit() / 100; +// cache_.SetMaxSizeAndEvictExtraEntries(new_max_size); +// } +// +// private: +// static constexpr int kDefaultCacheMaxSize = 500; +// LRUCache cache_; +// }; +// +class BASE_EXPORT MemoryConsumer { + public: + virtual ~MemoryConsumer() = default; + + // The memory limit, expressed as a percentage. + int memory_limit() const { return memory_limit_; } + + // Same as `memory_limit`, but expressed as a ratio. + double memory_limit_ratio() const { return memory_limit_ / 100.0; } + + protected: + // Invoked when memory above the current `memory_limit()` should be freed. + virtual void OnReleaseMemory() = 0; + + // Invoked when the `memory_limit()` assigned to this instance is updated. See + // the class comment above for a detailed description of how this limit works. + virtual void OnUpdateMemoryLimit() = 0; + + private: + friend class RegisteredMemoryConsumer; + friend class AsyncMemoryConsumerRegistration; + + // Instructs this consumer to update its internal memory limit. See the class + // comment above for a detailed description of how this limit works. + void UpdateMemoryLimit(int percentage); + + // Instructs this consumer to release memory that is above the current + // `memory_limit()`. + void ReleaseMemory(); + + int memory_limit_ = 100; + + SEQUENCE_CHECKER(sequence_checker_); +}; + +// Similar to ScopedObservation, registers a MemoryConsumer with the global +// MemoryConsumerRegistry. +class BASE_EXPORT ScopedMemoryConsumerRegistration { + public: + ScopedMemoryConsumerRegistration(std::string_view consumer_id, + MemoryConsumerTraits traits, + MemoryConsumer* consumer); + + ScopedMemoryConsumerRegistration(const ScopedMemoryConsumerRegistration&) = + delete; + ScopedMemoryConsumerRegistration& operator=( + const ScopedMemoryConsumerRegistration&) = delete; + + ~ScopedMemoryConsumerRegistration(); + + private: + std::string consumer_id_; + raw_ptr consumer_; +}; + +} // namespace base + +#endif // BASE_MEMORY_COORDINATOR_MEMORY_CONSUMER_H_ diff --git a/naiveproxy/src/base/memory_coordinator/memory_consumer_registry.cc b/naiveproxy/src/base/memory_coordinator/memory_consumer_registry.cc new file mode 100644 index 0000000000..04317bf9fa --- /dev/null +++ b/naiveproxy/src/base/memory_coordinator/memory_consumer_registry.cc @@ -0,0 +1,56 @@ +// Copyright 2025 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/memory_coordinator/memory_consumer_registry.h" + +#include "base/check.h" +#include "base/check_op.h" + +namespace base { + +namespace { + +MemoryConsumerRegistry* g_memory_consumer_registry = nullptr; + +} // namespace + +void RegisteredMemoryConsumer::UpdateMemoryLimit(int percentage) { + memory_consumer_->UpdateMemoryLimit(percentage); +} + +void RegisteredMemoryConsumer::ReleaseMemory() { + memory_consumer_->ReleaseMemory(); +} + +RegisteredMemoryConsumer::RegisteredMemoryConsumer( + MemoryConsumer* memory_consumer) + : memory_consumer_(memory_consumer) {} + +// static +MemoryConsumerRegistry& MemoryConsumerRegistry::Get() { + CHECK(g_memory_consumer_registry); + return *g_memory_consumer_registry; +} + +// static +void MemoryConsumerRegistry::Set(MemoryConsumerRegistry* instance) { + CHECK_NE(bool(g_memory_consumer_registry), bool(instance)); + g_memory_consumer_registry = instance; +} + +void MemoryConsumerRegistry::AddMemoryConsumer(std::string_view consumer_id, + MemoryConsumerTraits traits, + MemoryConsumer* consumer) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + OnMemoryConsumerAdded(consumer_id, traits, + RegisteredMemoryConsumer(consumer)); +} + +void MemoryConsumerRegistry::RemoveMemoryConsumer(std::string_view consumer_id, + MemoryConsumer* consumer) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + OnMemoryConsumerRemoved(consumer_id, RegisteredMemoryConsumer(consumer)); +} + +} // namespace base diff --git a/naiveproxy/src/base/memory_coordinator/memory_consumer_registry.h b/naiveproxy/src/base/memory_coordinator/memory_consumer_registry.h new file mode 100644 index 0000000000..66d84cc8d6 --- /dev/null +++ b/naiveproxy/src/base/memory_coordinator/memory_consumer_registry.h @@ -0,0 +1,94 @@ +// Copyright 2025 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_MEMORY_COORDINATOR_MEMORY_CONSUMER_REGISTRY_H_ +#define BASE_MEMORY_COORDINATOR_MEMORY_CONSUMER_REGISTRY_H_ + +#include +#include + +#include "base/base_export.h" +#include "base/memory/raw_ptr.h" +#include "base/memory_coordinator/memory_consumer.h" +#include "base/sequence_checker.h" + +namespace base { + +// Provides an interface to safely notify MemoryConsumers of their memory limit. +class BASE_EXPORT RegisteredMemoryConsumer { + public: + void UpdateMemoryLimit(int percentage); + void ReleaseMemory(); + + friend bool operator==(const RegisteredMemoryConsumer& lhs, + const RegisteredMemoryConsumer& rhs) = default; + + private: + friend class MemoryConsumerRegistry; + + explicit RegisteredMemoryConsumer(MemoryConsumer* memory_consumer); + + raw_ptr memory_consumer_; +}; + +// A minimal interface for registering a MemoryConsumer with the +// global registry for the current process. +class BASE_EXPORT MemoryConsumerRegistry { + public: + static MemoryConsumerRegistry& Get(); + static void Set(MemoryConsumerRegistry* instance); + + // Adds/Removes an instance of MemoryConsumer with a specific + // `consumer_id` and `traits`. + void AddMemoryConsumer(std::string_view consumer_id, + MemoryConsumerTraits traits, + MemoryConsumer* consumer); + void RemoveMemoryConsumer(std::string_view consumer_id, + MemoryConsumer* consumer); + + protected: + virtual ~MemoryConsumerRegistry() = default; + + RegisteredMemoryConsumer CreateRegisteredMemoryConsumer( + MemoryConsumer* memory_consumer) { + return RegisteredMemoryConsumer(memory_consumer); + } + + private: + virtual void OnMemoryConsumerAdded(std::string_view consumer_id, + MemoryConsumerTraits traits, + RegisteredMemoryConsumer consumer) = 0; + virtual void OnMemoryConsumerRemoved(std::string_view consumer_id, + RegisteredMemoryConsumer consumer) = 0; + + SEQUENCE_CHECKER(sequence_checker_); +}; + +// Helper class for creating and registering a singleton registry. This is +// separate from the base interface so that tests can instantiate multiple +// registries in the same process. +template +class ScopedMemoryConsumerRegistry { + public: + template + explicit ScopedMemoryConsumerRegistry(Args&&... args) + : registry_(std::forward(args)...) { + MemoryConsumerRegistry::Set(®istry_); + } + + ScopedMemoryConsumerRegistry(const ScopedMemoryConsumerRegistry&) = delete; + ScopedMemoryConsumerRegistry operator=(ScopedMemoryConsumerRegistry&) = + delete; + + ~ScopedMemoryConsumerRegistry() { MemoryConsumerRegistry::Set(nullptr); } + + RegistryType& Get() { return registry_; } + + private: + RegistryType registry_; +}; + +} // namespace base + +#endif // BASE_MEMORY_COORDINATOR_MEMORY_CONSUMER_REGISTRY_H_ diff --git a/naiveproxy/src/base/memory_coordinator/mock_memory_consumer.cc b/naiveproxy/src/base/memory_coordinator/mock_memory_consumer.cc new file mode 100644 index 0000000000..8fad5aa822 --- /dev/null +++ b/naiveproxy/src/base/memory_coordinator/mock_memory_consumer.cc @@ -0,0 +1,13 @@ +// Copyright 2025 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/memory_coordinator/mock_memory_consumer.h" + +namespace base { + +MockMemoryConsumer::MockMemoryConsumer() = default; + +MockMemoryConsumer::~MockMemoryConsumer() = default; + +} // namespace base diff --git a/naiveproxy/src/base/memory_coordinator/mock_memory_consumer.h b/naiveproxy/src/base/memory_coordinator/mock_memory_consumer.h new file mode 100644 index 0000000000..cc3c96b5f5 --- /dev/null +++ b/naiveproxy/src/base/memory_coordinator/mock_memory_consumer.h @@ -0,0 +1,24 @@ +// Copyright 2025 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_MEMORY_COORDINATOR_MOCK_MEMORY_CONSUMER_H_ +#define BASE_MEMORY_COORDINATOR_MOCK_MEMORY_CONSUMER_H_ + +#include "base/memory_coordinator/memory_consumer.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace base { + +class MockMemoryConsumer : public MemoryConsumer { + public: + MockMemoryConsumer(); + ~MockMemoryConsumer() override; + + MOCK_METHOD(void, OnUpdateMemoryLimit, (), (override)); + MOCK_METHOD(void, OnReleaseMemory, (), (override)); +}; + +} // namespace base + +#endif // BASE_MEMORY_COORDINATOR_MOCK_MEMORY_CONSUMER_H_ diff --git a/naiveproxy/src/base/memory_coordinator/test_memory_consumer_registry.cc b/naiveproxy/src/base/memory_coordinator/test_memory_consumer_registry.cc new file mode 100644 index 0000000000..f1848b320a --- /dev/null +++ b/naiveproxy/src/base/memory_coordinator/test_memory_consumer_registry.cc @@ -0,0 +1,51 @@ +// Copyright 2025 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/memory_coordinator/test_memory_consumer_registry.h" + +#include "base/check.h" +#include "base/check_op.h" +#include "base/containers/contains.h" +#include "base/memory_coordinator/memory_consumer.h" + +namespace base { + +TestMemoryConsumerRegistry::TestMemoryConsumerRegistry() { + MemoryConsumerRegistry::Set(this); +} + +TestMemoryConsumerRegistry::~TestMemoryConsumerRegistry() { + MemoryConsumerRegistry::Set(nullptr); + + CHECK(memory_consumers_.empty()); +} + +void TestMemoryConsumerRegistry::OnMemoryConsumerAdded( + std::string_view consumer_id, + MemoryConsumerTraits traits, + RegisteredMemoryConsumer consumer) { + CHECK(!base::Contains(memory_consumers_, consumer)); + memory_consumers_.push_back(consumer); +} + +void TestMemoryConsumerRegistry::OnMemoryConsumerRemoved( + std::string_view consumer_id, + RegisteredMemoryConsumer consumer) { + size_t removed = std::erase(memory_consumers_, consumer); + CHECK_EQ(removed, 1u); +} + +void TestMemoryConsumerRegistry::NotifyUpdateMemoryLimit(int percentage) { + for (RegisteredMemoryConsumer consumer : memory_consumers_) { + consumer.UpdateMemoryLimit(percentage); + } +} + +void TestMemoryConsumerRegistry::NotifyReleaseMemory() { + for (RegisteredMemoryConsumer consumer : memory_consumers_) { + consumer.ReleaseMemory(); + } +} + +} // namespace base diff --git a/naiveproxy/src/base/memory_coordinator/test_memory_consumer_registry.h b/naiveproxy/src/base/memory_coordinator/test_memory_consumer_registry.h new file mode 100644 index 0000000000..f1bf7bb57f --- /dev/null +++ b/naiveproxy/src/base/memory_coordinator/test_memory_consumer_registry.h @@ -0,0 +1,44 @@ +// Copyright 2025 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_MEMORY_COORDINATOR_TEST_MEMORY_CONSUMER_REGISTRY_H_ +#define BASE_MEMORY_COORDINATOR_TEST_MEMORY_CONSUMER_REGISTRY_H_ + +#include + +#include + +#include "base/memory_coordinator/memory_consumer_registry.h" + +namespace base { + +// A test class that allows registration of MemoryConsumers in unit tests. Do +// not instantiate in browser tests. +class TestMemoryConsumerRegistry : public MemoryConsumerRegistry { + public: + TestMemoryConsumerRegistry(); + ~TestMemoryConsumerRegistry() override; + + // MemoryConsumerRegistry: + void OnMemoryConsumerAdded(std::string_view consumer_id, + MemoryConsumerTraits traits, + RegisteredMemoryConsumer consumer) override; + void OnMemoryConsumerRemoved(std::string_view consumer_id, + RegisteredMemoryConsumer consumer) override; + + // Invokes UpdateMemoryLimit(percentage) on all consumers. + void NotifyUpdateMemoryLimit(int percentage); + + // Invokes DoReleaseMemory() on all consumers. + void NotifyReleaseMemory(); + + size_t size() const { return memory_consumers_.size(); } + + private: + std::vector memory_consumers_; +}; + +} // namespace base + +#endif // BASE_MEMORY_COORDINATOR_TEST_MEMORY_CONSUMER_REGISTRY_H_ diff --git a/naiveproxy/src/base/memory_coordinator/traits.h b/naiveproxy/src/base/memory_coordinator/traits.h new file mode 100644 index 0000000000..4d32d38d01 --- /dev/null +++ b/naiveproxy/src/base/memory_coordinator/traits.h @@ -0,0 +1,140 @@ +// Copyright 2025 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_MEMORY_COORDINATOR_TRAITS_H_ +#define BASE_MEMORY_COORDINATOR_TRAITS_H_ + +#include + +namespace base { + +// Describes how a MemoryConsumer works using a set of enum values. +struct MemoryConsumerTraits { + // Indicates if this MemoryConsumer supports the concept of a memory limit. + enum class SupportsMemoryLimit : uint8_t { + kYes, + kNo, + + kMaxValue = kNo, + }; + + // Indicates if the memory freed happens inside the process where the consumer + // lives. If yes, then the consumer can be notified to help in the case of + // address space exhaustion in the current process. + enum class InProcess : uint8_t { + kYes, + kNo, + + kMaxValue = kNo, + }; + + // The approximate scale of how much memory the consumer can manage. + enum class EstimatedMemoryUsage : uint8_t { + // Under 10 MBs. + kSmall, + // Tens of MBs. + kMedium, + // Hundreds of MBs up to multiple GBs. + kLarge, + + kMaxValue = kLarge, + }; + + // Indicates if the memory this consumer manages is cheap to free. Traversing + // a data structure is usually more expensive than freeing a single chunk of + // memory and can cause memory to be paged in. Note that the page size is + // typically between 4k and 16k. + enum class ReleaseMemoryCost : uint8_t { + // Most of the savings are from allocations larger than the page size that + // are freed without being accessed. + kFreesPagesWithoutTraversal, + // Most of the savings are from allocations smaller than the page size, or + // from larger allocations that are accessed prior to be freed. + kRequiresTraversal, + + kMaxValue = kRequiresTraversal, + }; + + // Indicates if recreating the memory is possible, and if so, if is it + // expensive to do so. + enum class RecreateMemoryCost : uint8_t { + // Freed memory can't be recreated. + kNA, + // Recreating the memory is not expensive. i.e. Read a file into memory. + kCheap, + // Recreating the memory is expensive. i.e. Complex decoding of a resource. + kExpensive, + + kMaxValue = kExpensive, + }; + + enum class InformationRetention : uint8_t { + // Freeing memory will result in loss of user state. I.e. discarding a tab. + kLossy, + // Freeing memory will not result in the loss of user state. I.e. It is a + // cache, or it can be recalculated from a raw resource. + kLossless, + + kMaxValue = kLossless, + }; + + enum class MemoryReleaseBehavior : uint8_t { + // OnReleaseMemory() can be called repeatedly to release additional memory. + // i.e. Tab discarding. + kRepeatable, + // Once OnReleaseMemory() is called once, additional calls will not have any + // effect. i.e. Cache clearing. + kIdempotent, + + kMaxValue = kIdempotent, + }; + + // Indicates if freeing memory is an asynchronous operation or a synchronous + // operation. Knowing that a consumer will execute synchronously is useful to + // know because the memory coordinator policy can then immediately assess the + // new state of the machine after the notification. + enum class ExecutionType : uint8_t { + kSynchronous, + kAsynchronous, + + kMaxValue = kAsynchronous, + }; + + // Indicates if this consumer manages references to the v8 heap. In this case, + // no memory is actually released until a garbage collection is done. + enum class ReleaseGCReferences : uint8_t { + kYes, + kNo, + + kMaxValue = kNo, + }; + + // Trait for the v8 garbage collector. + enum class GarbageCollectsV8Heap : uint8_t { + kYes, + kNo, + + kMaxValue = kNo, + }; + + friend bool operator==(const MemoryConsumerTraits& lhs, + const MemoryConsumerTraits& rhs) = default; + + // LINT.IfChange + SupportsMemoryLimit supports_memory_limit; + InProcess in_process; + EstimatedMemoryUsage estimated_memory_usage; + ReleaseMemoryCost release_memory_cost; + RecreateMemoryCost recreate_memory_cost; + InformationRetention information_retention; + MemoryReleaseBehavior memory_release_behavior; + ExecutionType execution_type; + ReleaseGCReferences release_gc_references; + GarbageCollectsV8Heap garbage_collects_v8_heap; + // LINT.ThenChange(//content/common/memory_coordinator/mojom/memory_coordinator.mojom) +}; + +} // namespace base + +#endif // BASE_MEMORY_COORDINATOR_TRAITS_H_ diff --git a/naiveproxy/src/base/message_loop/io_watcher.cc b/naiveproxy/src/base/message_loop/io_watcher.cc index 3fb82b0a5c..6abe41d28f 100644 --- a/naiveproxy/src/base/message_loop/io_watcher.cc +++ b/naiveproxy/src/base/message_loop/io_watcher.cc @@ -22,7 +22,6 @@ IOWatcher* IOWatcher::Get() { return CurrentThread::Get()->GetIOWatcher(); } -#if !BUILDFLAG(IS_NACL) #if BUILDFLAG(IS_WIN) bool IOWatcher::RegisterIOHandler(HANDLE file, MessagePumpForIO::IOHandler* handler) { @@ -62,6 +61,5 @@ bool IOWatcher::WatchZxHandle( return WatchZxHandleImpl(handle, persistent, signals, controller, delegate); } #endif -#endif // !BUILDFLAG(IS_NACL) } // namespace base diff --git a/naiveproxy/src/base/message_loop/io_watcher.h b/naiveproxy/src/base/message_loop/io_watcher.h index e3e8b135a3..7dff497460 100644 --- a/naiveproxy/src/base/message_loop/io_watcher.h +++ b/naiveproxy/src/base/message_loop/io_watcher.h @@ -36,7 +36,6 @@ class BASE_EXPORT IOWatcher { // Returns null otherwise. static IOWatcher* Get(); -#if !BUILDFLAG(IS_NACL) #if BUILDFLAG(IS_WIN) // Please see MessagePumpWin for definitions of these methods. [[nodiscard]] bool RegisterIOHandler(HANDLE file, @@ -101,14 +100,12 @@ class BASE_EXPORT IOWatcher { MessagePumpForIO::ZxHandleWatchController* controller, MessagePumpForIO::ZxHandleWatcher* delegate); #endif // BUILDFLAG(IS_FUCHSIA) -#endif // !BUILDFLAG(IS_NACL) protected: IOWatcher(); // IOWatcher implementations must implement these methods for any applicable // platform(s). -#if !BUILDFLAG(IS_NACL) #if BUILDFLAG(IS_WIN) virtual bool RegisterIOHandlerImpl(HANDLE file, MessagePumpForIO::IOHandler* handler) = 0; @@ -136,7 +133,6 @@ class BASE_EXPORT IOWatcher { MessagePumpForIO::ZxHandleWatchController* controller, MessagePumpForIO::ZxHandleWatcher* delegate) = 0; #endif // BUILDFLAG(IS_FUCHSIA) -#endif // !BUILDFLAG(IS_NACL) }; } // namespace base diff --git a/naiveproxy/src/base/message_loop/message_pump.cc b/naiveproxy/src/base/message_loop/message_pump.cc index 0f99896563..ae0b8d4a30 100644 --- a/naiveproxy/src/base/message_loop/message_pump.cc +++ b/naiveproxy/src/base/message_loop/message_pump.cc @@ -42,7 +42,7 @@ std::atomic g_align_wake_ups_and_leeway = MessagePump::MessagePumpFactory* message_pump_for_ui_factory_ = nullptr; -#if !BUILDFLAG(IS_NACL) && BUILDFLAG(IS_POSIX) +#if BUILDFLAG(IS_POSIX) class MessagePumpForIOFdWatchImpl : public IOWatcher::FdWatch, public MessagePumpForIO::FdWatcher { public: @@ -76,7 +76,6 @@ class IOWatcherForCurrentIOThread : public IOWatcher { IOWatcherForCurrentIOThread() : thread_(CurrentIOThread::Get()) {} // IOWatcher: -#if !BUILDFLAG(IS_NACL) #if BUILDFLAG(IS_WIN) bool RegisterIOHandlerImpl(HANDLE file, MessagePumpForIO::IOHandler* handler) override { @@ -134,7 +133,6 @@ class IOWatcherForCurrentIOThread : public IOWatcher { delegate); } #endif // BUILDFLAG(IS_FUCHSIA) -#endif // !BUILDFLAG(IS_NACL) private: CurrentIOThread thread_; @@ -171,9 +169,8 @@ std::unique_ptr MessagePump::Create(MessagePumpType type) { } #if BUILDFLAG(IS_APPLE) return message_pump_apple::Create(); -#elif BUILDFLAG(IS_NACL) || BUILDFLAG(IS_AIX) - // Currently NaCl and AIX don't have a UI MessagePump. - // TODO(abarth): Figure out if we need this. +#elif BUILDFLAG(IS_AIX) + // Currently AIX doesn't have a UI MessagePump. NOTREACHED(); #elif BUILDFLAG(IS_ANDROID) { diff --git a/naiveproxy/src/base/message_loop/message_pump_android.cc b/naiveproxy/src/base/message_loop/message_pump_android.cc index 5823750dcb..2a74fa52ac 100644 --- a/naiveproxy/src/base/message_loop/message_pump_android.cc +++ b/naiveproxy/src/base/message_loop/message_pump_android.cc @@ -21,6 +21,7 @@ #include "base/android/input_hint_checker.h" #include "base/android/jni_android.h" #include "base/android/scoped_java_ref.h" +#include "base/android/yield_to_looper_checker.h" #include "base/check.h" #include "base/check_op.h" #include "base/message_loop/io_watcher.h" @@ -33,6 +34,7 @@ using base::android::InputHintChecker; using base::android::InputHintResult; +using base::android::YieldToLooperChecker; namespace base { @@ -455,15 +457,23 @@ void MessagePumpAndroid::DoNonDelayedLooperWork(bool do_idle_work) { next_work_info = delegate_->DoWork(); - // As an optimization, yield to the Looper when input events are waiting to - // be handled. In some cases input events can remain undetected. Such "input - // 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_ && next_work_info.is_immediate() && - InputHintChecker::HasInput()) { - ScheduleWork(); - return; + if (is_type_ui_ && next_work_info.is_immediate()) { + // To reduce startup ANRs, yield if an embedder signifies that startup is + // currently running. + if (YieldToLooperChecker::GetInstance().ShouldYield()) { + ScheduleWork(); + return; + } + + // As an optimization, yield to the Looper when input events are waiting + // to be handled. In some cases input events can remain undetected. Such + // "input 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 (InputHintChecker::HasInput()) { + ScheduleWork(); + return; + } } } while (next_work_info.is_immediate()); diff --git a/naiveproxy/src/base/message_loop/message_pump_default.cc b/naiveproxy/src/base/message_loop/message_pump_default.cc index f61747c9c6..ee1e3357c4 100644 --- a/naiveproxy/src/base/message_loop/message_pump_default.cc +++ b/naiveproxy/src/base/message_loop/message_pump_default.cc @@ -70,8 +70,6 @@ void MessagePumpDefault::Run(Delegate* delegate) { event_.Wait(); } } else { - TRACE_EVENT(TRACE_DISABLED_BY_DEFAULT("base"), "TimeWait", "delay_ms", - next_work_info.remaining_delay().InMilliseconds()); // Not handling shorter sleeps to keep the code as simple as possible. if (ShouldBusyLoop() && next_work_info.remaining_delay() > max_busy_loop_time_) { diff --git a/naiveproxy/src/base/message_loop/message_pump_for_io.h b/naiveproxy/src/base/message_loop/message_pump_for_io.h index ae0ceb174e..090f1df937 100644 --- a/naiveproxy/src/base/message_loop/message_pump_for_io.h +++ b/naiveproxy/src/base/message_loop/message_pump_for_io.h @@ -17,8 +17,6 @@ #include "base/message_loop/message_pump_io_ios.h" #elif BUILDFLAG(IS_APPLE) #include "base/message_loop/message_pump_kqueue.h" -#elif BUILDFLAG(IS_NACL) -#include "base/message_loop/message_pump_default.h" #elif BUILDFLAG(IS_FUCHSIA) #include "base/message_loop/message_pump_fuchsia.h" #elif BUILDFLAG(IS_POSIX) @@ -34,8 +32,6 @@ using MessagePumpForIO = MessagePumpForIO; using MessagePumpForIO = MessagePumpIOSForIO; #elif BUILDFLAG(IS_APPLE) using MessagePumpForIO = MessagePumpKqueue; -#elif BUILDFLAG(IS_NACL) -using MessagePumpForIO = MessagePumpDefault; #elif BUILDFLAG(IS_FUCHSIA) using MessagePumpForIO = MessagePumpFuchsia; #elif BUILDFLAG(IS_POSIX) diff --git a/naiveproxy/src/base/message_loop/message_pump_for_ui.h b/naiveproxy/src/base/message_loop/message_pump_for_ui.h index 458c29bddd..e421d75201 100644 --- a/naiveproxy/src/base/message_loop/message_pump_for_ui.h +++ b/naiveproxy/src/base/message_loop/message_pump_for_ui.h @@ -16,7 +16,7 @@ #include "base/message_loop/message_pump_android.h" #elif BUILDFLAG(IS_APPLE) #include "base/message_loop/message_pump.h" -#elif BUILDFLAG(IS_NACL) || BUILDFLAG(IS_AIX) +#elif BUILDFLAG(IS_AIX) // No MessagePumpForUI, see below. #elif defined(USE_GLIB) #include "base/message_loop/message_pump_glib.h" @@ -38,8 +38,8 @@ using MessagePumpForUI = MessagePumpAndroid; // be represented by a plain MessagePump: message_pump_apple::Create() must be // used to instantiate the right impl. using MessagePumpForUI = MessagePump; -#elif BUILDFLAG(IS_NACL) || BUILDFLAG(IS_AIX) -// Currently NaCl and AIX don't have a MessagePumpForUI. +#elif BUILDFLAG(IS_AIX) +// Currently AIX doesn't have a MessagePumpForUI. // TODO(abarth): Figure out if we need this. #elif defined(USE_GLIB) using MessagePumpForUI = MessagePumpGlib; diff --git a/naiveproxy/src/base/metrics/bucket_ranges.cc b/naiveproxy/src/base/metrics/bucket_ranges.cc index edab2fea1c..03c5768da6 100644 --- a/naiveproxy/src/base/metrics/bucket_ranges.cc +++ b/naiveproxy/src/base/metrics/bucket_ranges.cc @@ -62,18 +62,7 @@ void BucketRanges::ResetChecksum() { } bool BucketRanges::Equals(const BucketRanges* other) const { - if (checksum_ != other->checksum_) { - return false; - } - if (ranges_.size() != other->ranges_.size()) { - return false; - } - for (size_t index = 0; index < ranges_.size(); ++index) { - if (ranges_[index] != other->ranges_[index]) { - return false; - } - } - return true; + return checksum_ == other->checksum_ && ranges_ == other->ranges_; } } // namespace base diff --git a/naiveproxy/src/base/metrics/field_trial_params.h b/naiveproxy/src/base/metrics/field_trial_params.h index 0c5ab654df..8f6c48098e 100644 --- a/naiveproxy/src/base/metrics/field_trial_params.h +++ b/naiveproxy/src/base/metrics/field_trial_params.h @@ -235,8 +235,8 @@ struct FeatureParam { // Returns the param-string for the given enum value. std::string GetName(Enum value) const { for (size_t i = 0; i < option_count; ++i) { - if (value == options[i].value) { - return options[i].name; + if (value == UNSAFE_TODO(options[i].value)) { + return UNSAFE_TODO(options[i].name); } } NOTREACHED(); diff --git a/naiveproxy/src/base/metrics/histogram.cc b/naiveproxy/src/base/metrics/histogram.cc index d49f5ad5d1..c5a3de611a 100644 --- a/naiveproxy/src/base/metrics/histogram.cc +++ b/naiveproxy/src/base/metrics/histogram.cc @@ -808,9 +808,9 @@ class LinearHistogram::Factory : public Histogram::Factory { LinearHistogram* histogram = static_cast(base_histogram); // Set range descriptions. if (descriptions_) { - for (int i = 0; descriptions_[i].description; ++i) { - histogram->bucket_description_[descriptions_[i].sample] = - descriptions_[i].description; + for (int i = 0; UNSAFE_TODO(descriptions_[i].description); ++i) { + UNSAFE_TODO(histogram->bucket_description_[descriptions_[i].sample] = + descriptions_[i].description); } } } diff --git a/naiveproxy/src/base/metrics/histogram_base.h b/naiveproxy/src/base/metrics/histogram_base.h index 4a214a0e16..90738d1274 100644 --- a/naiveproxy/src/base/metrics/histogram_base.h +++ b/naiveproxy/src/base/metrics/histogram_base.h @@ -22,7 +22,6 @@ namespace base { -class Value; class HistogramBase; class HistogramSamples; class Pickle; diff --git a/naiveproxy/src/base/metrics/histogram_functions.h b/naiveproxy/src/base/metrics/histogram_functions.h index 20ca685ec4..5df0663a06 100644 --- a/naiveproxy/src/base/metrics/histogram_functions.h +++ b/naiveproxy/src/base/metrics/histogram_functions.h @@ -202,7 +202,7 @@ BASE_EXPORT void UmaHistogramMemoryKB(std::string_view name, int sample); // Used to measure common MB-granularity memory stats. Sample is in MB. Range is // 1MB to ~1G. BASE_EXPORT void UmaHistogramMemoryMB(std::string_view name, int sample); -// Used to measure common MB-granularity memory stats. Range is 1G to ~64G. +// Used to measure common MB-granularity memory stats. Range is 1MB to ~64G. BASE_EXPORT void UmaHistogramMemoryLargeMB(std::string_view name, int sample); // LINT.ThenChange(/base/metrics/histogram_functions_internal_overloads.h:UmaHistogramMemory) diff --git a/naiveproxy/src/base/metrics/histogram_macros.h b/naiveproxy/src/base/metrics/histogram_macros.h index 0824a1ae8b..b44dc026e0 100644 --- a/naiveproxy/src/base/metrics/histogram_macros.h +++ b/naiveproxy/src/base/metrics/histogram_macros.h @@ -340,11 +340,11 @@ enum class ScopedHistogramTiming { UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, 1000, 500000, 50) // Used to measure common MB-granularity memory stats. Sample is in MB. Range is -// 1MB to ~1G. +// 1MB to ~4G. #define UMA_HISTOGRAM_MEMORY_MEDIUM_MB(name, sample) \ UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, 1, 4000, 100) -// Used to measure common MB-granularity memory stats. Range is 1G to ~64G. +// Used to measure common MB-granularity memory stats. Range is 1MB to ~64G. #define UMA_HISTOGRAM_MEMORY_LARGE_MB(name, sample) \ UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, 1, 64000, 100) diff --git a/naiveproxy/src/base/metrics/histogram_macros_internal.h b/naiveproxy/src/base/metrics/histogram_macros_internal.h index daa5515c2a..09a9458fac 100644 --- a/naiveproxy/src/base/metrics/histogram_macros_internal.h +++ b/naiveproxy/src/base/metrics/histogram_macros_internal.h @@ -15,6 +15,7 @@ #include "base/dcheck_is_on.h" #include "base/metrics/histogram.h" #include "base/metrics/sparse_histogram.h" +#include "base/no_destructor.h" #include "base/time/time.h" #include "base/types/cxx23_to_underlying.h" @@ -56,9 +57,9 @@ struct EnumSizeTraits { // process. // In some cases (integration into 3rd party code), it's useful to separate the -// definition of |atomic_histogram_pointer| from its use. To achieve this we -// define HISTOGRAM_POINTER_USE, which uses an |atomic_histogram_pointer|, and -// STATIC_HISTOGRAM_POINTER_BLOCK, which defines an |atomic_histogram_pointer| +// definition of `atomic_histogram_pointer` from its use. To achieve this we +// define HISTOGRAM_POINTER_USE, which uses an `atomic_histogram_pointer`, and +// STATIC_HISTOGRAM_POINTER_BLOCK, which defines an `atomic_histogram_pointer` // and forwards to HISTOGRAM_POINTER_USE. #define HISTOGRAM_POINTER_USE( \ atomic_histogram_pointer, constant_histogram_name, \ @@ -70,7 +71,7 @@ struct EnumSizeTraits { if (!histogram_pointer) { \ /* \ * This is the slow path, which will construct OR find the \ - * matching histogram. |histogram_factory_get_invocation| includes \ + * matching histogram. `histogram_factory_get_invocation` includes \ * locks on a global histogram name map and is completely thread \ * safe. \ */ \ @@ -91,7 +92,7 @@ struct EnumSizeTraits { } while (0) // This is a helper macro used by other macros and shouldn't be used directly. -// Defines the static |atomic_histogram_pointer| and forwards to +// Defines the static `atomic_histogram_pointer` and forwards to // HISTOGRAM_POINTER_USE. #define STATIC_HISTOGRAM_POINTER_BLOCK(constant_histogram_name, \ histogram_add_method_invocation, \ @@ -161,9 +162,8 @@ struct EnumSizeTraits { scale, \ flag) {} \ }; \ - static base::LazyInstance::Leaky \ - scaled_leaky; \ - scaled_leaky.Get().AddScaledCount(sample, count); \ + static base::NoDestructor scaled_leaky; \ + scaled_leaky->AddScaledCount(sample, count); \ } while (0) // Helper for 'overloading' UMA_HISTOGRAM_ENUMERATION with a variable number of @@ -177,7 +177,7 @@ struct EnumSizeTraits { base::internal::EnumSizeTraits>::Count(), \ flags) -// Note: The value in |sample| must be strictly less than |enum_size|. +// Note: The value in `sample` must be strictly less than `enum_size`. #define INTERNAL_UMA_HISTOGRAM_ENUMERATION_SPECIFY_BOUNDARY(name, sample, \ enum_size, flags) \ INTERNAL_HISTOGRAM_ENUMERATION_WITH_FLAG(name, sample, enum_size, flags) diff --git a/naiveproxy/src/base/metrics/histogram_shared_memory.cc b/naiveproxy/src/base/metrics/histogram_shared_memory.cc index 229f4488ea..b8ba6af6fe 100644 --- a/naiveproxy/src/base/metrics/histogram_shared_memory.cc +++ b/naiveproxy/src/base/metrics/histogram_shared_memory.cc @@ -121,24 +121,20 @@ HistogramSharedMemory::Create(int process_id, // static bool HistogramSharedMemory::PassOnCommandLineIsEnabled(int process_type) { - // On ChromeOS and for "utility" processes on other platforms there seems to - // be one or more mechanisms on startup which walk through all inherited - // shared memory regions and take a read-only handle to them. When we later - // attempt to deserialize the handle info and take a writable handle we - // find that the handle is already owned in read-only mode, triggering - // a crash due to "FD ownership violation". + // On Android "utility" processes, there seems to be one or more mechanisms on + // startup which walk through all inherited shared memory regions and take a + // read-only handle to them. When we later attempt to deserialize the handle + // info and take a writable handle we find that the handle is already owned in + // read-only mode, triggering a crash due to "FD ownership violation". // // Example: The call to OpenSymbolFiles() in base/debug/stack_trace_posix.cc // grabs a read-only handle to the shmem region for some process types. // - // TODO(crbug.com/40109064): Fix ChromeOS GPU and Android utility processes. - // Constants from content::ProcessType; - [[maybe_unused]] constexpr int PROCESS_TYPE_GPU = 9; + // TODO(crbug.com/40109064): Fix Android utility processes. Constants from + // content::ProcessType; [[maybe_unused]] constexpr int PROCESS_TYPE_UTILITY = 6; return (FeatureList::IsEnabled(kPassHistogramSharedMemoryOnLaunch) -#if BUILDFLAG(IS_CHROMEOS) - && process_type != PROCESS_TYPE_GPU -#elif BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(IS_ANDROID) && process_type != PROCESS_TYPE_UTILITY #endif ); diff --git a/naiveproxy/src/base/metrics/persistent_histogram_allocator.cc b/naiveproxy/src/base/metrics/persistent_histogram_allocator.cc index 7c2675bb5b..a0096152c5 100644 --- a/naiveproxy/src/base/metrics/persistent_histogram_allocator.cc +++ b/naiveproxy/src/base/metrics/persistent_histogram_allocator.cc @@ -758,7 +758,6 @@ void GlobalHistogramAllocator::CreateWithLocalMemory(size_t size, std::make_unique(size, id, name))); } -#if !BUILDFLAG(IS_NACL) // static bool GlobalHistogramAllocator::CreateWithFile(const FilePath& file_path, size_t size, @@ -940,7 +939,6 @@ bool GlobalHistogramAllocator::CreateSpareFile(const FilePath& spare_path, return success; } -#endif // !BUILDFLAG(IS_NACL) // static void GlobalHistogramAllocator::CreateWithSharedMemoryRegion( @@ -1047,10 +1045,6 @@ bool GlobalHistogramAllocator::MovePersistentFile(const FilePath& dir) { } bool GlobalHistogramAllocator::WriteToPersistentLocation() { -#if BUILDFLAG(IS_NACL) - // NACL doesn't support file operations, including ImportantFileWriter. - NOTREACHED(); -#else // Stop if no destination is set. if (!HasPersistentLocation()) { NOTREACHED() << "Could not write \"" << Name() << "\" persistent histograms" @@ -1066,15 +1060,11 @@ bool GlobalHistogramAllocator::WriteToPersistentLocation() { } return true; -#endif } void GlobalHistogramAllocator::DeletePersistentLocation() { memory_allocator()->SetMemoryState(PersistentMemoryAllocator::MEMORY_DELETED); -#if BUILDFLAG(IS_NACL) - NOTREACHED(); -#else if (!HasPersistentLocation()) { return; } @@ -1085,7 +1075,6 @@ void GlobalHistogramAllocator::DeletePersistentLocation() { // new opens will not be possible. File file(persistent_location_, File::FLAG_OPEN | File::FLAG_READ | File::FLAG_DELETE_ON_CLOSE); -#endif } GlobalHistogramAllocator::GlobalHistogramAllocator( diff --git a/naiveproxy/src/base/metrics/persistent_histogram_allocator.h b/naiveproxy/src/base/metrics/persistent_histogram_allocator.h index 5d13b2d0de..0f0c387eb4 100644 --- a/naiveproxy/src/base/metrics/persistent_histogram_allocator.h +++ b/naiveproxy/src/base/metrics/persistent_histogram_allocator.h @@ -394,7 +394,6 @@ class BASE_EXPORT GlobalHistogramAllocator uint64_t id, std::string_view name); -#if !BUILDFLAG(IS_NACL) // Create a global allocator by memory-mapping a `file`. If the file does // not exist, it will be created with the specified `size`. If the file does // exist, the allocator will use and add to its contents, ignoring the passed @@ -454,7 +453,6 @@ class BASE_EXPORT GlobalHistogramAllocator // Create a "spare" file that can later be made the "active" file. This // should be done on a background thread if possible. static bool CreateSpareFile(const FilePath& spare_path, size_t size); -#endif // Create a global allocator using a block of shared memory accessed // through the given `region`. The allocator maps the shared memory into diff --git a/naiveproxy/src/base/metrics/persistent_memory_allocator.cc b/naiveproxy/src/base/metrics/persistent_memory_allocator.cc index 67001ae1d6..e79c88646b 100644 --- a/naiveproxy/src/base/metrics/persistent_memory_allocator.cc +++ b/naiveproxy/src/base/metrics/persistent_memory_allocator.cc @@ -350,11 +350,7 @@ PersistentMemoryAllocator::PersistentMemoryAllocator(Memory memory, mem_type_(memory.type), mem_size_(checked_cast(size)), mem_page_(checked_cast((page_size ? page_size : size))), -#if BUILDFLAG(IS_NACL) - vm_page_size_(4096U), // SysInfo is not built for NACL. -#else vm_page_size_(SysInfo::VMAllocationGranularity()), -#endif access_mode_(access_mode) { // These asserts ensure that the structures are 32/64-bit agnostic and meet // all the requirements of use within the allocator. They access private @@ -705,14 +701,12 @@ PersistentMemoryAllocator::Reference PersistentMemoryAllocator::AllocateImpl( // TODO(crbug.com/40064026): With the current state of the code, this // code path should not be reached. However, crash reports have been // hinting that it is. Add crash keys to investigate this. -#if !BUILDFLAG(IS_NACL) const auto* allocator = GlobalHistogramAllocator::Get(); SCOPED_CRASH_KEY_STRING256( PMA, "file_name", allocator && allocator->HasPersistentLocation() ? allocator->GetPersistentLocation().BaseName().AsUTF8Unsafe() : "N/A"); -#endif // !BUILDFLAG(IS_NACL) // It is not thread-safe to read from the block header. this->DumpWithoutCrashing(/*ref=*/freeptr, /*expected_type=*/type_id, @@ -1029,7 +1023,6 @@ void PersistentMemoryAllocator::DumpWithoutCrashing( [[maybe_unused]] uint32_t expected_type, [[maybe_unused]] size_t expected_size, [[maybe_unused]] bool dump_block_header) const { -#if !BUILDFLAG(IS_NACL) SCOPED_CRASH_KEY_STRING32(PMA, "name", Name()); SCOPED_CRASH_KEY_NUMBER(PMA, "memory_size", size()); SCOPED_CRASH_KEY_NUMBER(PMA, "page_size", page_size()); @@ -1058,7 +1051,6 @@ void PersistentMemoryAllocator::DumpWithoutCrashing( block ? NumberToString(block->type_id) : unknown); SCOPED_CRASH_KEY_STRING32(PMA, "block_next", block ? NumberToString(block->next) : unknown); -#endif // !BUILDFLAG(IS_NACL) ::base::debug::DumpWithoutCrashing(); } @@ -1190,7 +1182,6 @@ bool ReadOnlySharedPersistentMemoryAllocator::IsSharedMemoryAcceptable( return IsMemoryAcceptable(memory.memory(), memory.size(), 0, true); } -#if !BUILDFLAG(IS_NACL) //----- FilePersistentMemoryAllocator ------------------------------------------ FilePersistentMemoryAllocator::FilePersistentMemoryAllocator( @@ -1275,7 +1266,6 @@ void FilePersistentMemoryAllocator::FlushPartial(size_t length, bool sync) { #error Unsupported OS. #endif } -#endif // !BUILDFLAG(IS_NACL) //----- DelayedPersistentAllocation -------------------------------------------- @@ -1344,7 +1334,6 @@ span DelayedPersistentAllocation::GetUntyped() const { // reached. Getting here means the is some corruption or error in the // allocator and/or the allocated block. -#if !BUILDFLAG(IS_NACL) // There are many crash reports containing the `kBlockCookieAllocated` magic // value in `ref`. This value is used to indicate that a given block in // persistent memory was successfully allocated, so it should not appear as a @@ -1361,16 +1350,17 @@ span DelayedPersistentAllocation::GetUntyped() const { SCOPED_CRASH_KEY_STRING32( PMA, "ref_value_before", ref_is_magic_number - ? NumberToString((reference_ - 1)->load(std::memory_order_relaxed)) + ? NumberToString( + (UNSAFE_TODO(reference_ - 1))->load(std::memory_order_relaxed)) : "N/A"); SCOPED_CRASH_KEY_STRING32( PMA, "ref_value_after", ref_is_magic_number - ? NumberToString((reference_ + 1)->load(std::memory_order_relaxed)) + ? NumberToString( + (UNSAFE_TODO(reference_ + 1))->load(std::memory_order_relaxed)) : "N/A"); SCOPED_CRASH_KEY_BOOL(PMA, "ref_found", ref_found); SCOPED_CRASH_KEY_BOOL(PMA, "race_detected", race_detected); -#endif // !BUILDFLAG(IS_NACL) // The allocator has detected a corrupt/invalid reference. This is not fatal. // Capture the current state to a crash dump so the circumstances can be diff --git a/naiveproxy/src/base/metrics/persistent_memory_allocator.h b/naiveproxy/src/base/metrics/persistent_memory_allocator.h index 42dee558f7..ab4501347e 100644 --- a/naiveproxy/src/base/metrics/persistent_memory_allocator.h +++ b/naiveproxy/src/base/metrics/persistent_memory_allocator.h @@ -903,8 +903,6 @@ class BASE_EXPORT ReadOnlySharedPersistentMemoryAllocator base::ReadOnlySharedMemoryMapping shared_memory_; }; -// NACL doesn't support any kind of file access in build. -#if !BUILDFLAG(IS_NACL) // This allocator takes a memory-mapped file object and performs allocation // from it. The allocator takes ownership of the file object. class BASE_EXPORT FilePersistentMemoryAllocator @@ -946,7 +944,6 @@ class BASE_EXPORT FilePersistentMemoryAllocator private: std::unique_ptr mapped_file_; }; -#endif // !BUILDFLAG(IS_NACL) // An allocation that is defined but not executed until required at a later // time. This allows for potential users of an allocation to be decoupled diff --git a/naiveproxy/src/base/metrics/persistent_sample_map.cc b/naiveproxy/src/base/metrics/persistent_sample_map.cc index 83b65d50e5..9433d65f94 100644 --- a/naiveproxy/src/base/metrics/persistent_sample_map.cc +++ b/naiveproxy/src/base/metrics/persistent_sample_map.cc @@ -12,6 +12,7 @@ #include "base/check_op.h" #include "base/containers/contains.h" +#include "base/debug/crash_logging.h" #include "base/metrics/histogram_base.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_samples.h" @@ -20,10 +21,6 @@ #include "base/notreached.h" #include "build/buildflag.h" -#if !BUILDFLAG(IS_NACL) -#include "base/debug/crash_logging.h" -#endif - namespace base { using Count32 = HistogramBase::Count32; @@ -76,7 +73,8 @@ void PersistentSampleMap::Accumulate(Sample32 value, Count32 count) { } Count32 PersistentSampleMap::GetCount(Sample32 value) const { - const std::atomic* const count_pointer = GetSampleCountStorage(value); + const std::atomic* const count_pointer = + GetSampleCountStorage(value); return count_pointer ? count_pointer->load(std::memory_order_relaxed) : 0; } @@ -147,10 +145,8 @@ PersistentSampleMap::CreatePersistentRecord( if (!allocator->IsFull()) { const bool corrupt = allocator->IsCorrupt(); -#if !BUILDFLAG(IS_NACL) // TODO(crbug.com/40064026): Remove. SCOPED_CRASH_KEY_BOOL("PersistentSampleMap", "corrupted", corrupt); -#endif // !BUILDFLAG(IS_NACL) DUMP_WILL_BE_NOTREACHED() << "corrupt=" << corrupt; } return 0; diff --git a/naiveproxy/src/base/metrics/sample_vector.cc b/naiveproxy/src/base/metrics/sample_vector.cc index 8f95c4ead1..ffed6e2f2a 100644 --- a/naiveproxy/src/base/metrics/sample_vector.cc +++ b/naiveproxy/src/base/metrics/sample_vector.cc @@ -14,11 +14,11 @@ #include "base/debug/crash_logging.h" #include "base/debug/dump_without_crashing.h" #include "base/debug/leak_annotations.h" -#include "base/lazy_instance.h" #include "base/memory/ptr_util.h" #include "base/memory/raw_span.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/persistent_memory_allocator.h" +#include "base/no_destructor.h" #include "base/notreached.h" #include "base/numerics/safe_conversions.h" #include "base/strings/strcat.h" @@ -438,14 +438,14 @@ void SampleVectorBase::MoveSingleSampleToCounts() { } void SampleVectorBase::MountCountsStorageAndMoveSingleSample() { - // There are many SampleVector objects and the lock is needed very - // infrequently (just when advancing from single-sample to multi-sample) so - // define a single, global lock that all can use. This lock only prevents - // concurrent entry into the code below; access and updates to |counts_data_| - // still requires atomic operations. - static LazyInstance::Leaky counts_lock = LAZY_INSTANCE_INITIALIZER; if (counts_data_.load(std::memory_order_relaxed) == nullptr) { - AutoLock lock(counts_lock.Get()); + // There are many SampleVector objects and the lock is needed very + // infrequently (just when advancing from single-sample to multi-sample) so + // define a single, global lock that all can use. This lock only prevents + // concurrent entry into the code below; access and updates to + // |counts_data_| still requires atomic operations. + static base::NoDestructor counts_lock; + AutoLock lock(*counts_lock); if (counts_data_.load(std::memory_order_relaxed) == nullptr) { // Create the actual counts storage while the above lock is acquired. span counts = CreateCountsStorageWhileLocked(); @@ -636,11 +636,9 @@ PersistentSampleVector::PersistentSampleVector( // once investigation is complete. if (result != MountExistingCountsStorageResult::kSucceeded && result != MountExistingCountsStorageResult::kNothingToRead) { -#if !BUILDFLAG(IS_NACL) SCOPED_CRASH_KEY_STRING64("PSV", "name", name); SCOPED_CRASH_KEY_NUMBER("PSV", "counts_ref", persistent_counts_.reference()); -#endif debug::DumpWithoutCrashing(); } } diff --git a/naiveproxy/src/base/metrics/statistics_recorder.cc b/naiveproxy/src/base/metrics/statistics_recorder.cc index 0a6227cd84..20755633d4 100644 --- a/naiveproxy/src/base/metrics/statistics_recorder.cc +++ b/naiveproxy/src/base/metrics/statistics_recorder.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/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "base/metrics/statistics_recorder.h" #include @@ -24,6 +19,7 @@ #include "base/metrics/metrics_hashes.h" #include "base/metrics/persistent_histogram_allocator.h" #include "base/metrics/record_histogram_checker.h" +#include "base/no_destructor.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/values.h" @@ -39,9 +35,6 @@ bool HistogramNameLesser(const base::HistogramBase* a, } // namespace -// static -LazyInstance::Leaky StatisticsRecorder::lock_ = LAZY_INSTANCE_INITIALIZER; - // static StatisticsRecorder* StatisticsRecorder::top_ = nullptr; @@ -322,6 +315,17 @@ void StatisticsRecorder::InitLogOnShutdown() { InitLogOnShutdownWhileLocked(); } +// static +Lock& StatisticsRecorder::GetLock() { + static base::NoDestructor lock; + return *lock; +} + +// static +void StatisticsRecorder::AssertLockHeld() { + GetLock().AssertAcquired(); +} + HistogramBase* StatisticsRecorder::FindHistogramByHashInternal( uint64_t hash, std::string_view name) const { diff --git a/naiveproxy/src/base/metrics/statistics_recorder.h b/naiveproxy/src/base/metrics/statistics_recorder.h index 3b3f2dc856..221bec825d 100644 --- a/naiveproxy/src/base/metrics/statistics_recorder.h +++ b/naiveproxy/src/base/metrics/statistics_recorder.h @@ -22,7 +22,6 @@ #include "base/base_export.h" #include "base/functional/callback.h" #include "base/gtest_prod_util.h" -#include "base/lazy_instance.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/metrics/histogram_base.h" @@ -94,12 +93,12 @@ class BASE_EXPORT StatisticsRecorder { public: // Constructor. Called with the desired histogram name and the callback to // be invoked when a sample is recorded. - explicit ScopedHistogramSampleObserver(std::string_view histogram_name, - OnSampleCallback callback); - explicit ScopedHistogramSampleObserver(std::string_view histogram_name, - OnSampleWithEventCallback callback); - explicit ScopedHistogramSampleObserver(std::string_view histogram_name, - base::RepeatingClosure callback); + ScopedHistogramSampleObserver(std::string_view histogram_name, + OnSampleCallback callback); + ScopedHistogramSampleObserver(std::string_view histogram_name, + OnSampleWithEventCallback callback); + ScopedHistogramSampleObserver(std::string_view histogram_name, + base::RepeatingClosure callback); ~ScopedHistogramSampleObserver(); private: @@ -320,8 +319,11 @@ class BASE_EXPORT StatisticsRecorder { } private: - static Lock& GetLock() { return lock_.Get(); } - static void AssertLockHeld() { lock_.Get().AssertAcquired(); } + // Global lock for internal synchronization. + // Note: Care must be taken to not read or write anything to persistent memory + // while holding this lock, as that could cause a file I/O stall. + static Lock& GetLock(); + static void AssertLockHeld(); // Returns the histogram registered with |hash|, if there is one. Returns // nullptr otherwise. @@ -401,11 +403,6 @@ class BASE_EXPORT StatisticsRecorder { // Previous global recorder that existed when this one was created. raw_ptr previous_ = nullptr; - // Global lock for internal synchronization. - // Note: Care must be taken to not read or write anything to persistent memory - // while holding this lock, as that could cause a file I/O stall. - static LazyInstance::Leaky lock_; - // Current global recorder. This recorder is used by static methods. When a // new global recorder is created by CreateTemporaryForTesting(), then the // previous global recorder is referenced by top_->previous_. diff --git a/naiveproxy/src/base/nix/mime_util_xdg.cc b/naiveproxy/src/base/nix/mime_util_xdg.cc index 4abd08fd45..d4691ac6f2 100644 --- a/naiveproxy/src/base/nix/mime_util_xdg.cc +++ b/naiveproxy/src/base/nix/mime_util_xdg.cc @@ -8,6 +8,7 @@ #include #include +#include "base/byte_count.h" #include "base/check.h" #include "base/containers/stack.h" #include "base/environment.h" @@ -30,7 +31,7 @@ namespace { // Ridiculously large size for a /usr/share/mime/mime.cache file. // Default file is about 100KB, allow up to 10MB. -constexpr size_t kMaxMimeTypesFileSize = 10 * 1024 * 1024; +constexpr ByteCount kMaxMimeTypesFileSize = MiB(10); // Maximum number of nodes to allow in reverse suffix tree. // Default file has ~3K nodes, allow up to 30K. constexpr size_t kMaxNodes = 30000; @@ -115,7 +116,8 @@ bool ParseMimeTypes(const FilePath& file_path, MimeTypeMap& out_mime_types) { // 0x100 = case-sensitive std::string buf; - if (!ReadFileToStringWithMaxSize(file_path, &buf, kMaxMimeTypesFileSize)) { + if (!ReadFileToStringWithMaxSize(file_path, &buf, + kMaxMimeTypesFileSize.InBytes())) { LOG(ERROR) << "Failed reading in mime.cache file: " << file_path; return false; } diff --git a/naiveproxy/src/base/numerics/byte_conversions.h b/naiveproxy/src/base/numerics/byte_conversions.h index cc8d6f8b35..440b507828 100644 --- a/naiveproxy/src/base/numerics/byte_conversions.h +++ b/naiveproxy/src/base/numerics/byte_conversions.h @@ -13,10 +13,9 @@ #include #include "base/numerics/basic_ops_impl.h" -#include "build/build_config.h" // Chromium only builds and runs on Little Endian machines. -static_assert(ARCH_CPU_LITTLE_ENDIAN); +static_assert(std::endian::native == std::endian::little); namespace base { diff --git a/naiveproxy/src/base/numerics/safe_conversions.h b/naiveproxy/src/base/numerics/safe_conversions.h index 7d57ca2ac8..1e08eb281e 100644 --- a/naiveproxy/src/base/numerics/safe_conversions.h +++ b/naiveproxy/src/base/numerics/safe_conversions.h @@ -14,7 +14,7 @@ #include "base/numerics/safe_conversions_impl.h" // IWYU pragma: export -#if defined(__ARMEL__) && !defined(__native_client__) +#if defined(__ARMEL__) #include "base/numerics/safe_conversions_arm_impl.h" // IWYU pragma: export #define BASE_HAS_OPTIMIZED_SAFE_CONVERSIONS (1) #else diff --git a/naiveproxy/src/base/numerics/safe_math_clang_gcc_impl.h b/naiveproxy/src/base/numerics/safe_math_clang_gcc_impl.h index daf7d889e9..ca97bf70d8 100644 --- a/naiveproxy/src/base/numerics/safe_math_clang_gcc_impl.h +++ b/naiveproxy/src/base/numerics/safe_math_clang_gcc_impl.h @@ -14,7 +14,7 @@ #include "base/numerics/safe_conversions.h" -#if !defined(__native_client__) && (defined(__ARMEL__) || defined(__arch64__)) +#if defined(__ARMEL__) || defined(__arch64__) #include "base/numerics/safe_math_arm_impl.h" // IWYU pragma: export #define BASE_HAS_ASSEMBLER_SAFE_MATH (1) #else diff --git a/naiveproxy/src/base/numerics/safe_math_shared_impl.h b/naiveproxy/src/base/numerics/safe_math_shared_impl.h index c0078d5741..68c3b872d2 100644 --- a/naiveproxy/src/base/numerics/safe_math_shared_impl.h +++ b/naiveproxy/src/base/numerics/safe_math_shared_impl.h @@ -11,21 +11,13 @@ #include #include "base/numerics/safe_conversions.h" -#include "build/build_config.h" #if defined(__asmjs__) || defined(__wasm__) // Optimized safe math instructions are incompatible with asmjs. #define BASE_HAS_OPTIMIZED_SAFE_MATH (0) -// Where available use builtin math overflow support on Clang and GCC. -#elif !defined(__native_client__) && \ - ((defined(__clang__) && \ - ((__clang_major__ > 3) || \ - (__clang_major__ == 3 && __clang_minor__ >= 4))) || \ - (defined(__GNUC__) && __GNUC__ >= 5)) +#else #include "base/numerics/safe_math_clang_gcc_impl.h" // IWYU pragma: export #define BASE_HAS_OPTIMIZED_SAFE_MATH (1) -#else -#define BASE_HAS_OPTIMIZED_SAFE_MATH (0) #endif namespace base { diff --git a/naiveproxy/src/base/observer_list.h b/naiveproxy/src/base/observer_list.h index bb0b408e97..ee0dc64dc8 100644 --- a/naiveproxy/src/base/observer_list.h +++ b/naiveproxy/src/base/observer_list.h @@ -55,12 +55,12 @@ // virtual void OnBar(MyWidget* w, int x, int y) = 0; // }; // -// void AddObserver(Observer* obs) { -// observers_.AddObserver(obs); +// void AddObserver(Observer* observer) { +// observers_.AddObserver(observer); // } // -// void RemoveObserver(Observer* obs) { -// observers_.RemoveObserver(obs); +// void RemoveObserver(Observer* observer) { +// observers_.RemoveObserver(observer); // } // // void NotifyFoo() { @@ -70,9 +70,9 @@ // void NotifyBar(int x, int y) { // // Use manual iteration when Notify() is not suitable, e.g. // // if passing different args to different observers is needed. -// for (Observer& obs : observers_) { -// gfx::Point local_point = GetLocalPoint(obs, x, y); -// obs.OnBar(this, local_point.x(), local_point.y()); +// for (Observer& observer : observers_) { +// gfx::Point local_point = GetLocalPoint(observer, x, y); +// observer.OnBar(this, local_point.x(), local_point.y()); // } // } // @@ -96,8 +96,8 @@ enum class ObserverListPolicy { EXISTING_ONLY, }; -// When check_empty is true, assert that the list is empty on destruction. -// When allow_reentrancy is false, iterating throught the list while already in +// When `check_empty` is true, assert that the list is empty on destruction. +// When `allow_reentrancy` is false, iterating through the list while already in // the iteration loop will result in DCHECK failure. // TODO(oshima): Change the default to non reentrant. https://crbug.com/812109 template (current_notification); task_runner->PostTask( current_notification->from_here, - BindOnce(&Self::NotifyWrapper, this, - // While `observer` may be dangling, we pass it and - // check it wasn't deallocated in NotifyWrapper() which can - // check `observers_` to verify presence (the owner of the - // observer is responsible for removing it from that list - // before deallocation). - UnsafeDangling(observer), - NotificationData(this, observer_id, - current_notification->from_here, - notification_data->method))); + base::BindOnce(&Self::NotifyWrapper, this, + // While `observer` may be dangling, we pass it and + // check it wasn't deallocated in NotifyWrapper() + // which can check `observers_` to verify presence + // (the owner of the observer is responsible for + // removing it from that list before deallocation). + UnsafeDangling(observer), + NotificationData(this, observer_id, + current_notification->from_here, + notification_data->method))); } } @@ -231,22 +231,22 @@ class ObserverListThreadSafe : public internal::ObserverListThreadSafeBase { template void Notify(const Location& from_here, Method m, Params&&... params) { RepeatingCallback method = - BindRepeating(&Dispatcher::Run, m, - std::forward(params)...); + base::BindRepeating(&Dispatcher::Run, m, + std::forward(params)...); AutoLock lock(lock_); for (const auto& observer : observers_) { observer.second.task_runner->PostTask( from_here, - BindOnce(&Self::NotifyWrapper, this, - // While `observer.first` may be dangling, we pass it and - // check it wasn't deallocated in NotifyWrapper() which can - // check `observers_` to verify presence (the owner of the - // observer is responsible for removing it from that list - // before deallocation). - UnsafeDangling(observer.first), - NotificationData(this, observer.second.observer_id, - from_here, method))); + base::BindOnce(&Self::NotifyWrapper, this, + // While `observer.first` may be dangling, we pass it + // and check it wasn't deallocated in NotifyWrapper() + // which can check `observers_` to verify presence (the + // owner of the observer is responsible for removing it + // from that list before deallocation). + UnsafeDangling(observer.first), + NotificationData(this, observer.second.observer_id, + from_here, method))); } } diff --git a/naiveproxy/src/base/path_service.cc b/naiveproxy/src/base/path_service.cc index 43d4401d67..c6a1855428 100644 --- a/naiveproxy/src/base/path_service.cc +++ b/naiveproxy/src/base/path_service.cc @@ -310,6 +310,22 @@ bool PathService::OverrideAndCreateIfNeeded(int key, return true; } +// static +bool PathService::OverrideWithoutCheckForTesting(int key, + const FilePath& path) { + PathData* path_data = GetPathData(); + DCHECK(path_data); + + AutoLock scoped_lock(path_data->lock); + + // Clear the cache now. Some of its entries could have depended + // on the value we are overriding, and are now out of sync with reality. + path_data->cache.clear(); + path_data->overrides[key] = path; + + return true; +} + // static bool PathService::RemoveOverrideForTests(int key) { PathData* path_data = GetPathData(); diff --git a/naiveproxy/src/base/path_service.h b/naiveproxy/src/base/path_service.h index 7767022a05..5a397ad2d3 100644 --- a/naiveproxy/src/base/path_service.h +++ b/naiveproxy/src/base/path_service.h @@ -57,6 +57,10 @@ class BASE_EXPORT PathService { bool is_absolute, bool create); + // This function does the same as `PathService::Override()` but it skips the + // checks for testing the invalid cases. + static bool OverrideWithoutCheckForTesting(int key, const FilePath& path); + // Returns whether an override is present for a special directory or file. static bool IsOverriddenForTesting(int key); diff --git a/naiveproxy/src/base/pickle.h b/naiveproxy/src/base/pickle.h index 2649abef73..f867de5de6 100644 --- a/naiveproxy/src/base/pickle.h +++ b/naiveproxy/src/base/pickle.h @@ -319,7 +319,7 @@ class BASE_EXPORT Pickle { // The protected constructor. Note that this creates a Pickle that does not // own its own data. enum UnownedData { kUnownedData }; - explicit Pickle(UnownedData, span data); + Pickle(UnownedData, span data); // Returns size of the header, which can have default value, set by user or // calculated by passed raw data. diff --git a/naiveproxy/src/base/posix/safe_strerror.cc b/naiveproxy/src/base/posix/safe_strerror.cc index 12c3dbc033..66a93f2b8c 100644 --- a/naiveproxy/src/base/posix/safe_strerror.cc +++ b/naiveproxy/src/base/posix/safe_strerror.cc @@ -13,7 +13,7 @@ namespace base { -#if defined(__GLIBC__) || BUILDFLAG(IS_NACL) +#if defined(__GLIBC__) #define USE_HISTORICAL_STRERROR_R 1 // Post-L versions of bionic define the GNU-specific strerror_r if _GNU_SOURCE // is defined, but the symbol is renamed to __gnu_strerror_r which only exists diff --git a/naiveproxy/src/base/power_monitor/cpu_frequency_utils.cc b/naiveproxy/src/base/power_monitor/cpu_frequency_utils.cc index 4885ccba2f..c8db95bc03 100644 --- a/naiveproxy/src/base/power_monitor/cpu_frequency_utils.cc +++ b/naiveproxy/src/base/power_monitor/cpu_frequency_utils.cc @@ -45,7 +45,7 @@ double EstimateCpuFrequency() { std::optional EstimateCpuThroughput() { #if defined(ARCH_CPU_X86_FAMILY) - TRACE_EVENT0("power", "EstimateCpuThroughput"); + TRACE_EVENT("base.power", "EstimateCpuThroughput"); #if BUILDFLAG(IS_WIN) DWORD start_processor_number = GetCurrentProcessorNumber(); diff --git a/naiveproxy/src/base/power_monitor/power_monitor.cc b/naiveproxy/src/base/power_monitor/power_monitor.cc index 68a7441443..c5e7efb627 100644 --- a/naiveproxy/src/base/power_monitor/power_monitor.cc +++ b/naiveproxy/src/base/power_monitor/power_monitor.cc @@ -14,10 +14,31 @@ #include "power_observer.h" namespace base { +namespace { -void PowerMonitor::Initialize(std::unique_ptr source) { +perfetto::StaticString BatteryStatusToString( + PowerStateObserver::BatteryPowerStatus status) { + switch (status) { + case PowerStateObserver::BatteryPowerStatus::kBatteryPower: + return "BatteryPower"; + case PowerStateObserver::BatteryPowerStatus::kExternalPower: + return "ExternalPower"; + case PowerStateObserver::BatteryPowerStatus::kUnknown: + return "Unknown"; + } + NOTREACHED(); +} + +} // namespace + +void PowerMonitor::Initialize(std::unique_ptr source, + bool emit_global_event) { DCHECK(!IsInitialized()); source_ = std::move(source); + emit_global_event_ = emit_global_event; + if (emit_global_event_) { + TrackEvent::AddSessionObserver(this); + } // When a power source is associated with the power monitor, ensure the // initial state is propagated to observers, if needed. @@ -156,13 +177,12 @@ void PowerMonitor::NotifyPowerStateChange( ? "On" : "Off") << " battery"; - TRACE_EVENT_INSTANT( - "power", - battery_power_status == - PowerStateObserver::BatteryPowerStatus::kBatteryPower - ? perfetto::StaticString("PowerMonitor::BatteryPower") - : perfetto::StaticString("PowerMonitor::ExternalPower"), - process_track_); + if (emit_global_event_) { + TRACE_EVENT_END("base.power", battery_power_track_); + TRACE_EVENT_BEGIN("base.power", + BatteryStatusToString(battery_power_status), + battery_power_track_); + } } AutoLock auto_lock(battery_power_status_lock_); @@ -176,11 +196,18 @@ void PowerMonitor::NotifyPowerStateChange( void PowerMonitor::NotifySuspend() { DCHECK(IsInitialized()); - TRACE_EVENT_INSTANT("power", "PowerMonitor::NotifySuspend", process_track_); DVLOG(1) << "Power Suspending"; + if (emit_global_event_) { + TRACE_EVENT_INSTANT("base.power", "PowerMonitor::NotifySuspend", + suspend_track_); + } AutoLock auto_lock(is_system_suspended_lock_); if (!is_system_suspended_) { + if (emit_global_event_) { + TRACE_EVENT_BEGIN("base.power", "PowerMonitor::Suspended", + suspend_track_); + } is_system_suspended_ = true; last_system_resume_time_ = TimeTicks::Max(); power_suspend_observers_->Notify(FROM_HERE, @@ -190,13 +217,19 @@ void PowerMonitor::NotifySuspend() { void PowerMonitor::NotifyResume() { DCHECK(IsInitialized()); - TRACE_EVENT_INSTANT("power", "PowerMonitor::NotifyResume", process_track_); DVLOG(1) << "Power Resuming"; + if (emit_global_event_) { + TRACE_EVENT_INSTANT("base.power", "PowerMonitor::NotifyResume", + suspend_track_); + } TimeTicks resume_time = TimeTicks::Now(); AutoLock auto_lock(is_system_suspended_lock_); if (is_system_suspended_) { + if (emit_global_event_) { + TRACE_EVENT_END("base.power", suspend_track_); + } is_system_suspended_ = false; last_system_resume_time_ = resume_time; power_suspend_observers_->Notify(FROM_HERE, @@ -236,7 +269,8 @@ PowerMonitor* PowerMonitor::GetInstance() { } PowerMonitor::PowerMonitor() - : process_track_("PowerMonitor"), + : suspend_track_("SuspendStatus", 0, perfetto::Track()), + battery_power_track_("BatteryPowerStatus", 0, perfetto::Track()), power_state_observers_( base::MakeRefCounted>()), power_suspend_observers_( @@ -247,4 +281,25 @@ PowerMonitor::PowerMonitor() PowerMonitor::~PowerMonitor() = default; +void PowerMonitor::OnStart(const perfetto::DataSourceBase::StartArgs&) { + if (!emit_global_event_) { + return; + } + { + AutoLock auto_lock(is_system_suspended_lock_); + if (is_system_suspended_) { + TRACE_EVENT_END("base.power", suspend_track_); + TRACE_EVENT_BEGIN("base.power", "PowerMonitor::Suspended", + suspend_track_); + } + } + { + AutoLock auto_lock(battery_power_status_lock_); + TRACE_EVENT_END("base.power", battery_power_track_); + TRACE_EVENT_BEGIN("base.power", + BatteryStatusToString(battery_power_status_), + battery_power_track_); + } +} + } // namespace base diff --git a/naiveproxy/src/base/power_monitor/power_monitor.h b/naiveproxy/src/base/power_monitor/power_monitor.h index c8f7efddfa..14c9d7417e 100644 --- a/naiveproxy/src/base/power_monitor/power_monitor.h +++ b/naiveproxy/src/base/power_monitor/power_monitor.h @@ -14,6 +14,7 @@ #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" +#include "third_party/perfetto/include/perfetto/tracing/internal/track_event_internal.h" namespace base { @@ -25,15 +26,17 @@ class PowerMonitorSource; // initialization happens before any other methods are invoked, including // IsInitialized(). IsInitialized() exists only as a convenience for detection // of test contexts where the PowerMonitor global is never created. -class BASE_EXPORT PowerMonitor { +class BASE_EXPORT PowerMonitor : public perfetto::TrackEventSessionObserver { public: static PowerMonitor* GetInstance(); - // Initializes global PowerMonitor state. Takes ownership of |source|, which + // Initializes global PowerMonitor state. Takes ownership of `source`, which // will be leaked on process teardown. May only be called once. Not threadsafe // - no other PowerMonitor methods may be called on any thread while calling - // Initialize(). |source| must not be nullptr. - void Initialize(std::unique_ptr source); + // Initialize(). `source` must not be nullptr. Global trace events are emitted + // iff `emit_global_event=true`; this is only set in the browser process. + void Initialize(std::unique_ptr source, + bool emit_global_event = false); PowerMonitor(const PowerMonitor&) = delete; PowerMonitor& operator=(const PowerMonitor&) = delete; @@ -107,7 +110,10 @@ class BASE_EXPORT PowerMonitor { friend class base::NoDestructor; PowerMonitor(); - ~PowerMonitor(); + ~PowerMonitor() override; + + // perfetto::TrackEventSessionObserver overrides: + void OnStart(const perfetto::DataSourceBase::StartArgs&) override; const PowerMonitorSource* Source() const; @@ -130,7 +136,9 @@ class BASE_EXPORT PowerMonitor { mutable Lock battery_power_status_lock_; - perfetto::NamedTrack process_track_; + bool emit_global_event_ = false; + const perfetto::NamedTrack suspend_track_; + const perfetto::NamedTrack battery_power_track_; PowerThermalObserver::DeviceThermalState power_thermal_state_ GUARDED_BY(power_thermal_state_lock_) = PowerThermalObserver::DeviceThermalState::kUnknown; diff --git a/naiveproxy/src/base/power_monitor/power_monitor_device_source_ios.mm b/naiveproxy/src/base/power_monitor/power_monitor_device_source_ios.mm index 87bad4a660..c9fab879cd 100644 --- a/naiveproxy/src/base/power_monitor/power_monitor_device_source_ios.mm +++ b/naiveproxy/src/base/power_monitor/power_monitor_device_source_ios.mm @@ -12,7 +12,7 @@ namespace base { PowerStateObserver::BatteryPowerStatus PowerMonitorDeviceSource::GetBatteryPowerStatus() const { -#if TARGET_IPHONE_SIMULATOR +#if TARGET_OS_SIMULATOR return PowerStateObserver::BatteryPowerStatus::kExternalPower; #else UIDevice* currentDevice = [UIDevice currentDevice]; diff --git a/naiveproxy/src/base/process/launch.h b/naiveproxy/src/base/process/launch.h index 8f08514045..a601e7c93f 100644 --- a/naiveproxy/src/base/process/launch.h +++ b/naiveproxy/src/base/process/launch.h @@ -39,10 +39,6 @@ #include "base/posix/file_descriptor_shuffle.h" #endif -#if BUILDFLAG(IS_ANDROID) -#include "base/android/binder.h" -#endif - #if BUILDFLAG(IS_MAC) #include "base/mac/process_requirement.h" #endif @@ -227,13 +223,6 @@ 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 @@ -509,6 +498,11 @@ BASE_EXPORT bool GetAppOutput(const std::vector& argv, // stderr. BASE_EXPORT bool GetAppOutputAndError(const std::vector& argv, std::string* output); + +// Like the POSIX-specific GetAppOutput above, but also includes the exit code. +BASE_EXPORT bool GetAppOutputWithExitCode(const std::vector& argv, + std::string* output, + int* exit_code); #endif // BUILDFLAG(IS_WIN) // If supported on the platform, and the user has sufficent rights, increase diff --git a/naiveproxy/src/base/process/launch_fuchsia.cc b/naiveproxy/src/base/process/launch_fuchsia.cc index 79ee18b5a0..3a20d8745f 100644 --- a/naiveproxy/src/base/process/launch_fuchsia.cc +++ b/naiveproxy/src/base/process/launch_fuchsia.cc @@ -303,6 +303,12 @@ bool GetAppOutputWithExitCode(const CommandLine& cl, return GetAppOutputInternal(cl, false, output, exit_code); } +bool GetAppOutputWithExitCode(const std::vector& argv, + std::string* output, + int* exit_code) { + return GetAppOutputWithExitCode(CommandLine(argv), output, exit_code); +} + void RaiseProcessToHighPriority() { // Fuchsia doesn't provide an API to change process priority. } diff --git a/naiveproxy/src/base/process/launch_mac.cc b/naiveproxy/src/base/process/launch_mac.cc index 116f4b86b8..b63d58da98 100644 --- a/naiveproxy/src/base/process/launch_mac.cc +++ b/naiveproxy/src/base/process/launch_mac.cc @@ -2,11 +2,74 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "build/build_config.h" + +#if BUILDFLAG(IS_IOS_TVOS) +#include + +#if TARGET_OS_SIMULATOR +// On tvOS, all posix_spawn*() functions except for posix_spawnp() are marked +// unavailable, but the symbols and the implementation are present (but +// unusable on tvOS device builds targeted for distribution due to App Store +// restrictions on the use of multiple processes). posix_spawnp() is required +// for the test launcher code to be able to launch multiple processes in the +// simulator, but it is not fully usable without the functions marked +// unavailable. +// +// Work around it by changing the availability annotation of the functions used +// in this file before including . This is done as early as possible +// (i.e. before even including base/process/launch.h) to prevent from +// being indirectly included before we are able to declare a different +// availability. +// +// Note: is included as a system header together with the other +// regular headers outside this block. The inclusion as a system header turns +// off the availability warning that would normally be thrown by LLVM when the +// header's function declarations with different availability annotations were +// added. See the discussion in +// https://chromium-review.googlesource.com/c/chromium/src/+/6687371/comment/6baf4b4c_8a60d02a/ +#include +#include +#include + +extern "C" { + +using posix_spawnattr_t = void*; +using posix_spawn_file_actions_t = void*; + +int posix_spawnattr_init(posix_spawnattr_t*) __API_AVAILABLE(tvos(1.0)); +int posix_spawnattr_destroy(posix_spawnattr_t*) __API_AVAILABLE(tvos(1.0)); +int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t*) + __API_AVAILABLE(tvos(1.0)); +int posix_spawn_file_actions_init(posix_spawn_file_actions_t*) + __API_AVAILABLE(tvos(1.0)); +int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t*, int, int) + __API_AVAILABLE(tvos(1.0)); +int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t*, + int, + const char*, + int, + mode_t) __API_AVAILABLE(tvos(1.0)); +int posix_spawn_file_actions_addinherit_np(posix_spawn_file_actions_t*, int) + __API_AVAILABLE(tvos(1.0)); +int posix_spawnattr_setpgroup(posix_spawnattr_t*, pid_t) + __API_AVAILABLE(tvos(1.0)); +int posix_spawnattr_setflags(posix_spawnattr_t*, short) + __API_AVAILABLE(tvos(1.0)); +int posix_spawnattr_set_csm_np(const posix_spawnattr_t*, uint32_t) + __API_AVAILABLE(tvos(1.0)); + +} // extern "C" + +#else +#error This file is not supported on tvOS device builds. +#endif // TARGET_OS_SIMULATOR +#endif // BUILDFLAG(IS_IOS_TVOS) + #include "base/process/launch.h" #include #include -#include #include #include #include @@ -295,7 +358,13 @@ Process LaunchProcess(const std::vector& argv, pid_t pid; { const bool has_mach_ports_for_rendezvous = - !options.mach_ports_for_rendezvous.empty(); +#if BUILDFLAG(IS_IOS_TVOS) + false +#else + !options.mach_ports_for_rendezvous.empty() +#endif // BUILDFLAG(IS_IOS_TVOS) + ; + #if BUILDFLAG(IS_IOS) // This code is only used for the iOS simulator to launch tests. We do not // support setting MachPorts on launch. You should look at @@ -380,11 +449,7 @@ bool GetAppOutputAndError(const CommandLine& cl, std::string* output) { bool GetAppOutputWithExitCode(const CommandLine& cl, std::string* output, int* exit_code) { - GetAppOutputOptions options; - options.output = output; - bool rv = GetAppOutputInternal(cl.argv(), &options); - *exit_code = options.exit_code; - return rv; + return GetAppOutputWithExitCode(cl.argv(), output, exit_code); } bool GetAppOutput(const std::vector& argv, std::string* output) { @@ -403,6 +468,16 @@ bool GetAppOutputAndError(const std::vector& argv, options.exit_code == EXIT_SUCCESS; } +bool GetAppOutputWithExitCode(const std::vector& argv, + std::string* output, + int* exit_code) { + GetAppOutputOptions options; + options.output = output; + bool rv = GetAppOutputInternal(argv, &options); + *exit_code = options.exit_code; + return rv; +} + void RaiseProcessToHighPriority() { // Historically this has not been implemented on POSIX and macOS. This could // influence the Mach task policy in the future. diff --git a/naiveproxy/src/base/process/launch_posix.cc b/naiveproxy/src/base/process/launch_posix.cc index 7b1d5f9c9b..4f9ffed9d9 100644 --- a/naiveproxy/src/base/process/launch_posix.cc +++ b/naiveproxy/src/base/process/launch_posix.cc @@ -716,6 +716,13 @@ bool GetAppOutputWithExitCode(const CommandLine& cl, exit_code); } +bool GetAppOutputWithExitCode(const std::vector& argv, + std::string* output, + int* exit_code) { + // Run |execve()| with the current environment. + return GetAppOutputInternal(argv, nullptr, false, output, true, exit_code); +} + #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_AIX) namespace { diff --git a/naiveproxy/src/base/process/launch_unittest_win.cc b/naiveproxy/src/base/process/launch_unittest_win.cc index c4d3d72d2c..8a07a00442 100644 --- a/naiveproxy/src/base/process/launch_unittest_win.cc +++ b/naiveproxy/src/base/process/launch_unittest_win.cc @@ -62,7 +62,7 @@ TEST(LaunchWinTest, GetAppOutputWithExitCodeAndTimeout_SuccessOutput) { TEST(LaunchWinTest, GetAppOutputWithExitCodeAndTimeout_TimeoutOutput) { CommandLine cl(FilePath(FILE_PATH_LITERAL("cmd"))); cl.AppendArg("/c"); - cl.AppendArg("echo hello && start /wait /min timeout 5"); + cl.AppendArg("echo hello && start /wait /min %windir%\\System32\\timeout 5"); std::string partial_outputs; std::string output; int exit_code = 0; diff --git a/naiveproxy/src/base/process/process_metrics.cc b/naiveproxy/src/base/process/process_metrics.cc index 9caf42004a..f885e56399 100644 --- a/naiveproxy/src/base/process/process_metrics.cc +++ b/naiveproxy/src/base/process/process_metrics.cc @@ -69,27 +69,6 @@ SystemMetrics SystemMetrics::Sample() { return system_metrics; } -Value::Dict SystemMetrics::ToDict() const { - Value::Dict res; - - res.Set("committed_memory", static_cast(committed_memory_)); -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) - Value::Dict meminfo = memory_info_.ToDict(); - meminfo.Merge(vmstat_info_.ToDict()); - res.Set("meminfo", std::move(meminfo)); - res.Set("diskinfo", disk_info_.ToDict()); -#endif -#if BUILDFLAG(IS_CHROMEOS) - res.Set("swapinfo", swap_info_.ToDict()); - res.Set("gpu_meminfo", gpu_memory_info_.ToDict()); -#endif -#if BUILDFLAG(IS_WIN) - res.Set("perfinfo", performance_.ToDict()); -#endif - - return res; -} - ProcessMetrics::~ProcessMetrics() = default; std::unique_ptr ProcessMetrics::CreateCurrentProcessMetrics() { diff --git a/naiveproxy/src/base/process/process_metrics.h b/naiveproxy/src/base/process/process_metrics.h index d996d8b45b..4ade83b7ed 100644 --- a/naiveproxy/src/base/process/process_metrics.h +++ b/naiveproxy/src/base/process/process_metrics.h @@ -326,9 +326,6 @@ struct BASE_EXPORT SystemMemoryInfoKB { SystemMemoryInfoKB(const SystemMemoryInfoKB& other); SystemMemoryInfoKB& operator=(const SystemMemoryInfoKB& other); - // Serializes the platform specific fields to value. - Value::Dict ToDict() const; - int total = 0; #if !BUILDFLAG(IS_WIN) @@ -426,9 +423,6 @@ GetSystemCommitChargeFromMeminfo(const SystemMemoryInfoKB& meminfo); // Data from /proc/vmstat. struct BASE_EXPORT VmStatInfo { - // Serializes the platform specific fields to value. - Value::Dict ToDict() const; - uint64_t pswpin = 0; uint64_t pswpout = 0; uint64_t pgmajfault = 0; @@ -450,9 +444,6 @@ struct BASE_EXPORT SystemDiskInfo { SystemDiskInfo(const SystemDiskInfo&); SystemDiskInfo& operator=(const SystemDiskInfo&); - // Serializes the platform specific fields to value. - Value::Dict ToDict() const; - uint64_t reads = 0; uint64_t reads_merged = 0; uint64_t sectors_read = 0; @@ -491,9 +482,6 @@ struct BASE_EXPORT SwapInfo { orig_data_size(0), mem_used_total(0) {} - // Serializes the platform specific fields to value. - Value::Dict ToDict() const; - uint64_t num_reads = 0; uint64_t num_writes = 0; uint64_t compr_data_size = 0; @@ -521,9 +509,6 @@ BASE_EXPORT bool GetSwapInfo(SwapInfo* swap_info); // Data about GPU memory usage. These fields will be -1 if not supported. struct BASE_EXPORT GraphicsMemoryInfoKB { - // Serializes the platform specific fields to value. - Value::Dict ToDict() const; - int gpu_objects = -1; int64_t gpu_memory_size = -1; }; @@ -541,9 +526,6 @@ struct BASE_EXPORT SystemPerformanceInfo { SystemPerformanceInfo(const SystemPerformanceInfo& other); SystemPerformanceInfo& operator=(const SystemPerformanceInfo& other); - // Serializes the platform specific fields to value. - Value::Dict ToDict() const; - // Total idle time of all processes in the system (units of 100 ns). uint64_t idle_time = 0; // Number of bytes read. @@ -584,9 +566,6 @@ class BASE_EXPORT SystemMetrics { static SystemMetrics Sample(); - // Serializes the system metrics to value. - Value::Dict ToDict() const; - private: FRIEND_TEST_ALL_PREFIXES(SystemMetricsTest, SystemMetrics); diff --git a/naiveproxy/src/base/process/process_metrics_linux.cc b/naiveproxy/src/base/process/process_metrics_linux.cc index d327b12f7a..c1fe2c2e11 100644 --- a/naiveproxy/src/base/process/process_metrics_linux.cc +++ b/naiveproxy/src/base/process/process_metrics_linux.cc @@ -379,30 +379,6 @@ const size_t kDiskWeightedIOTime = 13; } // namespace -Value::Dict SystemMemoryInfoKB::ToDict() const { - Value::Dict res; - res.Set("total", total); - res.Set("free", free); - res.Set("available", available); - res.Set("buffers", buffers); - res.Set("cached", cached); - res.Set("active_anon", active_anon); - res.Set("inactive_anon", inactive_anon); - res.Set("active_file", active_file); - res.Set("inactive_file", inactive_file); - res.Set("swap_total", swap_total); - res.Set("swap_free", swap_free); - res.Set("swap_used", swap_total - swap_free); - res.Set("dirty", dirty); - res.Set("reclaimable", reclaimable); -#if BUILDFLAG(IS_CHROMEOS) - res.Set("shmem", shmem); - res.Set("slab", slab); -#endif - - return res; -} - bool ParseProcMeminfo(std::string_view meminfo_data, SystemMemoryInfoKB* meminfo) { // The format of /proc/meminfo is: @@ -553,16 +529,6 @@ bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) { return true; } -Value::Dict VmStatInfo::ToDict() const { - Value::Dict res; - // TODO(crbug.com/40228085): Make base::Value able to hold uint64_t and remove - // casts below. - res.Set("pswpin", static_cast(pswpin)); - res.Set("pswpout", static_cast(pswpout)); - res.Set("pgmajfault", static_cast(pgmajfault)); - return res; -} - bool GetVmStatInfo(VmStatInfo* vmstat) { // Synchronously reading files in /proc is safe. ScopedAllowBlockingForProcessMetrics allow_blocking; @@ -598,26 +564,6 @@ SystemDiskInfo::SystemDiskInfo(const SystemDiskInfo&) = default; SystemDiskInfo& SystemDiskInfo::operator=(const SystemDiskInfo&) = default; -Value::Dict SystemDiskInfo::ToDict() const { - Value::Dict res; - - // Write out uint64_t variables as doubles. - // Note: this may discard some precision, but for JS there's no other option. - res.Set("reads", static_cast(reads)); - res.Set("reads_merged", static_cast(reads_merged)); - res.Set("sectors_read", static_cast(sectors_read)); - res.Set("read_time", static_cast(read_time)); - res.Set("writes", static_cast(writes)); - res.Set("writes_merged", static_cast(writes_merged)); - res.Set("sectors_written", static_cast(sectors_written)); - res.Set("write_time", static_cast(write_time)); - res.Set("io", static_cast(io)); - res.Set("io_time", static_cast(io_time)); - res.Set("weighted_io_time", static_cast(weighted_io_time)); - - return res; -} - bool IsValidDiskName(std::string_view candidate) { if (candidate.length() < 3) { return false; @@ -732,32 +678,6 @@ TimeDelta GetUserCpuTimeSinceBoot() { } #if BUILDFLAG(IS_CHROMEOS) -Value::Dict SwapInfo::ToDict() const { - Value::Dict res; - - // Write out uint64_t variables as doubles. - // Note: this may discard some precision, but for JS there's no other option. - res.Set("num_reads", static_cast(num_reads)); - res.Set("num_writes", static_cast(num_writes)); - res.Set("orig_data_size", static_cast(orig_data_size)); - res.Set("compr_data_size", static_cast(compr_data_size)); - res.Set("mem_used_total", static_cast(mem_used_total)); - double ratio = compr_data_size ? static_cast(orig_data_size) / - static_cast(compr_data_size) - : 0; - res.Set("compression_ratio", ratio); - - return res; -} - -Value::Dict GraphicsMemoryInfoKB::ToDict() const { - Value::Dict res; - - res.Set("gpu_objects", gpu_objects); - res.Set("gpu_memory_size", static_cast(gpu_memory_size)); - - return res; -} bool ParseZramMmStat(std::string_view mm_stat_data, SwapInfo* swap_info) { // There are 7 columns in /sys/block/zram0/mm_stat, diff --git a/naiveproxy/src/base/process/process_metrics_win.cc b/naiveproxy/src/base/process/process_metrics_win.cc index 4d2ba62b1f..0cf0300a2c 100644 --- a/naiveproxy/src/base/process/process_metrics_win.cc +++ b/naiveproxy/src/base/process/process_metrics_win.cc @@ -279,31 +279,6 @@ SystemPerformanceInfo::SystemPerformanceInfo( SystemPerformanceInfo& SystemPerformanceInfo::operator=( const SystemPerformanceInfo& other) = default; -Value::Dict SystemPerformanceInfo::ToDict() const { - Value::Dict result; - - // Write out uint64_t variables as doubles. - // Note: this may discard some precision, but for JS there's no other option. - result.Set("idle_time", strict_cast(idle_time)); - result.Set("read_transfer_count", strict_cast(read_transfer_count)); - result.Set("write_transfer_count", strict_cast(write_transfer_count)); - result.Set("other_transfer_count", strict_cast(other_transfer_count)); - result.Set("read_operation_count", strict_cast(read_operation_count)); - result.Set("write_operation_count", - strict_cast(write_operation_count)); - result.Set("other_operation_count", - strict_cast(other_operation_count)); - result.Set("pagefile_pages_written", - strict_cast(pagefile_pages_written)); - result.Set("pagefile_pages_write_ios", - strict_cast(pagefile_pages_write_ios)); - result.Set("available_pages", strict_cast(available_pages)); - result.Set("pages_read", strict_cast(pages_read)); - result.Set("page_read_ios", strict_cast(page_read_ios)); - - return result; -} - // Retrieves performance counters from the operating system. // Fills in the provided |info| structure. Returns true on success. BASE_EXPORT bool GetSystemPerformanceInfo(SystemPerformanceInfo* info) { diff --git a/naiveproxy/src/base/process/set_process_title.cc b/naiveproxy/src/base/process/set_process_title.cc index b638952395..aacd4a841f 100644 --- a/naiveproxy/src/base/process/set_process_title.cc +++ b/naiveproxy/src/base/process/set_process_title.cc @@ -44,7 +44,7 @@ namespace base { // TODO(jrg): Find out if setproctitle or equivalent is available on Android. #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_SOLARIS) && \ - !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_FUCHSIA) && !BUILDFLAG(IS_NACL) + !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_FUCHSIA) void SetProcessTitleFromCommandLine(const char** main_argv) { // Build a single string which consists of all the arguments separated diff --git a/naiveproxy/src/base/profiler/chrome_unwinder_android_32.cc b/naiveproxy/src/base/profiler/chrome_unwinder_android_32.cc index b651dccb5f..fdb7c31f66 100644 --- a/naiveproxy/src/base/profiler/chrome_unwinder_android_32.cc +++ b/naiveproxy/src/base/profiler/chrome_unwinder_android_32.cc @@ -2,16 +2,12 @@ // 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/profiler/chrome_unwinder_android_32.h" #include #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/memory/aligned_memory.h" #include "base/notreached.h" #include "base/numerics/checked_math.h" @@ -34,7 +30,8 @@ uintptr_t* GetRegisterPointer(RegisterContext* context, &RegisterContext::arm_ip, &RegisterContext::arm_sp, &RegisterContext::arm_lr, &RegisterContext::arm_pc, }; - return reinterpret_cast(&(context->*registers[register_index])); + return reinterpret_cast( + &(context->*UNSAFE_TODO(registers[register_index]))); } // Pops the value on the top of stack out and assign it to target register. @@ -64,7 +61,7 @@ uintptr_t DecodeULEB128(const uint8_t*& bytes) { DCHECK_LE(shift, sizeof(uintptr_t) * 8); // ULEB128 must not overflow. value += (*bytes & 0x7fu) << shift; shift += 7; - } while (*bytes++ & 0x80); + } while (*UNSAFE_TODO(bytes++) & 0x80); return value; } @@ -189,7 +186,8 @@ UnwindInstructionResult ExecuteUnwindInstruction( if (GetTopBits(*instruction, 2) == 0b00) { // 00xxxxxx // vsp = vsp + (xxxxxx << 2) + 4. Covers range 0x04-0x100 inclusive. - const uintptr_t offset = ((*instruction++ & 0b00111111u) << 2) + 4; + const uintptr_t offset = + ((*UNSAFE_TODO(instruction++) & 0b00111111u) << 2) + 4; const auto new_sp = CheckedNumeric(RegisterContextStackPointer(thread_context)) + @@ -200,7 +198,8 @@ UnwindInstructionResult ExecuteUnwindInstruction( } else if (GetTopBits(*instruction, 2) == 0b01) { // 01xxxxxx // vsp = vsp - (xxxxxx << 2) - 4. Covers range 0x04-0x100 inclusive. - const uintptr_t offset = ((*instruction++ & 0b00111111u) << 2) + 4; + const uintptr_t offset = + ((*UNSAFE_TODO(instruction++) & 0b00111111u) << 2) + 4; const auto new_sp = CheckedNumeric(RegisterContextStackPointer(thread_context)) - offset; @@ -210,7 +209,7 @@ UnwindInstructionResult ExecuteUnwindInstruction( } else if (GetTopBits(*instruction, 4) == 0b1001) { // 1001nnnn (nnnn != 13,15) // Set vsp = r[nnnn]. - const uint8_t register_index = *instruction++ & 0b00001111; + const uint8_t register_index = *UNSAFE_TODO(instruction++) & 0b00001111; DCHECK_NE(register_index, 13); // Must not set sp to sp. DCHECK_NE(register_index, 15); // Must not set sp to pc. // Note: We shouldn't have cases that are setting caller-saved registers @@ -222,7 +221,8 @@ UnwindInstructionResult ExecuteUnwindInstruction( } else if (GetTopBits(*instruction, 5) == 0b10101) { // 10101nnn // Pop r4-r[4+nnn], r14 - const uint8_t max_register_index = (*instruction++ & 0b00000111u) + 4; + const uint8_t max_register_index = + (*UNSAFE_TODO(instruction++) & 0b00000111u) + 4; for (uint8_t n = 4; n <= max_register_index; n++) { if (!PopRegister(thread_context, n)) { return UnwindInstructionResult::kAborted; @@ -231,15 +231,16 @@ UnwindInstructionResult ExecuteUnwindInstruction( if (!PopRegister(thread_context, 14)) { return UnwindInstructionResult::kAborted; } - } else if (*instruction == 0b10000000 && *(instruction + 1) == 0) { + } else if (*instruction == 0b10000000 && + *(UNSAFE_TODO(instruction + 1)) == 0) { // 10000000 00000000 // Refuse to unwind. - instruction += 2; + UNSAFE_TODO(instruction += 2); return UnwindInstructionResult::kAborted; } else if (GetTopBits(*instruction, 4) == 0b1000) { const uint32_t register_bitmask = - ((*instruction & 0xfu) << 8) + *(instruction + 1); - instruction += 2; + ((*instruction & 0xfu) << 8) + *(UNSAFE_TODO(instruction + 1)); + UNSAFE_TODO(instruction += 2); // 1000iiii iiiiiiii // Pop up to 12 integer registers under masks {r15-r12}, {r11-r4} for (uint8_t register_index = 4; register_index < 16; register_index++) { @@ -258,7 +259,7 @@ UnwindInstructionResult ExecuteUnwindInstruction( // indicates that no further instructions are to be processed for this // frame. - instruction++; + UNSAFE_TODO(instruction++); // Only copy lr to pc when pc is not updated by other instructions before. if (!pc_was_updated) { thread_context->arm_pc = thread_context->arm_lr; @@ -269,7 +270,7 @@ UnwindInstructionResult ExecuteUnwindInstruction( // 10110010 uleb128 // vsp = vsp + 0x204 + (uleb128 << 2) // (for vsp increments of 0x104-0x200, use 00xxxxxx twice) - instruction++; + UNSAFE_TODO(instruction++); const auto new_sp = CheckedNumeric(RegisterContextStackPointer(thread_context)) + (CheckedNumeric(DecodeULEB128(instruction)) << 2) + 0x204; diff --git a/naiveproxy/src/base/profiler/metadata_recorder.h b/naiveproxy/src/base/profiler/metadata_recorder.h index 57503d35af..688adc660d 100644 --- a/naiveproxy/src/base/profiler/metadata_recorder.h +++ b/naiveproxy/src/base/profiler/metadata_recorder.h @@ -194,8 +194,8 @@ class BASE_EXPORT MetadataRecorder { public: // Acquires an exclusive read lock on the metadata recorder which is held // until the object is destroyed. - explicit MetadataProvider(MetadataRecorder* metadata_recorder, - PlatformThreadId thread_id) + MetadataProvider(MetadataRecorder* metadata_recorder, + PlatformThreadId thread_id) EXCLUSIVE_LOCK_FUNCTION(metadata_recorder_->read_lock_); ~MetadataProvider() UNLOCK_FUNCTION(); MetadataProvider(const MetadataProvider&) = delete; diff --git a/naiveproxy/src/base/profiler/sample_metadata.h b/naiveproxy/src/base/profiler/sample_metadata.h index 4af45683d0..b0a6dd0021 100644 --- a/naiveproxy/src/base/profiler/sample_metadata.h +++ b/naiveproxy/src/base/profiler/sample_metadata.h @@ -69,7 +69,7 @@ enum class SampleMetadataScope { class BASE_EXPORT SampleMetadata { public: // Set the metadata value associated with |name| to be recorded for |scope|. - explicit SampleMetadata(std::string_view name, SampleMetadataScope scope); + SampleMetadata(std::string_view name, SampleMetadataScope scope); SampleMetadata(const SampleMetadata&) = default; ~SampleMetadata() = default; diff --git a/naiveproxy/src/base/profiler/stack_copier_signal.cc b/naiveproxy/src/base/profiler/stack_copier_signal.cc index ce877e250f..79a3fce9ac 100644 --- a/naiveproxy/src/base/profiler/stack_copier_signal.cc +++ b/naiveproxy/src/base/profiler/stack_copier_signal.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/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "base/profiler/stack_copier_signal.h" #include @@ -21,6 +16,7 @@ #include #include "base/check.h" +#include "base/compiler_specific.h" #include "base/memory/raw_ptr.h" #include "base/memory/raw_ptr_exclusion.h" #include "base/notreached.h" @@ -165,7 +161,8 @@ void CopyStackSignalHandler(int n, siginfo_t* siginfo, void* sigcontext) { *params->success = false; const ucontext_t* ucontext = static_cast(sigcontext); - std::memcpy(params->context, &ucontext->uc_mcontext, sizeof(mcontext_t)); + UNSAFE_TODO( + std::memcpy(params->context, &ucontext->uc_mcontext, sizeof(mcontext_t))); const uintptr_t bottom = RegisterContextStackPointer(params->context); const uintptr_t top = params->stack_base_address; @@ -253,7 +250,7 @@ bool StackCopierSignal::CopyStack(StackBuffer* stack_buffer, // Set the signal handler for the thread to the stack copy function. struct sigaction action; struct sigaction original_action; - memset(&action, 0, sizeof(action)); + UNSAFE_TODO(memset(&action, 0, sizeof(action))); action.sa_sigaction = CopyStackSignalHandler; action.sa_flags = SA_RESTART | SA_SIGINFO; sigemptyset(&action.sa_mask); diff --git a/naiveproxy/src/base/profiler/win32_stack_frame_unwinder.h b/naiveproxy/src/base/profiler/win32_stack_frame_unwinder.h index 75e09f1eda..975169fe12 100644 --- a/naiveproxy/src/base/profiler/win32_stack_frame_unwinder.h +++ b/naiveproxy/src/base/profiler/win32_stack_frame_unwinder.h @@ -61,7 +61,7 @@ class BASE_EXPORT Win32StackFrameUnwinder { UnwindFunctions(); }; - explicit Win32StackFrameUnwinder(); + Win32StackFrameUnwinder(); Win32StackFrameUnwinder(const Win32StackFrameUnwinder&) = delete; Win32StackFrameUnwinder& operator=(const Win32StackFrameUnwinder&) = delete; diff --git a/naiveproxy/src/base/rand_util.h b/naiveproxy/src/base/rand_util.h index fb2d471828..8c33656699 100644 --- a/naiveproxy/src/base/rand_util.h +++ b/naiveproxy/src/base/rand_util.h @@ -111,8 +111,11 @@ T RandomizeByPercentage(T value, double percentage) { // adjustment may not fit in a `T`. The clamped value described in pseudocode // step (2) above will always fit in a `uint64_t`, so do math in `uint64_t`s. const uint64_t abs_value = SafeUnsignedAbs(value); + // Explicitly cast to double to avoid implicit conversion warnings on stricter + // toolchains. The potential precision loss from converting a large uint64_t + // is acceptable for this percentage-based randomization. const uint64_t max_abs_adjustment = - ClampRound(abs_value * percentage / 100); + ClampRound(static_cast(abs_value) * percentage / 100.0); if (!max_abs_adjustment) { return value; } diff --git a/naiveproxy/src/base/sequence_token.h b/naiveproxy/src/base/sequence_token.h index 8f6d49b581..cf532ef16c 100644 --- a/naiveproxy/src/base/sequence_token.h +++ b/naiveproxy/src/base/sequence_token.h @@ -104,9 +104,9 @@ class BASE_EXPORT [[maybe_unused, nodiscard]] TaskScope { // returned by `CurrentTaskIsThreadBound()` within the scope. // `is_running_synchronously` is true iff this is instantiated for a task run // synchronously by `RunOrPostTask()`. - explicit TaskScope(SequenceToken sequence_token, - bool is_thread_bound, - bool is_running_synchronously = false); + TaskScope(SequenceToken sequence_token, + bool is_thread_bound, + bool is_running_synchronously = false); TaskScope(const TaskScope&) = delete; TaskScope& operator=(const TaskScope&) = delete; ~TaskScope(); diff --git a/naiveproxy/src/base/state_transitions.h b/naiveproxy/src/base/state_transitions.h index b3082c77ac..c17f0fa799 100644 --- a/naiveproxy/src/base/state_transitions.h +++ b/naiveproxy/src/base/state_transitions.h @@ -9,7 +9,7 @@ #include "base/check_op.h" #include "base/containers/contains.h" -#include "base/no_destructor.h" +#include "base/containers/span.h" namespace base { @@ -72,14 +72,14 @@ struct StateTransitions { : state_transitions(std::move(state_transitions)) {} // Returns a list of states that are valid to transition to from |source|. - const std::vector& GetValidTransitions(const State& source) const { + span GetValidTransitions(const State& source) const + LIFETIME_BOUND { for (const StateTransition& state_transition : state_transitions) { if (state_transition.source == source) { return state_transition.destinations; } } - static const base::NoDestructor> no_transitions; - return *no_transitions; + return span(); } // Tests whether transitioning from |source| to |destination| is valid. diff --git a/naiveproxy/src/base/strings/safe_sprintf.cc b/naiveproxy/src/base/strings/safe_sprintf.cc index 53674c628b..50863cbf1c 100644 --- a/naiveproxy/src/base/strings/safe_sprintf.cc +++ b/naiveproxy/src/base/strings/safe_sprintf.cc @@ -164,7 +164,7 @@ class Buffer { // have been allocated for the |buffer_|. inline bool Out(char ch) { if (size_ >= 1 && count_ < size_) { - buffer_[count_] = ch; + UNSAFE_TODO(buffer_[count_] = ch); return IncrementCountByOne(); } // |count_| still needs to be updated, even if the buffer has been @@ -263,7 +263,8 @@ class Buffer { if (idx > size_) { idx = size_; } - return buffer_ + idx; + // SAFETY: idx checked against size_ above. + return UNSAFE_BUFFERS(buffer_ + idx); } // User-provided buffer that will receive the fully formatted output string. @@ -363,7 +364,9 @@ bool Buffer::IToASCII(bool sign, // have to discard digits in the order that we have already emitted // them. This is essentially equivalent to: // memmove(buffer_ + start, buffer_ + start + 1, size_ - start - 1) - for (char *move = buffer_ + start, *end = buffer_ + size_ - 1; + // SAFETY: start checked against size_ above. + for (char *move = UNSAFE_BUFFERS(buffer_ + start), + *end = UNSAFE_BUFFERS(buffer_ + size_ - 1); move < end; UNSAFE_TODO(++move)) { *move = UNSAFE_TODO(move[1]); } @@ -423,7 +426,8 @@ bool Buffer::IToASCII(bool sign, // order. We can't easily generate them in forward order, as we can't tell // the number of characters needed until we are done converting. // So, now, we reverse the string (except for the possible '-' sign). - char* front = buffer_ + start; + // SAFETY: start checked against size_ above. + char* front = UNSAFE_BUFFERS(buffer_ + start); char* back = GetInsertionPoint(); UNSAFE_TODO({ while (--back > front) { diff --git a/naiveproxy/src/base/strings/string_view_rust.h b/naiveproxy/src/base/strings/string_view_rust.h index adf5b2daac..de38239857 100644 --- a/naiveproxy/src/base/strings/string_view_rust.h +++ b/naiveproxy/src/base/strings/string_view_rust.h @@ -12,10 +12,6 @@ #include "build/build_config.h" #include "third_party/rust/cxx/v1/cxx.h" -#if BUILDFLAG(IS_NACL) -#error "string_view_rust.h included under IS_NACL" -#endif - namespace base { // Create a Rust str from a std::string_view. This will call std::abort diff --git a/naiveproxy/src/base/strings/stringprintf.h b/naiveproxy/src/base/strings/stringprintf.h index 81a70dc1c6..3a5c17eab3 100644 --- a/naiveproxy/src/base/strings/stringprintf.h +++ b/naiveproxy/src/base/strings/stringprintf.h @@ -8,10 +8,8 @@ #include // va_list #include -#include #include "base/base_export.h" -#include "base/check.h" #include "base/compiler_specific.h" #include "third_party/abseil-cpp/absl/strings/str_format.h" diff --git a/naiveproxy/src/base/supports_user_data.cc b/naiveproxy/src/base/supports_user_data.cc index 31ff533257..5f77c528dc 100644 --- a/naiveproxy/src/base/supports_user_data.cc +++ b/naiveproxy/src/base/supports_user_data.cc @@ -142,4 +142,9 @@ void SupportsUserData::ClearAllUserData() { impl_->user_data_.swap(user_data); } +size_t SupportsUserData::UserDataCount() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return impl_->user_data_.size(); +} + } // namespace base diff --git a/naiveproxy/src/base/supports_user_data.h b/naiveproxy/src/base/supports_user_data.h index cad8045ea2..65cb60de5c 100644 --- a/naiveproxy/src/base/supports_user_data.h +++ b/naiveproxy/src/base/supports_user_data.h @@ -62,6 +62,9 @@ class BASE_EXPORT SupportsUserData { // needs to provide reset functionality. void ClearAllUserData(); + // Returns the number of Data objects attached to this object. + size_t UserDataCount() const; + private: struct Impl; std::unique_ptr impl_; diff --git a/naiveproxy/src/base/synchronization/condition_variable_posix.cc b/naiveproxy/src/base/synchronization/condition_variable_posix.cc index 0c4e4a12c9..45b6cf0983 100644 --- a/naiveproxy/src/base/synchronization/condition_variable_posix.cc +++ b/naiveproxy/src/base/synchronization/condition_variable_posix.cc @@ -37,13 +37,11 @@ ConditionVariable::ConditionVariable(Lock* user_lock) { int rv = 0; // http://crbug.com/293736 - // NaCl doesn't support monotonic clock based absolute deadlines. // On older Android platform versions, it's supported through the // non-standard pthread_cond_timedwait_monotonic_np. Newer platform // versions have pthread_condattr_setclock. // Mac can use relative time deadlines. -#if !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_NACL) && \ - !defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC) +#if !BUILDFLAG(IS_APPLE) && !defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC) pthread_condattr_t attrs; rv = pthread_condattr_init(&attrs); DCHECK_EQ(0, rv); @@ -102,18 +100,10 @@ void ConditionVariable::TimedWait(const TimeDelta& max_time) { #else // The timeout argument to pthread_cond_timedwait is in absolute time. struct timespec absolute_time; -#if BUILDFLAG(IS_NACL) - // See comment in constructor for why this is different in NaCl. - struct timeval now; - gettimeofday(&now, NULL); - absolute_time.tv_sec = now.tv_sec; - absolute_time.tv_nsec = now.tv_usec * Time::kNanosecondsPerMicrosecond; -#else struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); absolute_time.tv_sec = now.tv_sec; absolute_time.tv_nsec = now.tv_nsec; -#endif absolute_time.tv_sec += relative_time.tv_sec; absolute_time.tv_nsec += relative_time.tv_nsec; diff --git a/naiveproxy/src/base/synchronization/lock.h b/naiveproxy/src/base/synchronization/lock.h index 23618e4614..b5113ab9c8 100644 --- a/naiveproxy/src/base/synchronization/lock.h +++ b/naiveproxy/src/base/synchronization/lock.h @@ -35,6 +35,12 @@ class LOCKABLE BASE_EXPORT Lock { Lock(const Lock&) = delete; Lock& operator=(const Lock&) = delete; +#if defined(__clang__) + // We use this only for clang's thread annotation "Negative Capabilities". It + // should never be called. We intentionally leave it undefined. + Lock& operator!(); +#endif + #if !DCHECK_IS_ON() // Optimized wrapper implementation diff --git a/naiveproxy/src/base/synchronization/lock_impl_posix.cc b/naiveproxy/src/base/synchronization/lock_impl_posix.cc index 94491635a8..2e2e02ac8d 100644 --- a/naiveproxy/src/base/synchronization/lock_impl_posix.cc +++ b/naiveproxy/src/base/synchronization/lock_impl_posix.cc @@ -88,7 +88,7 @@ void dcheck_unlock_result(int rv) { // Lock::PriorityInheritanceAvailable still must be checked as the code may // compile but the underlying platform still may not correctly support priority // inheritance locks. -#if BUILDFLAG(IS_NACL) || BUILDFLAG(IS_FUCHSIA) +#if BUILDFLAG(IS_FUCHSIA) #define PRIORITY_INHERITANCE_LOCKS_POSSIBLE() 0 #else #define PRIORITY_INHERITANCE_LOCKS_POSSIBLE() 1 diff --git a/naiveproxy/src/base/synchronization/waitable_event.cc b/naiveproxy/src/base/synchronization/waitable_event.cc index de226a00e2..7cfa11ea54 100644 --- a/naiveproxy/src/base/synchronization/waitable_event.cc +++ b/naiveproxy/src/base/synchronization/waitable_event.cc @@ -2,14 +2,10 @@ // 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/synchronization/waitable_event.h" #include "base/check.h" +#include "base/compiler_specific.h" #include "base/threading/scoped_blocking_call.h" #include "base/trace_event/trace_event.h" #include "base/tracing_buildflags.h" @@ -80,7 +76,7 @@ size_t WaitableEvent::WaitMany(WaitableEvent** events, size_t count) { FROM_HERE, BlockingType::MAY_BLOCK); const size_t signaled_id = WaitManyImpl(events, count); - WaitableEvent* const signaled_event = events[signaled_id]; + WaitableEvent* const signaled_event = UNSAFE_TODO(events[signaled_id]); if (!signaled_event->only_used_while_idle_) { TRACE_EVENT_INSTANT("wakeup.flow,toplevel.flow", "WaitableEvent::WaitMany Complete", diff --git a/naiveproxy/src/base/synchronization/waitable_event_posix.cc b/naiveproxy/src/base/synchronization/waitable_event_posix.cc index 8cd673e9a1..ab14e0055a 100644 --- a/naiveproxy/src/base/synchronization/waitable_event_posix.cc +++ b/naiveproxy/src/base/synchronization/waitable_event_posix.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/synchronization/waitable_event.h" #include @@ -17,6 +12,7 @@ #include #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/memory/stack_allocated.h" #include "base/synchronization/condition_variable.h" #include "base/synchronization/lock.h" @@ -237,7 +233,7 @@ size_t WaitableEvent::WaitManyImpl(WaitableEvent** raw_waitables, std::vector> waitables; waitables.reserve(count); for (size_t i = 0; i < count; ++i) { - waitables.emplace_back(raw_waitables[i], i); + waitables.emplace_back(UNSAFE_TODO(raw_waitables[i]), i); } DCHECK_EQ(count, waitables.size()); @@ -285,19 +281,19 @@ size_t WaitableEvent::WaitManyImpl(WaitableEvent** raw_waitables, // Take the locks of each WaitableEvent in turn (except the signaled one) and // remove our SyncWaiter from the wait-list for (size_t i = 0; i < count; ++i) { - if (raw_waitables[i] != signaled_event) { - raw_waitables[i]->kernel_->lock_.Acquire(); + if (UNSAFE_TODO(raw_waitables[i]) != signaled_event) { + UNSAFE_TODO(raw_waitables[i])->kernel_->lock_.Acquire(); // There's no possible ABA issue with the address of the SyncWaiter here // because it lives on the stack. Thus the tag value is just the pointer // value again. - raw_waitables[i]->kernel_->Dequeue(&sw, &sw); - raw_waitables[i]->kernel_->lock_.Release(); + UNSAFE_TODO(raw_waitables[i])->kernel_->Dequeue(&sw, &sw); + UNSAFE_TODO(raw_waitables[i])->kernel_->lock_.Release(); } else { // By taking this lock here we ensure that |Signal| has completed by the // time we return, because |Signal| holds this lock. This matches the // behaviour of |Wait| and |TimedWait|. - raw_waitables[i]->kernel_->lock_.Acquire(); - raw_waitables[i]->kernel_->lock_.Release(); + UNSAFE_TODO(raw_waitables[i])->kernel_->lock_.Acquire(); + UNSAFE_TODO(raw_waitables[i])->kernel_->lock_.Release(); signaled_index = i; } } @@ -323,10 +319,10 @@ size_t WaitableEvent::EnqueueMany(std::pair* waitables, size_t winner = count; size_t winner_index = count; for (size_t i = 0; i < count; ++i) { - auto& kernel = waitables[i].first->kernel_; + auto& kernel = UNSAFE_TODO(waitables[i]).first->kernel_; kernel->lock_.Acquire(); - if (kernel->signaled_ && waitables[i].second < winner) { - winner = waitables[i].second; + if (kernel->signaled_ && UNSAFE_TODO(waitables[i]).second < winner) { + winner = UNSAFE_TODO(waitables[i]).second; winner_index = i; } } @@ -335,14 +331,15 @@ size_t WaitableEvent::EnqueueMany(std::pair* waitables, // and return. if (winner == count) { for (size_t i = 0; i < count; ++i) { - waitables[i].first->Enqueue(waiter); + UNSAFE_TODO(waitables[i]).first->Enqueue(waiter); } return count; } // Unlock in reverse order and possibly clear the chosen winner's signal // before returning its index. - for (auto* w = waitables + count - 1; w >= waitables; --w) { + for (auto* w = UNSAFE_TODO(waitables + count - 1); w >= waitables; + UNSAFE_TODO(--w)) { auto& kernel = w->first->kernel_; if (w->second == winner) { if (!kernel->manual_reset_) { diff --git a/naiveproxy/src/base/system/sys_info_android.cc b/naiveproxy/src/base/system/sys_info_android.cc index 3fa75298bf..b1b5e3cd95 100644 --- a/naiveproxy/src/base/system/sys_info_android.cc +++ b/naiveproxy/src/base/system/sys_info_android.cc @@ -9,7 +9,6 @@ #include #include "base/compiler_specific.h" -#include "base/lazy_instance.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" diff --git a/naiveproxy/src/base/system/sys_info_posix.cc b/naiveproxy/src/base/system/sys_info_posix.cc index 19f50f0b28..901f2eaba8 100644 --- a/naiveproxy/src/base/system/sys_info_posix.cc +++ b/naiveproxy/src/base/system/sys_info_posix.cc @@ -29,6 +29,7 @@ #include "base/notreached.h" #include "base/numerics/safe_conversions.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/system/sys_info_internal.h" @@ -315,7 +316,7 @@ int SysInfo::NumberOfEfficientProcessorsImpl() { return 0; } if (!StringToUint( - content, + base::TrimWhitespaceASCII(content, TRIM_ALL), &max_core_frequencies_khz[static_cast(core_index)])) { return 0; } diff --git a/naiveproxy/src/base/task/common/checked_lock_impl.cc b/naiveproxy/src/base/task/common/checked_lock_impl.cc index 172a754bca..a457aa6fd3 100644 --- a/naiveproxy/src/base/task/common/checked_lock_impl.cc +++ b/naiveproxy/src/base/task/common/checked_lock_impl.cc @@ -11,9 +11,9 @@ #include #include "base/check_op.h" -#include "base/lazy_instance.h" #include "base/memory/raw_ptr.h" #include "base/memory/raw_ptr_exclusion.h" +#include "base/no_destructor.h" #include "base/synchronization/condition_variable.h" #include "base/task/common/checked_lock.h" #include "base/threading/platform_thread.h" @@ -138,8 +138,10 @@ class SafeAcquisitionTracker { RAW_PTR_EXCLUSION ThreadLocalOwnedPointer tls_acquired_locks_; }; -LazyInstance::Leaky g_safe_acquisition_tracker = - LAZY_INSTANCE_INITIALIZER; +SafeAcquisitionTracker& GetSafeAcquisitionTracker() { + static base::NoDestructor tracker; + return *tracker; +} } // namespace @@ -147,7 +149,7 @@ CheckedLockImpl::CheckedLockImpl() : CheckedLockImpl(nullptr) {} CheckedLockImpl::CheckedLockImpl(const CheckedLockImpl* predecessor) { DCHECK(predecessor == nullptr || !predecessor->is_universal_successor_); - g_safe_acquisition_tracker.Get().RegisterLock(this, predecessor); + GetSafeAcquisitionTracker().RegisterLock(this, predecessor); } CheckedLockImpl::CheckedLockImpl(UniversalPredecessor) @@ -155,25 +157,25 @@ CheckedLockImpl::CheckedLockImpl(UniversalPredecessor) CheckedLockImpl::CheckedLockImpl(UniversalSuccessor) : is_universal_successor_(true) { - g_safe_acquisition_tracker.Get().RegisterLock(this, nullptr); + GetSafeAcquisitionTracker().RegisterLock(this, nullptr); } CheckedLockImpl::~CheckedLockImpl() { - g_safe_acquisition_tracker.Get().UnregisterLock(this); + GetSafeAcquisitionTracker().UnregisterLock(this); } void CheckedLockImpl::AssertNoLockHeldOnCurrentThread() { - g_safe_acquisition_tracker.Get().AssertNoLockHeldOnCurrentThread(); + GetSafeAcquisitionTracker().AssertNoLockHeldOnCurrentThread(); } void CheckedLockImpl::Acquire(subtle::LockTracking tracking) { lock_.Acquire(tracking); - g_safe_acquisition_tracker.Get().RecordAcquisition(this); + GetSafeAcquisitionTracker().RecordAcquisition(this); } void CheckedLockImpl::Release() { lock_.Release(); - g_safe_acquisition_tracker.Get().RecordRelease(this); + GetSafeAcquisitionTracker().RecordRelease(this); } void CheckedLockImpl::AssertAcquired() const { diff --git a/naiveproxy/src/base/task/common/lazy_now.h b/naiveproxy/src/base/task/common/lazy_now.h index 1862e155e3..599e1abcf0 100644 --- a/naiveproxy/src/base/task/common/lazy_now.h +++ b/naiveproxy/src/base/task/common/lazy_now.h @@ -21,7 +21,7 @@ class TickClock; class BASE_EXPORT LazyNow { public: explicit LazyNow(TimeTicks now); - explicit LazyNow(std::optional now, const TickClock* tick_clock); + LazyNow(std::optional now, const TickClock* tick_clock); explicit LazyNow(const TickClock* tick_clock); LazyNow(const LazyNow&) = delete; LazyNow& operator=(const LazyNow&) = delete; diff --git a/naiveproxy/src/base/task/common/task_annotator.cc b/naiveproxy/src/base/task/common/task_annotator.cc index dad844df1f..8ecc8cf6ef 100644 --- a/naiveproxy/src/base/task/common/task_annotator.cc +++ b/naiveproxy/src/base/task/common/task_annotator.cc @@ -399,7 +399,7 @@ void TaskAnnotator::LongTaskTracker::EmitReceivedIPCDetails( if (!ipc_interface_name_ || !ipc_hash_ || !ipc_method_info_) { return; } -#if !BUILDFLAG(IS_NACL) + // Emit all of the IPC hash information if this task // comes from a mojo interface. auto* info = ctx.event()->set_chrome_mojo_event_info(); @@ -417,7 +417,6 @@ void TaskAnnotator::LongTaskTracker::EmitReceivedIPCDetails( if (location_iid) { info->set_mojo_interface_method_iid(*location_iid); } -#endif } // This method is used to record the queueing time and task start time for tasks diff --git a/naiveproxy/src/base/task/common/task_annotator.h b/naiveproxy/src/base/task/common/task_annotator.h index 7922462bc5..58df202166 100644 --- a/naiveproxy/src/base/task/common/task_annotator.h +++ b/naiveproxy/src/base/task/common/task_annotator.h @@ -160,10 +160,10 @@ class BASE_EXPORT [[maybe_unused, nodiscard]] TaskAnnotator::ScopedSetIpcHash { class BASE_EXPORT [[maybe_unused, nodiscard]] TaskAnnotator::LongTaskTracker { public: - explicit LongTaskTracker(const TickClock* tick_clock, - PendingTask& pending_task, - TaskAnnotator* task_annotator, - TimeTicks task_start_time); + LongTaskTracker(const TickClock* tick_clock, + PendingTask& pending_task, + TaskAnnotator* task_annotator, + TimeTicks task_start_time); LongTaskTracker(const LongTaskTracker&) = delete; diff --git a/naiveproxy/src/base/task/current_thread.cc b/naiveproxy/src/base/task/current_thread.cc index 0f5ac15e4b..e97435f170 100644 --- a/naiveproxy/src/base/task/current_thread.cc +++ b/naiveproxy/src/base/task/current_thread.cc @@ -122,8 +122,6 @@ bool CurrentThread::ApplicationTasksAllowedInNativeNestedLoop() const { return current_->IsTaskExecutionAllowedInNativeNestedLoop(); } -#if !BUILDFLAG(IS_NACL) - //------------------------------------------------------------------------------ // CurrentUIThread @@ -194,8 +192,6 @@ void CurrentUIThread::RemoveMessagePumpObserver( } #endif // BUILDFLAG(IS_WIN) -#endif // !BUILDFLAG(IS_NACL) - //------------------------------------------------------------------------------ // CurrentIOThread @@ -217,8 +213,6 @@ MessagePumpForIO* CurrentIOThread::GetMessagePumpForIO() const { return static_cast(current_->GetMessagePump()); } -#if !BUILDFLAG(IS_NACL) - #if BUILDFLAG(IS_WIN) bool CurrentIOThread::RegisterIOHandler(HANDLE file, MessagePumpForIO::IOHandler* handler) { @@ -257,8 +251,6 @@ bool CurrentIOThread::WatchMachReceivePort( } #endif -#endif // !BUILDFLAG(IS_NACL) - #if BUILDFLAG(IS_FUCHSIA) // Additional watch API for native platform resources. bool CurrentIOThread::WatchZxHandle( diff --git a/naiveproxy/src/base/task/current_thread.h b/naiveproxy/src/base/task/current_thread.h index b6e265e2d7..bca2544745 100644 --- a/naiveproxy/src/base/task/current_thread.h +++ b/naiveproxy/src/base/task/current_thread.h @@ -238,8 +238,6 @@ class BASE_EXPORT CurrentThread { raw_ptr current_; }; -#if !BUILDFLAG(IS_NACL) - // UI extension of CurrentThread. class BASE_EXPORT CurrentUIThread : public CurrentThread { public: @@ -293,8 +291,6 @@ class BASE_EXPORT CurrentUIThread : public CurrentThread { MessagePumpForUI* GetMessagePumpForUI() const; }; -#endif // !BUILDFLAG(IS_NACL) - // ForIO extension of CurrentThread. class BASE_EXPORT CurrentIOThread : public CurrentThread { public: @@ -307,8 +303,6 @@ class BASE_EXPORT CurrentIOThread : public CurrentThread { CurrentIOThread* operator->() { return this; } -#if !BUILDFLAG(IS_NACL) - #if BUILDFLAG(IS_WIN) // Please see MessagePumpWin for definitions of these methods. [[nodiscard]] bool RegisterIOHandler(HANDLE file, @@ -341,8 +335,6 @@ class BASE_EXPORT CurrentIOThread : public CurrentThread { MessagePumpForIO::ZxHandleWatcher* delegate); #endif // BUILDFLAG(IS_FUCHSIA) -#endif // !BUILDFLAG(IS_NACL) - private: explicit CurrentIOThread( sequence_manager::internal::SequenceManagerImpl* current) diff --git a/naiveproxy/src/base/task/sequence_manager/sequence_manager.cc b/naiveproxy/src/base/task/sequence_manager/sequence_manager.cc index 27a483afb3..1cc21ee073 100644 --- a/naiveproxy/src/base/task/sequence_manager/sequence_manager.cc +++ b/naiveproxy/src/base/task/sequence_manager/sequence_manager.cc @@ -174,4 +174,8 @@ SequenceManager::Settings SequenceManager::Settings::Builder::Build() { return std::move(settings_); } +SequenceManagerSettings::SequenceManagerSettings( + SequenceManager::Settings settings) + : settings(std::move(settings)) {} + } // namespace base::sequence_manager diff --git a/naiveproxy/src/base/task/sequence_manager/sequence_manager.h b/naiveproxy/src/base/task/sequence_manager/sequence_manager.h index 1c6d9c68d7..534e301399 100644 --- a/naiveproxy/src/base/task/sequence_manager/sequence_manager.h +++ b/naiveproxy/src/base/task/sequence_manager/sequence_manager.h @@ -352,6 +352,20 @@ CreateSequenceManagerOnCurrentThreadWithPump( BASE_EXPORT std::unique_ptr CreateUnboundSequenceManager( SequenceManager::Settings settings = SequenceManager::Settings()); +// Wrapper around SequenceManager::Settings. +// +// If you need `SequenceManager::Settings` in a header file, forward declare +// this `SequenceManagerSettings` instead of including the full +// `sequence_manager.h` header file. This helps avoid increasing compile size. +// For an example of its usage, see base/thread.h. +struct BASE_EXPORT SequenceManagerSettings { + explicit SequenceManagerSettings(SequenceManager::Settings settings); + SequenceManagerSettings(const SequenceManagerSettings&) = delete; + SequenceManagerSettings& operator=(const SequenceManagerSettings&) = delete; + + SequenceManager::Settings settings; +}; + } // namespace sequence_manager } // namespace base diff --git a/naiveproxy/src/base/task/sequence_manager/sequence_manager_impl.cc b/naiveproxy/src/base/task/sequence_manager/sequence_manager_impl.cc index 04539c9ee7..1848f831cc 100644 --- a/naiveproxy/src/base/task/sequence_manager/sequence_manager_impl.cc +++ b/naiveproxy/src/base/task/sequence_manager/sequence_manager_impl.cc @@ -133,10 +133,10 @@ void ReclaimMemoryFromQueue(internal::TaskQueueImpl* queue, LazyNow* lazy_now) { // Writes |address| in hexadecimal ("0x11223344") form starting from |output| // and moving backwards in memory. Returns a pointer to the first digit of the // result. Does *not* NUL-terminate the number. -#if !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_ANDROID) +#if !BUILDFLAG(IS_ANDROID) char* PrependHexAddress(char* output, const void* address) { uintptr_t value = reinterpret_cast(address); - static const char kHexChars[] = "0123456789ABCDEF"; + static const std::string_view kHexChars = "0123456789ABCDEF"; do { *output-- = kHexChars[value % 16]; value /= 16; @@ -145,7 +145,7 @@ char* PrependHexAddress(char* output, const void* address) { *output = '0'; return output; } -#endif // !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_ANDROID) +#endif // !BUILDFLAG(IS_ANDROID) // Atomic to avoid TSAN flags when a test tries to access the value before the // feature list is available. @@ -497,7 +497,6 @@ void SequenceManagerImpl::MaybeEmitTaskDetails( sequence_manager_task->set_priority( settings().priority_settings.TaskPriorityToProto(selected_task.priority)); sequence_manager_task->set_queue_name(selected_task.task_queue_name); - } void SequenceManagerImpl::SetRunTaskSynchronouslyAllowed( @@ -518,7 +517,7 @@ SequenceManagerImpl::SelectNextTask(LazyNow& lazy_now, return selected_task; } -#if DCHECK_IS_ON() && !BUILDFLAG(IS_NACL) +#if DCHECK_IS_ON() void SequenceManagerImpl::LogTaskDebugInfo( const WorkQueue* selected_work_queue) const { const Task* task = selected_work_queue->GetFrontTask(); @@ -573,7 +572,7 @@ void SequenceManagerImpl::LogTaskDebugInfo( } } } -#endif // DCHECK_IS_ON() && !BUILDFLAG(IS_NACL) +#endif // DCHECK_IS_ON() std::optional SequenceManagerImpl::SelectNextTaskImpl(LazyNow& lazy_now, @@ -625,9 +624,9 @@ SequenceManagerImpl::SelectNextTaskImpl(LazyNow& lazy_now, continue; } -#if DCHECK_IS_ON() && !BUILDFLAG(IS_NACL) +#if DCHECK_IS_ON() LogTaskDebugInfo(work_queue); -#endif // DCHECK_IS_ON() && !BUILDFLAG(IS_NACL) +#endif // DCHECK_IS_ON() main_thread_only().task_execution_stack.emplace_back( work_queue->TakeTaskFromWorkQueue(), work_queue->task_queue(), @@ -1187,17 +1186,17 @@ bool SequenceManagerImpl::IsType(MessagePumpType type) const { void SequenceManagerImpl::EnableCrashKeys(const char* async_stack_crash_key) { DCHECK(!main_thread_only().async_stack_crash_key); -#if !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_ANDROID) +#if !BUILDFLAG(IS_ANDROID) main_thread_only().async_stack_crash_key = debug::AllocateCrashKeyString( async_stack_crash_key, debug::CrashKeySize::Size64); static_assert(sizeof(main_thread_only().async_stack_buffer) == static_cast(debug::CrashKeySize::Size64), "Async stack buffer size must match crash key size."); -#endif // !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_ANDROID) +#endif // !BUILDFLAG(IS_ANDROID) } void SequenceManagerImpl::RecordCrashKeys(const PendingTask& pending_task) { -#if !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_ANDROID) +#if !BUILDFLAG(IS_ANDROID) // SetCrashKeyString is a no-op even if the crash key is null, but we'd still // have construct the std::string_view that is passed in. if (!main_thread_only().async_stack_crash_key) { @@ -1229,7 +1228,7 @@ void SequenceManagerImpl::RecordCrashKeys(const PendingTask& pending_task) { debug::SetCrashKeyString( main_thread_only().async_stack_crash_key, std::string_view(pos, static_cast(buffer_end - pos))); -#endif // !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_ANDROID) +#endif // !BUILDFLAG(IS_ANDROID) } internal::TaskQueueImpl* SequenceManagerImpl::currently_executing_task_queue() diff --git a/naiveproxy/src/base/task/sequence_manager/task_queue_impl.cc b/naiveproxy/src/base/task/sequence_manager/task_queue_impl.cc index 933fc9e5f9..2c642b3052 100644 --- a/naiveproxy/src/base/task/sequence_manager/task_queue_impl.cc +++ b/naiveproxy/src/base/task/sequence_manager/task_queue_impl.cc @@ -1539,7 +1539,6 @@ TaskQueueImpl::CreateQueueEnabledVoter() { } void TaskQueueImpl::RemoveCancelledTasks() { -#if !BUILDFLAG(IS_NACL) // TODO(crbug.com/394266102): Remove these crash keys after the bug is // understood and fixed. // @@ -1565,7 +1564,6 @@ void TaskQueueImpl::RemoveCancelledTasks() { static auto* post_remove_cancelled_tasks_delayed_work_queue_size = debug::AllocateCrashKeyString("post_rct_delayed_work_queue_size", debug::CrashKeySize::Size32); -#endif // !BUILDFLAG(IS_NACL) // Because callback destructors could have a side-effect of posting new tasks, // move cancelled callbacks into a temporary container before deleting them. @@ -1574,11 +1572,9 @@ void TaskQueueImpl::RemoveCancelledTasks() { { base::internal::CheckedAutoLock lock(any_thread_lock_); -#if !BUILDFLAG(IS_NACL) debug::SetCrashKeyString( pre_remove_cancelled_tasks_immediate_incoming_queue_size, NumberToString(any_thread_.immediate_incoming_queue.size())); -#endif // !BUILDFLAG(IS_NACL) for (auto& task : any_thread_.immediate_incoming_queue) { if (task.task.IsCancelled()) { @@ -1588,21 +1584,18 @@ void TaskQueueImpl::RemoveCancelledTasks() { std::erase_if(any_thread_.immediate_incoming_queue, [](const Task& task) { return task.task.is_null(); }); -#if !BUILDFLAG(IS_NACL) debug::SetCrashKeyString( post_remove_cancelled_tasks_immediate_incoming_queue_size, NumberToString(any_thread_.immediate_incoming_queue.size())); -#endif // !BUILDFLAG(IS_NACL) } -#if !BUILDFLAG(IS_NACL) debug::SetCrashKeyString( pre_remove_cancelled_tasks_immediate_work_queue_size, NumberToString(main_thread_only_.immediate_work_queue->Size())); -#endif // !BUILDFLAG(IS_NACL) + main_thread_only_.immediate_work_queue->RemoveCancelledTasks( WorkQueue::RemoveCancelledTasksPolicy::kAll); -#if !BUILDFLAG(IS_NACL) + debug::SetCrashKeyString( post_remove_cancelled_tasks_immediate_work_queue_size, NumberToString(main_thread_only_.immediate_work_queue->Size())); @@ -1610,14 +1603,13 @@ void TaskQueueImpl::RemoveCancelledTasks() { debug::SetCrashKeyString( pre_remove_cancelled_tasks_delayed_work_queue_size, NumberToString(main_thread_only_.delayed_work_queue->Size())); -#endif // !BUILDFLAG(IS_NACL) + main_thread_only_.delayed_work_queue->RemoveCancelledTasks( WorkQueue::RemoveCancelledTasksPolicy::kAll); -#if !BUILDFLAG(IS_NACL) + debug::SetCrashKeyString( post_remove_cancelled_tasks_delayed_work_queue_size, NumberToString(main_thread_only_.delayed_work_queue->Size())); -#endif // !BUILDFLAG(IS_NACL) } void TaskQueueImpl::AddQueueEnabledVoter(bool voter_is_enabled, diff --git a/naiveproxy/src/base/task/sequence_manager/task_queue_impl.h b/naiveproxy/src/base/task/sequence_manager/task_queue_impl.h index 1987d3cf3c..1d285ef7fe 100644 --- a/naiveproxy/src/base/task/sequence_manager/task_queue_impl.h +++ b/naiveproxy/src/base/task/sequence_manager/task_queue_impl.h @@ -317,9 +317,9 @@ class BASE_EXPORT TaskQueueImpl : public TaskQueue { class TaskRunner final : public SingleThreadTaskRunner { public: - explicit TaskRunner(scoped_refptr task_poster, - scoped_refptr associated_thread, - TaskType task_type); + TaskRunner(scoped_refptr task_poster, + scoped_refptr associated_thread, + TaskType task_type); bool PostDelayedTask(const Location& location, OnceClosure callback, diff --git a/naiveproxy/src/base/task/sequence_manager/tasks.h b/naiveproxy/src/base/task/sequence_manager/tasks.h index c67e892663..1b36fdb1e2 100644 --- a/naiveproxy/src/base/task/sequence_manager/tasks.h +++ b/naiveproxy/src/base/task/sequence_manager/tasks.h @@ -31,23 +31,23 @@ namespace internal { // Wrapper around PostTask method arguments and the assigned task type. // Eventually it becomes a PendingTask once accepted by a TaskQueueImpl. struct BASE_EXPORT PostedTask { - explicit PostedTask(scoped_refptr task_runner, - OnceClosure callback, - Location location, - TimeDelta delay = base::TimeDelta(), - Nestable nestable = Nestable::kNestable, - TaskType task_type = kTaskTypeNone, - WeakPtr - delayed_task_handle_delegate = nullptr); - explicit PostedTask(scoped_refptr task_runner, - OnceClosure callback, - Location location, - TimeTicks delayed_run_time, - subtle::DelayPolicy delay_policy, - Nestable nestable = Nestable::kNestable, - TaskType task_type = kTaskTypeNone, - WeakPtr - delayed_task_handle_delegate = nullptr); + PostedTask(scoped_refptr task_runner, + OnceClosure callback, + Location location, + TimeDelta delay = base::TimeDelta(), + Nestable nestable = Nestable::kNestable, + TaskType task_type = kTaskTypeNone, + WeakPtr delayed_task_handle_delegate = + nullptr); + PostedTask(scoped_refptr task_runner, + OnceClosure callback, + Location location, + TimeTicks delayed_run_time, + subtle::DelayPolicy delay_policy, + Nestable nestable = Nestable::kNestable, + TaskType task_type = kTaskTypeNone, + WeakPtr delayed_task_handle_delegate = + nullptr); PostedTask(PostedTask&& move_from) noexcept; PostedTask(const PostedTask&) = delete; PostedTask& operator=(const PostedTask&) = delete; diff --git a/naiveproxy/src/base/task/sequence_manager/thread_controller.cc b/naiveproxy/src/base/task/sequence_manager/thread_controller.cc index 87a9eb1574..4b3d07dabc 100644 --- a/naiveproxy/src/base/task/sequence_manager/thread_controller.cc +++ b/naiveproxy/src/base/task/sequence_manager/thread_controller.cc @@ -146,20 +146,8 @@ void ThreadController::RunLevelTracker::TimeKeeper::EnableRecording( Phase::kLastPhase, Phase::kLastPhase + 1, base::HistogramBase::kUmaTargetedHistogramFlag); - perfetto_track_.emplace( - reinterpret_cast(this), - // TODO(crbug.com/42050015): Replace with ThreadTrack::Current() after SDK - // migration. - // In the non-SDK version, ThreadTrack::Current() returns a different - // track id on some platforms (for example Mac OS), which results in - // async tracks not being associated with their thread. - perfetto::ThreadTrack::ForThread( - base::PlatformThread::CurrentId().raw())); - // TODO(crbug.com/42050015): Use Perfetto library to name this Track. - // auto desc = perfetto_track_->Serialize(); - // desc.set_name(JoinString({"MessagePumpPhases", thread_name}, " ")); - // perfetto::internal::TrackEventDataSource::SetTrackDescriptor( - // *perfetto_track_, desc); + perfetto_track_.emplace("MessagePumpPhases", 0, + perfetto::ThreadTrack::Current()); } void ThreadController::RunLevelTracker::OnRunLoopStarted(State initial_state, @@ -603,28 +591,12 @@ void ThreadController::RunLevelTracker::TimeKeeper::RecordEndOfPhase( const TimeTicks phase_end = lazy_now.Now(); RecordTimeInPhase(phase, last_phase_end_, phase_end); - // Ugly hack to name our `perfetto_track_`. - bool is_tracing_enabled = false; - TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("base"), - &is_tracing_enabled); - if (is_tracing_enabled) { - if (!was_tracing_enabled_) { - // The first event name on the track hackily names the track... - // TODO(crbug.com/42050015): Use the Perfetto library to properly name - // this Track in EnableRecording above. - TRACE_EVENT_INSTANT(TRACE_DISABLED_BY_DEFAULT("base"), - "MessagePumpPhases", *perfetto_track_, - last_phase_end_ - Seconds(1)); - } - - const char* event_name = PhaseToEventName(phase); - TRACE_EVENT_BEGIN(TRACE_DISABLED_BY_DEFAULT("base"), - perfetto::StaticString(event_name), *perfetto_track_, - last_phase_end_); - TRACE_EVENT_END(TRACE_DISABLED_BY_DEFAULT("base"), *perfetto_track_, - phase_end); - } - was_tracing_enabled_ = is_tracing_enabled; + const char* event_name = PhaseToEventName(phase); + TRACE_EVENT_BEGIN(TRACE_DISABLED_BY_DEFAULT("base"), + perfetto::StaticString(event_name), *perfetto_track_, + last_phase_end_); + TRACE_EVENT_END(TRACE_DISABLED_BY_DEFAULT("base"), *perfetto_track_, + phase_end); last_phase_end_ = phase_end; } diff --git a/naiveproxy/src/base/task/sequence_manager/thread_controller.h b/naiveproxy/src/base/task/sequence_manager/thread_controller.h index 39daf06f48..8be4452b80 100644 --- a/naiveproxy/src/base/task/sequence_manager/thread_controller.h +++ b/naiveproxy/src/base/task/sequence_manager/thread_controller.h @@ -376,10 +376,7 @@ class BASE_EXPORT ThreadController { // non-null when recording is enabled. raw_ptr histogram_ = nullptr; - std::optional perfetto_track_; - - // True if tracing was enabled during the last pass of RecordTimeInPhase. - bool was_tracing_enabled_ = false; + std::optional perfetto_track_; const raw_ref outer_; } time_keeper_{*this}; diff --git a/naiveproxy/src/base/task/single_thread_task_executor.h b/naiveproxy/src/base/task/single_thread_task_executor.h index 52bf678cf6..585254e727 100644 --- a/naiveproxy/src/base/task/single_thread_task_executor.h +++ b/naiveproxy/src/base/task/single_thread_task_executor.h @@ -52,8 +52,8 @@ class BASE_EXPORT SingleThreadTaskExecutor { void SetWorkBatchSize(int work_batch_size); private: - explicit SingleThreadTaskExecutor(MessagePumpType type, - std::unique_ptr pump); + SingleThreadTaskExecutor(MessagePumpType type, + std::unique_ptr pump); std::unique_ptr sequence_manager_; sequence_manager::TaskQueue::Handle default_task_queue_; diff --git a/naiveproxy/src/base/task/task_features.cc b/naiveproxy/src/base/task/task_features.cc index fe789c4ee7..c58e0fa612 100644 --- a/naiveproxy/src/base/task/task_features.cc +++ b/naiveproxy/src/base/task/task_features.cc @@ -59,10 +59,4 @@ BASE_FEATURE(kRunTasksByBatches, FEATURE_DISABLED_BY_DEFAULT); #endif -BASE_FEATURE(kThreadPoolCap2, "ThreadPoolCap2", FEATURE_DISABLED_BY_DEFAULT); - -// Note: Do not use the prepared macro as of no need for a local cache. -constinit const FeatureParam kThreadPoolCapRestrictedCount{ - &kThreadPoolCap2, "restricted_count", 3}; - } // namespace base diff --git a/naiveproxy/src/base/task/task_features.h b/naiveproxy/src/base/task/task_features.h index 161870ff47..e958cf6f23 100644 --- a/naiveproxy/src/base/task/task_features.h +++ b/naiveproxy/src/base/task/task_features.h @@ -12,11 +12,6 @@ namespace base { -// Fixed amount of threads that will be used as a cap for thread pools. -BASE_EXPORT BASE_DECLARE_FEATURE(kThreadPoolCap2); - -BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(int, kThreadPoolCapRestrictedCount); - // Under this feature, a utility_thread_group will be created for // running USER_VISIBLE tasks. BASE_EXPORT BASE_DECLARE_FEATURE(kUseUtilityThreadGroup); diff --git a/naiveproxy/src/base/task/task_runner.h b/naiveproxy/src/base/task/task_runner.h index 20a7832c8b..8a24a42f3a 100644 --- a/naiveproxy/src/base/task/task_runner.h +++ b/naiveproxy/src/base/task/task_runner.h @@ -158,10 +158,10 @@ class BASE_EXPORT TaskRunner auto* result = new std::unique_ptr(); return PostTaskAndReply( from_here, - BindOnce(&internal::ReturnAsParamAdapter, - std::move(task), result), - BindOnce(&internal::ReplyAdapter, - std::move(reply), Owned(result))); + base::BindOnce(&internal::ReturnAsParamAdapter, + std::move(task), result), + base::BindOnce(&internal::ReplyAdapter, + std::move(reply), Owned(result))); } protected: diff --git a/naiveproxy/src/base/task/task_traits_nocompile.nc b/naiveproxy/src/base/task/task_traits_nocompile.nc index 90c70ce43f..9255e6cfb2 100644 --- a/naiveproxy/src/base/task/task_traits_nocompile.nc +++ b/naiveproxy/src/base/task/task_traits_nocompile.nc @@ -11,6 +11,7 @@ namespace base { constexpr TaskTraits traits = {MayBlock(), MayBlock()}; // expected-error {{constexpr variable 'traits' must be initialized by a constant expression}} // expected-error@base/traits_bag.h:* {{The traits bag contains multiple traits of the same type.}} + // expected-error@*:* {{no matching constructor for initialization}} constexpr TaskTraits traits2 = {WithBaseSyncPrimitives(), // expected-error {{constexpr variable 'traits2' must be initialized by a constant expression}} WithBaseSyncPrimitives()}; // expected-error@base/traits_bag.h:* {{The traits bag contains multiple traits of the same type.}} @@ -32,6 +33,6 @@ constexpr TaskTraits traits5 = {TaskShutdownBehavior::BLOCK_SHUTDOWN, // MayBlock(), // expected-error@base/traits_bag.h:* {{The traits bag contains multiple traits of the same type.}} TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}; // expected-error@*:* {{type occurs more than once in type list}} -constexpr TaskTraits traits6 = {TaskShutdownBehavior::BLOCK_SHUTDOWN, true}; // expected-error {{no matching constructor for initialization of 'const TaskTraits'}} +constexpr TaskTraits traits6 = {TaskShutdownBehavior::BLOCK_SHUTDOWN, true}; // expected-error@*:* 0-1 {{no matching constructor for initialization}} } // namespace base diff --git a/naiveproxy/src/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc b/naiveproxy/src/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc index 9ecaabd304..1e4718a42a 100644 --- a/naiveproxy/src/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc +++ b/naiveproxy/src/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc @@ -634,10 +634,10 @@ void PooledSingleThreadTaskRunnerManager::Start( WorkerThreadObserver* worker_thread_observer) { DCHECK(!worker_thread_observer_); worker_thread_observer_ = worker_thread_observer; -#if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) DCHECK(io_thread_task_runner); io_thread_task_runner_ = std::move(io_thread_task_runner); -#endif // (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#endif // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) g_use_utility_thread_group = CanUseUtilityThreadTypeForWorkerThread() && FeatureList::IsEnabled(kUseUtilityThreadGroup); diff --git a/naiveproxy/src/base/task/thread_pool/thread_group_impl.cc b/naiveproxy/src/base/task/thread_pool/thread_group_impl.cc index bc8fa19641..d00ccdc041 100644 --- a/naiveproxy/src/base/task/thread_pool/thread_group_impl.cc +++ b/naiveproxy/src/base/task/thread_pool/thread_group_impl.cc @@ -985,10 +985,7 @@ bool ThreadGroupImpl::IsOnIdleSetLockRequired(WorkerThread* worker) const { void ThreadGroupImpl::ScheduleAdjustMaxTasks() { // |adjust_max_tasks_posted_| can't change before the task posted below runs. - // Skip check on NaCl to avoid unsafe reference acquisition warning. -#if !BUILDFLAG(IS_NACL) DCHECK(TS_UNCHECKED_READ(adjust_max_tasks_posted_)); -#endif after_start().service_thread_task_runner->PostDelayedTask( FROM_HERE, BindOnce(&ThreadGroupImpl::AdjustMaxTasks, Unretained(this)), diff --git a/naiveproxy/src/base/task/thread_pool/thread_pool_impl.cc b/naiveproxy/src/base/task/thread_pool/thread_pool_impl.cc index e3f1345ac8..64a70b9de2 100644 --- a/naiveproxy/src/base/task/thread_pool/thread_pool_impl.cc +++ b/naiveproxy/src/base/task/thread_pool/thread_pool_impl.cc @@ -137,7 +137,7 @@ void ThreadPoolImpl::Start(const ThreadPoolInstance::InitParams& init_params, // FileDescriptorWatcher in the scope in which tasks run. ServiceThread::Options service_thread_options; service_thread_options.message_pump_type = -#if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) MessagePumpType::IO; #else MessagePumpType::DEFAULT; diff --git a/naiveproxy/src/base/task/thread_pool/thread_pool_instance.cc b/naiveproxy/src/base/task/thread_pool/thread_pool_instance.cc index 21180ece9e..16e6633716 100644 --- a/naiveproxy/src/base/task/thread_pool/thread_pool_instance.cc +++ b/naiveproxy/src/base/task/thread_pool/thread_pool_instance.cc @@ -95,7 +95,6 @@ ThreadPoolInstance::ScopedFizzleBlockShutdownTasks:: } } -#if !BUILDFLAG(IS_NACL) // static void ThreadPoolInstance::CreateAndStartWithDefaultParams( std::string_view name) { @@ -114,7 +113,6 @@ void ThreadPoolInstance::StartWithDefaultParams() { static_cast(std::max(3, SysInfo::NumberOfProcessors() - 1)); Start({max_num_foreground_threads}); } -#endif // !BUILDFLAG(IS_NACL) void ThreadPoolInstance::Create(std::string_view name) { Set(std::make_unique(name)); diff --git a/naiveproxy/src/base/task/thread_pool/thread_pool_instance.h b/naiveproxy/src/base/task/thread_pool/thread_pool_instance.h index 7a43a0df06..079b7c2dd0 100644 --- a/naiveproxy/src/base/task/thread_pool/thread_pool_instance.h +++ b/naiveproxy/src/base/task/thread_pool/thread_pool_instance.h @@ -220,7 +220,6 @@ class BASE_EXPORT ThreadPoolInstance { // not thread-safe; proper synchronization is required to use the // thread_pool.h API after registering a new ThreadPoolInstance. -#if !BUILDFLAG(IS_NACL) // Creates and starts a thread pool using default params. |name| is used to // label histograms, it must not be empty. It should identify the component // that calls this. Start() is called by this method; it is invalid to call it @@ -232,7 +231,6 @@ class BASE_EXPORT ThreadPoolInstance { // Create() and StartWithDefaultParams() calls. Start() is called by this // method; it is invalid to call it again afterwards. void StartWithDefaultParams(); -#endif // !BUILDFLAG(IS_NACL) // Creates a ready to start thread pool. |name| is used to label histograms, // it must not be empty. It should identify the component that creates the diff --git a/naiveproxy/src/base/task/thread_pool/worker_thread.cc b/naiveproxy/src/base/task/thread_pool/worker_thread.cc index fb60dd3070..3aa4e8a1b9 100644 --- a/naiveproxy/src/base/task/thread_pool/worker_thread.cc +++ b/naiveproxy/src/base/task/thread_pool/worker_thread.cc @@ -29,7 +29,7 @@ #include "partition_alloc/partition_alloc_config.h" // nogncheck #endif -#if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) #include "base/files/file_descriptor_watcher_posix.h" #endif @@ -167,7 +167,7 @@ bool WorkerThread::Start( CheckedAutoLock auto_lock(thread_lock_); DCHECK(thread_handle_.is_null()); -#if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) DCHECK(io_thread_task_runner); io_thread_task_runner_ = std::move(io_thread_task_runner); #endif @@ -307,7 +307,7 @@ void WorkerThread::UpdateThreadType(ThreadType desired_thread_type) { } void WorkerThread::ThreadMain() { -#if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) DCHECK(io_thread_task_runner_); FileDescriptorWatcher file_descriptor_watcher(io_thread_task_runner_); #endif diff --git a/naiveproxy/src/base/test/BUILD.gn b/naiveproxy/src/base/test/BUILD.gn index 15fdad3f0c..9932446936 100644 --- a/naiveproxy/src/base/test/BUILD.gn +++ b/naiveproxy/src/base/test/BUILD.gn @@ -4,7 +4,6 @@ import("//build/compiled_action.gni") import("//build/config/features.gni") -import("//build/config/nacl/config.gni") import("//build/config/ui.gni") import("//build/rust/rust_static_library.gni") import("//build_overrides/build.gni") @@ -50,6 +49,10 @@ rust_static_library("test_rust_logger_consumer") { static_library("test_support") { testonly = true sources = [ + "../memory_coordinator/mock_memory_consumer.cc", + "../memory_coordinator/mock_memory_consumer.h", + "../memory_coordinator/test_memory_consumer_registry.cc", + "../memory_coordinator/test_memory_consumer_registry.h", "../task/sequence_manager/test/fake_task.cc", "../task/sequence_manager/test/fake_task.h", "../task/sequence_manager/test/mock_time_domain.cc", @@ -89,6 +92,8 @@ static_library("test_support") { "launcher/test_result.h", "launcher/test_results_tracker.h", "launcher/unit_test_launcher.h", + "manual_hang_watcher.cc", + "manual_hang_watcher.h", "metrics/action_suffix_reader.cc", "metrics/action_suffix_reader.h", "metrics/histogram_enum_reader.cc", @@ -359,6 +364,10 @@ static_library("test_support") { "trace_to_file.cc", "trace_to_file.h", ] + + # TODO(crbug.com/40031409): Fix code that adds exit-time destructors and + # enable the diagnostic by removing this line. + configs += [ "//build/config/compiler:no_exit_time_destructors" ] } component("proto_test_support") { @@ -702,18 +711,15 @@ if (is_android) { "android/javatests/src/org/chromium/base/test/transit/Elements.java", "android/javatests/src/org/chromium/base/test/transit/EntryPointSentinelStation.java", "android/javatests/src/org/chromium/base/test/transit/Facility.java", - "android/javatests/src/org/chromium/base/test/transit/FacilityCheckIn.java", - "android/javatests/src/org/chromium/base/test/transit/FacilityCheckOut.java", - "android/javatests/src/org/chromium/base/test/transit/FacilitySwap.java", "android/javatests/src/org/chromium/base/test/transit/FragmentElement.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/PayloadCallbackCondition.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/SimpleConditions.java", "android/javatests/src/org/chromium/base/test/transit/Station.java", - "android/javatests/src/org/chromium/base/test/transit/StationToStationTrip.java", "android/javatests/src/org/chromium/base/test/transit/StatusStore.java", "android/javatests/src/org/chromium/base/test/transit/TrafficControl.java", "android/javatests/src/org/chromium/base/test/transit/TransitAsserts.java", diff --git a/naiveproxy/src/base/test/android/content_uri_test_utils.cc b/naiveproxy/src/base/test/android/content_uri_test_utils.cc index 17355f091c..0785325351 100644 --- a/naiveproxy/src/base/test/android/content_uri_test_utils.cc +++ b/naiveproxy/src/base/test/android/content_uri_test_utils.cc @@ -4,9 +4,12 @@ #include "base/test/android/content_uri_test_utils.h" +#include + #include "base/android/build_info.h" #include "base/android/path_utils.h" #include "base/files/file_path.h" +#include "base/files/file_util.h" #include "base/strings/escape.h" #include "base/strings/strcat.h" @@ -71,4 +74,14 @@ std::optional GetInMemoryContentTreeUriFromCacheDirDirectory( return GetInMemoryContentDocumentUriFromCacheDirPath(path, /*is_tree=*/true); } +std::optional GetVirtualDocumentPathFromCacheDirDirectory( + const FilePath& path) { + std::optional content_url = + GetInMemoryContentTreeUriFromCacheDirDirectory(path); + if (!content_url) { + return std::nullopt; + } + return base::ResolveToVirtualDocumentPath(*content_url); +} + } // namespace base::test::android diff --git a/naiveproxy/src/base/test/android/content_uri_test_utils.h b/naiveproxy/src/base/test/android/content_uri_test_utils.h index 28b0e8a44f..b971d4ab4a 100644 --- a/naiveproxy/src/base/test/android/content_uri_test_utils.h +++ b/naiveproxy/src/base/test/android/content_uri_test_utils.h @@ -35,6 +35,11 @@ std::optional GetInMemoryContentDocumentUriFromCacheDirFilePath( std::optional GetInMemoryContentTreeUriFromCacheDirDirectory( const FilePath& directory); +// Returns a virtual document path for the specified directory which must be +// under the cache dir, else returns std::nullopt. +std::optional GetVirtualDocumentPathFromCacheDirDirectory( + const FilePath& path); + } // namespace test::android } // namespace base diff --git a/naiveproxy/src/base/test/gtest_xml_unittest_result_printer.cc b/naiveproxy/src/base/test/gtest_xml_unittest_result_printer.cc index ce9ba377c7..2a055d7f7f 100644 --- a/naiveproxy/src/base/test/gtest_xml_unittest_result_printer.cc +++ b/naiveproxy/src/base/test/gtest_xml_unittest_result_printer.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/test/gtest_xml_unittest_result_printer.h" #include @@ -14,6 +9,7 @@ #include "base/base64.h" #include "base/check.h" #include "base/command_line.h" +#include "base/compiler_specific.h" #include "base/files/file_util.h" #include "base/i18n/time_formatting.h" #include "base/strings/string_util.h" @@ -79,11 +75,11 @@ void XmlUnitTestResultPrinter::AddLink(const std::string& name, // theory it should not be possible to reach here and the info is null. DCHECK(info); - fprintf(output_file_.get(), - " %s\n", - info->name(), info->test_suite_name(), name.c_str(), - escaped_url.c_str()); + UNSAFE_TODO(fprintf(output_file_.get(), + " %s\n", + info->name(), info->test_suite_name(), name.c_str(), + escaped_url.c_str())); fflush(output_file_); } @@ -101,11 +97,11 @@ void XmlUnitTestResultPrinter::AddTag(const std::string& name, // theory it should not be possible to reach here and the info is null. DCHECK(info); - fprintf(output_file_.get(), - " %s\n", - info->name(), info->test_suite_name(), name.c_str(), - escaped_value.c_str()); + UNSAFE_TODO(fprintf(output_file_.get(), + " %s\n", + info->name(), info->test_suite_name(), name.c_str(), + escaped_value.c_str())); fflush(output_file_); } @@ -123,11 +119,12 @@ void XmlUnitTestResultPrinter::AddSubTestResult( // which violates this function's preconditions. CHECK(info); - fprintf(output_file_.get(), - " name(), info->test_suite_name(), name.data(), - static_cast(elapsed_time) / Time::kMillisecondsPerSecond); + UNSAFE_TODO(fprintf( + output_file_.get(), + " name(), info->test_suite_name(), name.data(), + static_cast(elapsed_time) / Time::kMillisecondsPerSecond)); if (failure_message) { std::string encoded = base::Base64Encode(*failure_message); fprintf(output_file_.get(), " failure_message=\"%s\"", encoded.c_str()); @@ -176,26 +173,28 @@ void XmlUnitTestResultPrinter::OnTestStart(const testing::TestInfo& test_info) { // This is our custom extension - it helps to recognize which test was // running when the test binary crashed. Note that we cannot even open the // tag here - it requires e.g. run time of the test to be known. - fprintf(output_file_.get(), - " \n", - test_info.name(), test_info.test_suite_name(), - TimeFormatAsIso8601(Time::Now()).c_str()); + UNSAFE_TODO(fprintf( + output_file_.get(), + " \n", + test_info.name(), test_info.test_suite_name(), + TimeFormatAsIso8601(Time::Now()).c_str())); fflush(output_file_); test_running_ = true; } void XmlUnitTestResultPrinter::OnTestEnd(const testing::TestInfo& test_info) { DCHECK(test_running_); - fprintf(output_file_.get(), - " \n", - test_info.name(), - static_cast(test_info.result()->elapsed_time()) / - Time::kMillisecondsPerSecond, - test_info.test_suite_name(), - TimeFormatAsIso8601(Time::FromMillisecondsSinceUnixEpoch( - test_info.result()->start_timestamp())) - .c_str()); + UNSAFE_TODO( + fprintf(output_file_.get(), + " \n", + test_info.name(), + static_cast(test_info.result()->elapsed_time()) / + Time::kMillisecondsPerSecond, + test_info.test_suite_name(), + TimeFormatAsIso8601(Time::FromMillisecondsSinceUnixEpoch( + test_info.result()->start_timestamp())) + .c_str())); if (test_info.result()->Failed()) { fprintf(output_file_.get(), " \n"); @@ -207,7 +206,8 @@ void XmlUnitTestResultPrinter::OnTestEnd(const testing::TestInfo& test_info) { std::string limit_str = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kTestLauncherTestPartResultsLimit); - int test_part_results_limit = std::strtol(limit_str.c_str(), nullptr, 10); + int test_part_results_limit = + UNSAFE_TODO(std::strtol(limit_str.c_str(), nullptr, 10)); if (test_part_results_limit >= 0) { limit = std::min(limit, test_part_results_limit); } @@ -267,12 +267,13 @@ void XmlUnitTestResultPrinter::WriteTestPartResult( } std::string summary_encoded = base::Base64Encode(summary); std::string message_encoded = base::Base64Encode(message); - fprintf(output_file_.get(), - " \n" - " %s\n" - " %s\n" - " \n", - type, file, line, summary_encoded.c_str(), message_encoded.c_str()); + UNSAFE_TODO(fprintf( + output_file_.get(), + " \n" + " %s\n" + " %s\n" + " \n", + type, file, line, summary_encoded.c_str(), message_encoded.c_str())); fflush(output_file_); } diff --git a/naiveproxy/src/base/test/gtest_xml_util.cc b/naiveproxy/src/base/test/gtest_xml_util.cc index a088c6a1a1..f24a7fafb5 100644 --- a/naiveproxy/src/base/test/gtest_xml_util.cc +++ b/naiveproxy/src/base/test/gtest_xml_util.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/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "base/test/gtest_xml_util.h" #include @@ -17,6 +12,7 @@ #include "base/base64.h" #include "base/check.h" +#include "base/compiler_specific.h" #include "base/files/file_util.h" #include "base/strings/string_number_conversions.h" #include "base/test/gtest_util.h" @@ -183,9 +179,9 @@ bool ProcessGTestOutput(const base::FilePath& output_file, if (!xml_reader.NodeAttribute("time", &test_time_str)) { return false; } - result.elapsed_time = Microseconds( - static_cast(strtod(test_time_str.c_str(), nullptr) * - Time::kMicrosecondsPerSecond)); + result.elapsed_time = Microseconds(static_cast( + UNSAFE_TODO(strtod(test_time_str.c_str(), nullptr)) * + Time::kMicrosecondsPerSecond)); // The timestamp attribute records the local date and time of the test // execution. It might be missing in the xml generated by older diff --git a/naiveproxy/src/base/test/launcher/test_launcher.cc b/naiveproxy/src/base/test/launcher/test_launcher.cc index 4e1624fc9b..41f571607a 100644 --- a/naiveproxy/src/base/test/launcher/test_launcher.cc +++ b/naiveproxy/src/base/test/launcher/test_launcher.cc @@ -1828,10 +1828,6 @@ bool TestLauncher::Init(CommandLine* command_line) { results_tracker_.AddGlobalTag("OS_MAC"); #endif -#if BUILDFLAG(IS_NACL) - results_tracker_.AddGlobalTag("OS_NACL"); -#endif - #if BUILDFLAG(IS_OPENBSD) results_tracker_.AddGlobalTag("OS_OPENBSD"); #endif diff --git a/naiveproxy/src/base/test/manual_hang_watcher.cc b/naiveproxy/src/base/test/manual_hang_watcher.cc new file mode 100644 index 0000000000..cca15b54c8 --- /dev/null +++ b/naiveproxy/src/base/test/manual_hang_watcher.cc @@ -0,0 +1,67 @@ +// Copyright 2025 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/manual_hang_watcher.h" + +#include + +#include "base/functional/bind.h" +#include "base/functional/callback.h" +#include "base/synchronization/waitable_event.h" +#include "base/test/bind.h" +#include "base/time/time.h" + +namespace base::test { + +ManualHangWatcher::ManualHangWatcher(ProcessType process_type, + bool emit_crashes) { + HangWatcher::InitializeOnMainThread(process_type, emit_crashes); + + SetAfterMonitorClosureForTesting( + BindRepeating(&WaitableEvent::Signal, Unretained(&monitor_event_))); + + SetOnHangClosureForTesting(BindLambdaForTesting([this] { + hang_count_.fetch_add(1, std::memory_order_relaxed); + if (on_hang_closure_) { + on_hang_closure_.Run(); + } + })); + + // Disable periodic monitoring by setting a very very long monitoring + // period. Monitoring will be started manually by calling + // `TriggerSynchronousMonitoring()`. + SetMonitoringPeriodForTesting(Days(365)); + + // Start the monitoring loop. + Start(); +} + +ManualHangWatcher::~ManualHangWatcher() { + UninitializeOnMainThreadForTesting(); + + // Stop now instead of in `~HangWatcher()` to avoid a data race between + // the destructor and virtual calls. If we destroy `HangWatcher` right after + // it's created, `HangWatcher::Run()` might get called concurrently with + // `~HangWatcher`. The vtable pointer is changed when calling into a parent + // class destructor. Virtual calls might resolve differently before or after + // the vtable is changed. See here for details: + // https://github.com/google/sanitizers/wiki/ThreadSanitizerPopularDataRaces#data-race-on-vptr + Stop(); +} + +void ManualHangWatcher::SetOnHangClosure(RepeatingClosure closure) { + on_hang_closure_ = std::move(closure); +} + +void ManualHangWatcher::TriggerSynchronousMonitoring() { + monitor_event_.Reset(); + SignalMonitorEventForTesting(); + monitor_event_.Wait(); +} + +int ManualHangWatcher::GetHangCount() const { + return hang_count_.load(std::memory_order_relaxed); +} + +} // namespace base::test diff --git a/naiveproxy/src/base/test/manual_hang_watcher.h b/naiveproxy/src/base/test/manual_hang_watcher.h new file mode 100644 index 0000000000..5937d4766d --- /dev/null +++ b/naiveproxy/src/base/test/manual_hang_watcher.h @@ -0,0 +1,71 @@ +// Copyright 2025 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_MANUAL_HANG_WATCHER_H_ +#define BASE_TEST_MANUAL_HANG_WATCHER_H_ + +#include + +#include "base/functional/callback.h" +#include "base/synchronization/waitable_event.h" +#include "base/threading/hang_watcher.h" + +namespace base::test { + +// A version of `base::HangWatcher` that can be used in unit tests to check for +// hung threads manually and synchronously. +// +// In production, `HangWatcher` runs a periodic timer and checks whether threads +// are hung automatically on a background thread. This is unsuitable for unit +// tests, where we need monitoring to happen deterministically. +// `ManualHangWatcher` addresses this by disabling automated monitoring (by +// using a monitoring period of 365 days). Monitoring is instead manually +// triggered via `TriggerSynchronousMonitoring()`. +// +// Example usage: +// ManualHangWatcher hang_watcher(HangWatcher::ProcessType::kBrowserProcess); +// ScopedClosureRunner scoped_unregister = HangWatcher::RegisterThread( +// HangWatcher::ThreadType::kMainThread); +// +// HistogramTester histogram_tester; +// hang_watcher.TriggerSynchronousMonitoring(); // Checks if thread is hung. +// histogram_tester.ExpectBucketCount( +// "HangWatcher.IsThreadHung.BrowserProcess.UIThread.Normal", +// false, 1); // Thread is not hung. +class ManualHangWatcher : public HangWatcher { + public: + explicit ManualHangWatcher(ProcessType process_type, + bool emit_crashes = true); + + ~ManualHangWatcher() override; + + // Set a callback to be invoked when a hang is detected. + void SetOnHangClosure(RepeatingClosure closure); + + // Checks whether any of the watched threads are hung. The monitoring is done + // in the hang watcher's monitoring thread. This function signals that thread + // to start a monitoring pass and waits for it to complete. + // + // Results can be observed via histograms (using a `HistogramTester`), or by + // watching for hangs using either `SetOnHangClosure()` or `GetHangCount()`. + void TriggerSynchronousMonitoring(); + + // Return the number of time a hang was observed. + int GetHangCount() const; + + private: + // Used to wait for monitoring. Will be signaled by the HangWatcher thread and + // so needs to outlive it. + WaitableEvent monitor_event_; + + // Count the number of time the HangWatcher thread detected a hang. + std::atomic hang_count_ = 0; + + // If specified by a test, this closure is invoked when a hang is detected. + RepeatingClosure on_hang_closure_; +}; + +} // namespace base::test + +#endif // BASE_TEST_MANUAL_HANG_WATCHER_H_ diff --git a/naiveproxy/src/base/test/multiprocess_test_android.cc b/naiveproxy/src/base/test/multiprocess_test_android.cc index 62a12af7cd..427364153d 100644 --- a/naiveproxy/src/base/test/multiprocess_test_android.cc +++ b/naiveproxy/src/base/test/multiprocess_test_android.cc @@ -8,7 +8,6 @@ #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" @@ -55,7 +54,7 @@ Process SpawnMultiProcessTestChild(const std::string& procname, android::ToJavaArrayOfStrings(env, command_line.argv()); jint pid = android::Java_MultiprocessTestClientLauncher_launchClient( - env, j_argv, fds, base::android::PackBinderBox(env, options.binders)); + env, j_argv, fds); return Process(pid); } diff --git a/naiveproxy/src/base/test/perf_log.cc b/naiveproxy/src/base/test/perf_log.cc index 154877c048..e362018c35 100644 --- a/naiveproxy/src/base/test/perf_log.cc +++ b/naiveproxy/src/base/test/perf_log.cc @@ -2,14 +2,10 @@ // 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/test/perf_log.h" #include "base/check.h" +#include "base/compiler_specific.h" #include "base/files/file_util.h" #include "base/notreached.h" @@ -38,8 +34,8 @@ void FinalizePerfLog() { void LogPerfResult(const char* test_name, double value, const char* units) { CHECK(perf_log_file); - fprintf(perf_log_file, "%s\t%g\t%s\n", test_name, value, units); - printf("%s\t%g\t%s\n", test_name, value, units); + UNSAFE_TODO(fprintf(perf_log_file, "%s\t%g\t%s\n", test_name, value, units)); + UNSAFE_TODO(printf("%s\t%g\t%s\n", test_name, value, units)); fflush(stdout); } diff --git a/naiveproxy/src/base/test/scoped_logging_settings.h b/naiveproxy/src/base/test/scoped_logging_settings.h index 3f3995b588..4f2285d331 100644 --- a/naiveproxy/src/base/test/scoped_logging_settings.h +++ b/naiveproxy/src/base/test/scoped_logging_settings.h @@ -73,7 +73,7 @@ class BASE_EXPORT ScopedLoggingSettings { // must be destroyed in reverse creation order. class BASE_EXPORT ScopedVmoduleSwitches { public: - explicit ScopedVmoduleSwitches(); + ScopedVmoduleSwitches(); // Specify which modules and levels to enable. This uses the same syntax as // the commandline flag, e.g. "file=1,dir/other_file=2". void InitWithSwitches(const std::string& vmodule_switch); diff --git a/naiveproxy/src/base/test/scoped_path_override.cc b/naiveproxy/src/base/test/scoped_path_override.cc index 8f73691ac0..7460c13e8d 100644 --- a/naiveproxy/src/base/test/scoped_path_override.cc +++ b/naiveproxy/src/base/test/scoped_path_override.cc @@ -19,11 +19,18 @@ ScopedPathOverride::ScopedPathOverride(int key) : key_(key) { CHECK(result); } -ScopedPathOverride::ScopedPathOverride(int key, const base::FilePath& dir) +ScopedPathOverride::ScopedPathOverride(int key, + const base::FilePath& dir, + bool should_skip_check) : key_(key) { SaveOriginal(); - bool result = PathService::Override(key, dir); - CHECK(result); + if (should_skip_check) { + bool result = PathService::OverrideWithoutCheckForTesting(key, dir); + CHECK(result); + } else { + bool result = PathService::Override(key, dir); + CHECK(result); + } } ScopedPathOverride::ScopedPathOverride(int key, diff --git a/naiveproxy/src/base/test/scoped_path_override.h b/naiveproxy/src/base/test/scoped_path_override.h index 4a1b87775b..6ce3df3120 100644 --- a/naiveproxy/src/base/test/scoped_path_override.h +++ b/naiveproxy/src/base/test/scoped_path_override.h @@ -19,11 +19,16 @@ class FilePath; // scope of the test is left. class ScopedPathOverride { public: - // Contructor that initializes the override to a scoped temp directory. + // Constructor that initializes the override to a scoped temp directory. explicit ScopedPathOverride(int key); // Constructor that would use a path provided by the user. - ScopedPathOverride(int key, const FilePath& dir); + // If `should_skip_check` is set to true, it will call + // `PathService::OverrideWithoutCheckForTesting()` which may set an invalid or + // non-absolute path for testing. + ScopedPathOverride(int key, + const FilePath& dir, + bool should_skip_check = false); // See PathService::OverrideAndCreateIfNeeded. ScopedPathOverride(int key, diff --git a/naiveproxy/src/base/test/test_discardable_memory_allocator.cc b/naiveproxy/src/base/test/test_discardable_memory_allocator.cc index 293228d62c..b2d042cdae 100644 --- a/naiveproxy/src/base/test/test_discardable_memory_allocator.cc +++ b/naiveproxy/src/base/test/test_discardable_memory_allocator.cc @@ -2,17 +2,13 @@ // 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/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "base/test/test_discardable_memory_allocator.h" #include #include #include "base/check.h" +#include "base/compiler_specific.h" #include "base/memory/discardable_memory.h" #include "base/memory/ptr_util.h" @@ -36,7 +32,7 @@ class DiscardableMemoryImpl : public DiscardableMemory { is_locked_ = false; // Force eviction to catch clients not correctly checking the return value // of Lock(). - memset(data_.get(), 0, size_); + UNSAFE_TODO(memset(data_.get(), 0, size_)); } void* data() const override { diff --git a/naiveproxy/src/base/test/test_shared_memory_util.cc b/naiveproxy/src/base/test/test_shared_memory_util.cc index 9000ec1036..48a848ad49 100644 --- a/naiveproxy/src/base/test/test_shared_memory_util.cc +++ b/naiveproxy/src/base/test/test_shared_memory_util.cc @@ -11,7 +11,7 @@ #include "base/logging.h" #include "build/build_config.h" -#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL) +#if BUILDFLAG(IS_POSIX) #include #include #include @@ -33,8 +33,6 @@ namespace base { -#if !BUILDFLAG(IS_NACL) - static const size_t kDataSize = 1024; // Common routine used with Posix file descriptors. Check that shared memory @@ -138,8 +136,6 @@ bool CheckReadOnlyPlatformSharedMemoryRegionForTesting( #endif } -#endif // !BUILDFLAG(IS_NACL) - WritableSharedMemoryMapping MapForTesting( subtle::PlatformSharedMemoryRegion* region) { return MapAtForTesting(region, 0, region->GetSize()); diff --git a/naiveproxy/src/base/test/test_shortcut_win.cc b/naiveproxy/src/base/test/test_shortcut_win.cc index 601294279e..826aef98d2 100644 --- a/naiveproxy/src/base/test/test_shortcut_win.cc +++ b/naiveproxy/src/base/test/test_shortcut_win.cc @@ -139,23 +139,6 @@ void ValidateShortcut(const FilePath& shortcut_path, ADD_FAILURE() << "Unexpected variant type: " << pv_app_id.get().vt; } } - - if (properties.options & ShortcutProperties::PROPERTIES_DUAL_MODE) { - ScopedPropVariant pv_dual_mode; - EXPECT_EQ(S_OK, property_store->GetValue(PKEY_AppUserModel_IsDualMode, - pv_dual_mode.Receive())); - switch (pv_dual_mode.get().vt) { - case VT_EMPTY: - EXPECT_FALSE(properties.dual_mode); - break; - case VT_BOOL: - EXPECT_EQ(properties.dual_mode, - static_cast(pv_dual_mode.get().boolVal)); - break; - default: - ADD_FAILURE() << "Unexpected variant type: " << pv_dual_mode.get().vt; - } - } } } // namespace win diff --git a/naiveproxy/src/base/test/test_suite.cc b/naiveproxy/src/base/test/test_suite.cc index 76b34d4078..c7f973f99e 100644 --- a/naiveproxy/src/base/test/test_suite.cc +++ b/naiveproxy/src/base/test/test_suite.cc @@ -541,7 +541,21 @@ void TestSuite::Initialize() { // ASAN. #if PA_BUILDFLAG(USE_PARTITION_ALLOC) && !defined(ADDRESS_SANITIZER) allocator::PartitionAllocSupport::Get()->ReconfigureForTests(); -#endif // BUILDFLAG(IS_WIN) + +#if GTEST_HAS_DEATH_TEST + // Unfortunately GTEST does not call event listeners at all inside child + // processes. In such case do reconfiguration here instead of inside + // `FeatureListScopedToEachTest`. FeatureList is not fully initialized but + // better than never reconfigured. + // TODO(https://crbug.com/432019338): Remove this once fixed. + if (::testing::internal::InDeathTestChild()) { + allocator::PartitionAllocSupport::Get()->ReconfigureAfterFeatureListInit( + "", + /*configure_dangling_pointer_detector=*/true, + /*is_in_death_test_child=*/true); + } +#endif // GTEST_HAS_DEATH_TEST +#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC) && !defined(ADDRESS_SANITIZER) test::ScopedRunLoopTimeout::SetAddGTestFailureOnTimeout(); diff --git a/naiveproxy/src/base/test/test_support_ios.mm b/naiveproxy/src/base/test/test_support_ios.mm index f5d76b1ffc..902b33cabc 100644 --- a/naiveproxy/src/base/test/test_support_ios.mm +++ b/naiveproxy/src/base/test/test_support_ios.mm @@ -62,7 +62,7 @@ bool IsSceneStartupEnabled() { - (void)_terminateWithStatus:(int)status; @end -#if TARGET_IPHONE_SIMULATOR +#if TARGET_OS_SIMULATOR // Xcode 6 introduced behavior in the iOS Simulator where the software // keyboard does not appear if a hardware keyboard is connected. The following // declaration allows this behavior to be overridden when the app starts up. @@ -71,7 +71,7 @@ bool IsSceneStartupEnabled() { - (void)setAutomaticMinimizationEnabled:(BOOL)enabled; - (void)setSoftwareKeyboardShownByTouch:(BOOL)enabled; @end -#endif // TARGET_IPHONE_SIMULATOR +#endif // TARGET_OS_SIMULATOR // Can be used to easily check if the current application is being used for // running tests. @@ -122,7 +122,7 @@ bool IsSceneStartupEnabled() { - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { -#if TARGET_IPHONE_SIMULATOR +#if TARGET_OS_SIMULATOR // Xcode 6 introduced behavior in the iOS Simulator where the software // keyboard does not appear if a hardware keyboard is connected. The following // calls override this behavior by ensuring that the software keyboard is @@ -132,7 +132,7 @@ bool IsSceneStartupEnabled() { } else { [[UIKeyboardImpl sharedInstance] setSoftwareKeyboardShownByTouch:YES]; } -#endif // TARGET_IPHONE_SIMULATOR +#endif // TARGET_OS_SIMULATOR if (!IsSceneStartupEnabled()) { CGRect bounds = UIScreen.mainScreen.bounds; @@ -160,14 +160,14 @@ bool IsSceneStartupEnabled() { // output to stdout, but results must be written to NSLog in order to show up in // the device log that is retrieved from the device by the host. - (BOOL)shouldRedirectOutputToFile { -#if !TARGET_IPHONE_SIMULATOR +#if !TARGET_OS_SIMULATOR // Tests in XCTest mode don't need to redirect output to a file because the // test result parser analyzes console output. return !base::ShouldRunIOSUnittestsWithXCTest() && !base::debug::BeingDebugged(); #else return NO; -#endif // TARGET_IPHONE_SIMULATOR +#endif // TARGET_OS_SIMULATOR } // Returns the path to the directory to store gtest output files. diff --git a/naiveproxy/src/base/test/trace_event_analyzer.h b/naiveproxy/src/base/test/trace_event_analyzer.h index a2c53f11ad..b112e6f1ff 100644 --- a/naiveproxy/src/base/test/trace_event_analyzer.h +++ b/naiveproxy/src/base/test/trace_event_analyzer.h @@ -101,10 +101,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "base/trace_event/trace_event.h" - -namespace base { -class Value; -} +#include "base/values.h" namespace trace_analyzer { class QueryNode; diff --git a/naiveproxy/src/base/threading/hang_watcher.cc b/naiveproxy/src/base/threading/hang_watcher.cc index c62f44f870..6090fe95e7 100644 --- a/naiveproxy/src/base/threading/hang_watcher.cc +++ b/naiveproxy/src/base/threading/hang_watcher.cc @@ -124,12 +124,41 @@ void LogStatusHistogram(HangWatcher::ThreadType thread_type, break; case HangWatcher::ProcessType::kGPUProcess: - // Not recorded for now. + // `SetShuttingDown` is not called for the GPU process. If we ever decide + // to track shutdown hangs, we'll need the histograms below to be suffixed + // with ".Shutdown". CHECK(!shutting_down); + + switch (thread_type) { + case HangWatcher::ThreadType::kIOThread: + UMA_HISTOGRAM_SPLIT_BY_PROCESS_PRIORITY( + UMA_HISTOGRAM_BOOLEAN, sample_ticks, monitoring_period, + "HangWatcher.IsThreadHung.GpuProcess.IOThread", any_thread_hung); + break; + case HangWatcher::ThreadType::kMainThread: + UMA_HISTOGRAM_SPLIT_BY_PROCESS_PRIORITY( + UMA_HISTOGRAM_BOOLEAN, sample_ticks, monitoring_period, + "HangWatcher.IsThreadHung.GpuProcess.MainThread", + any_thread_hung); + break; + case HangWatcher::ThreadType::kCompositorThread: + UMA_HISTOGRAM_SPLIT_BY_PROCESS_PRIORITY( + UMA_HISTOGRAM_BOOLEAN, sample_ticks, monitoring_period, + "HangWatcher.IsThreadHung.GpuProcess.CompositorThread", + any_thread_hung); + break; + case HangWatcher::ThreadType::kThreadPoolThread: + // Not recorded for now. + break; + } break; case HangWatcher::ProcessType::kRendererProcess: + // `SetShuttingDown` is not called for the renderer process. If we ever + // decide to track shutdown hangs, we'll need the histograms below to be + // suffixed with ".Shutdown". CHECK(!shutting_down); + switch (thread_type) { case HangWatcher::ThreadType::kIOThread: UMA_HISTOGRAM_SPLIT_BY_PROCESS_PRIORITY( @@ -156,7 +185,11 @@ void LogStatusHistogram(HangWatcher::ThreadType thread_type, break; case HangWatcher::ProcessType::kUtilityProcess: + // `SetShuttingDown` is not called for the Utility process. If we ever + // decide to track shutdown hangs, we'll need the histograms below to be + // suffixed with ".Shutdown". CHECK(!shutting_down); + switch (thread_type) { case HangWatcher::ThreadType::kIOThread: UMA_HISTOGRAM_BOOLEAN( @@ -216,55 +249,88 @@ BASE_FEATURE(kEnableHangWatcher, #endif ); +// Enable HangWatcher on the GPU process. +BASE_FEATURE(kEnableHangWatcherOnGpuProcess, + "EnableHangWatcherOnGpuProcess", + FEATURE_DISABLED_BY_DEFAULT); + // Browser process. // Note: Do not use the prepared macro as of no need for a local cache. +const char kBrowserProcessIoThreadLogLevelParam[] = "io_thread_log_level"; +const char kBrowserProcessUiThreadLogLevelParam[] = "ui_thread_log_level"; +const char kBrowserProcessThreadPoolLogLevelParam[] = "threadpool_log_level"; constexpr base::FeatureParam kIOThreadLogLevel{ - &kEnableHangWatcher, "io_thread_log_level", + &kEnableHangWatcher, kBrowserProcessIoThreadLogLevelParam, static_cast(LoggingLevel::kUmaOnly)}; constexpr base::FeatureParam kUIThreadLogLevel{ - &kEnableHangWatcher, "ui_thread_log_level", + &kEnableHangWatcher, kBrowserProcessUiThreadLogLevelParam, static_cast(LoggingLevel::kUmaOnly)}; constexpr base::FeatureParam kThreadPoolLogLevel{ - &kEnableHangWatcher, "threadpool_log_level", + &kEnableHangWatcher, kBrowserProcessThreadPoolLogLevelParam, static_cast(LoggingLevel::kUmaOnly)}; // GPU process. // Note: Do not use the prepared macro as of no need for a local cache. +const char kGpuProcessIoThreadLogLevelParam[] = + "gpu_process_io_thread_log_level"; +const char kGpuProcessMainThreadLogLevelParam[] = + "gpu_process_main_thread_log_level"; +const char kGpuProcessCompositorThreadLogLevelParam[] = + "gpu_process_compositor_thread_log_level"; +const char kGpuProcessThreadPoolLogLevelParam[] = + "gpu_process_threadpool_log_level"; constexpr base::FeatureParam kGPUProcessIOThreadLogLevel{ - &kEnableHangWatcher, "gpu_process_io_thread_log_level", - static_cast(LoggingLevel::kNone)}; + &kEnableHangWatcher, kGpuProcessIoThreadLogLevelParam, + static_cast(LoggingLevel::kUmaOnly)}; constexpr base::FeatureParam kGPUProcessMainThreadLogLevel{ - &kEnableHangWatcher, "gpu_process_main_thread_log_level", - static_cast(LoggingLevel::kNone)}; + &kEnableHangWatcher, kGpuProcessMainThreadLogLevelParam, + static_cast(LoggingLevel::kUmaOnly)}; +constexpr base::FeatureParam kGPUProcessCompositorThreadLogLevel{ + &kEnableHangWatcher, kGpuProcessCompositorThreadLogLevelParam, + static_cast(LoggingLevel::kUmaOnly)}; constexpr base::FeatureParam kGPUProcessThreadPoolLogLevel{ - &kEnableHangWatcher, "gpu_process_threadpool_log_level", - static_cast(LoggingLevel::kNone)}; + &kEnableHangWatcher, kGpuProcessThreadPoolLogLevelParam, + static_cast(LoggingLevel::kUmaOnly)}; // Renderer process. // Note: Do not use the prepared macro as of no need for a local cache. +const char kRendererProcessIoThreadLogLevelParam[] = + "renderer_process_io_thread_log_level"; +const char kRendererProcessMainThreadLogLevelParam[] = + "renderer_process_main_thread_log_level"; +const char kRendererProcessThreadPoolLogLevelParam[] = + "renderer_process_threadpool_log_level"; +const char kRendererProcessCompositorThreadLogLevelParam[] = + "renderer_process_compositor_thread_log_level"; constexpr base::FeatureParam kRendererProcessIOThreadLogLevel{ - &kEnableHangWatcher, "renderer_process_io_thread_log_level", + &kEnableHangWatcher, kRendererProcessIoThreadLogLevelParam, static_cast(LoggingLevel::kUmaOnly)}; constexpr base::FeatureParam kRendererProcessMainThreadLogLevel{ - &kEnableHangWatcher, "renderer_process_main_thread_log_level", + &kEnableHangWatcher, kRendererProcessMainThreadLogLevelParam, static_cast(LoggingLevel::kUmaOnly)}; constexpr base::FeatureParam kRendererProcessThreadPoolLogLevel{ - &kEnableHangWatcher, "renderer_process_threadpool_log_level", + &kEnableHangWatcher, kRendererProcessThreadPoolLogLevelParam, static_cast(LoggingLevel::kUmaOnly)}; constexpr base::FeatureParam kRendererProcessCompositorThreadLogLevel{ - &kEnableHangWatcher, "renderer_process_compositor_thread_log_level", + &kEnableHangWatcher, kRendererProcessCompositorThreadLogLevelParam, static_cast(LoggingLevel::kUmaOnly)}; // Utility process. // Note: Do not use the prepared macro as of no need for a local cache. +const char kUtilityProcessIoThreadLogLevelParam[] = + "utility_process_io_thread_log_level"; +const char kUtilityProcessMainThreadLogLevelParam[] = + "utility_process_main_thread_log_level"; +const char kUtilityProcessThreadPoolLogLevelParam[] = + "utility_process_threadpool_log_level"; constexpr base::FeatureParam kUtilityProcessIOThreadLogLevel{ - &kEnableHangWatcher, "utility_process_io_thread_log_level", + &kEnableHangWatcher, kUtilityProcessIoThreadLogLevelParam, static_cast(LoggingLevel::kUmaOnly)}; constexpr base::FeatureParam kUtilityProcessMainThreadLogLevel{ - &kEnableHangWatcher, "utility_process_main_thread_log_level", + &kEnableHangWatcher, kUtilityProcessMainThreadLogLevelParam, static_cast(LoggingLevel::kUmaOnly)}; constexpr base::FeatureParam kUtilityProcessThreadPoolLogLevel{ - &kEnableHangWatcher, "utility_process_threadpool_log_level", + &kEnableHangWatcher, kUtilityProcessThreadPoolLogLevelParam, static_cast(LoggingLevel::kUmaOnly)}; constexpr const char* kThreadName = "HangWatcher"; @@ -277,7 +343,12 @@ constexpr const char* kThreadName = "HangWatcher"; // hangs but present unacceptable overhead. NOTE: If this period is ever changed // then all metrics that depend on it like // HangWatcher.IsThreadHung need to be updated. -constexpr auto kMonitoringPeriod = base::Seconds(10); +const char kHangWatcherMonitoringPeriodParam[] = + "hang_watcher_monitoring_period"; +constexpr base::FeatureParam kHangWatcherMonitoringPeriod( + &kEnableHangWatcher, + kHangWatcherMonitoringPeriodParam, + base::Seconds(10)); WatchHangsInScope::WatchHangsInScope(TimeDelta timeout) { internal::HangWatchState* current_hang_watch_state = @@ -386,10 +457,11 @@ void HangWatcher::InitializeOnMainThread(ProcessType process_type, bool enable_hang_watcher = base::FeatureList::IsEnabled(kEnableHangWatcher); - // Do not start HangWatcher in the GPU process until the issue related to - // invalid magic signature in the GPU WatchDog is fixed - // (https://crbug.com/1297760). - if (process_type == ProcessType::kGPUProcess) { + // The issue related to invalid magic signature in the GPU WatchDog is fixed + // (https://crbug.com/1297760), we can now rollout HangWatcher on the GPU + // process. + if (process_type == ProcessType::kGPUProcess && + !base::FeatureList::IsEnabled(kEnableHangWatcherOnGpuProcess)) { enable_hang_watcher = false; } @@ -436,6 +508,9 @@ void HangWatcher::InitializeOnMainThread(ProcessType process_type, g_main_thread_log_level.store( static_cast(kGPUProcessMainThreadLogLevel.Get()), std::memory_order_relaxed); + g_compositor_thread_log_level.store( + static_cast(kGPUProcessCompositorThreadLogLevel.Get()), + std::memory_order_relaxed); } else if (process_type == HangWatcher::ProcessType::kRendererProcess) { g_threadpool_log_level.store( static_cast(kRendererProcessThreadPoolLogLevel.Get()), @@ -535,7 +610,7 @@ void HangWatcher::SetShuttingDown() { } HangWatcher::HangWatcher() - : monitoring_period_(kMonitoringPeriod), + : monitoring_period_(kHangWatcherMonitoringPeriod.Get()), should_monitor_(WaitableEvent::ResetPolicy::AUTOMATIC), thread_(this, kThreadName), tick_clock_(base::DefaultTickClock::GetInstance()), @@ -560,7 +635,6 @@ void HangWatcher::CreateHangWatcherInstance() { ANNOTATE_LEAKING_OBJECT_PTR(g_instance); } -#if !BUILDFLAG(IS_NACL) debug::ScopedCrashKeyString HangWatcher::GetTimeSinceLastCriticalMemoryPressureCrashKey() { DCHECK_CALLED_ON_VALID_THREAD(hang_watcher_thread_checker_); @@ -592,7 +666,6 @@ HangWatcher::GetTimeSinceLastCriticalMemoryPressureCrashKey() { time_since_last_critical_memory_pressure.InSeconds())); } } -#endif std::string HangWatcher::GetTimeSinceLastSystemPowerResumeCrashKeyValue() const { @@ -626,7 +699,9 @@ HangWatcher::~HangWatcher() { DCHECK_EQ(g_instance, this); DCHECK(watch_states_.empty()); g_instance = nullptr; - Stop(); + if (thread_started_) { + Stop(); + } } void HangWatcher::Start() { @@ -646,9 +721,9 @@ void HangWatcher::Stop() { g_keep_monitoring.store(true, std::memory_order_relaxed); } -bool HangWatcher::IsWatchListEmpty() { +bool HangWatcher::IsWatchingThreads() { AutoLock auto_lock(watch_state_lock_); - return watch_states_.empty(); + return !watch_states_.empty(); } void HangWatcher::Wait() { @@ -711,7 +786,7 @@ void HangWatcher::Run() { while (g_keep_monitoring.load(std::memory_order_relaxed)) { Wait(); - if (!IsWatchListEmpty() && + if (IsWatchingThreads() && g_keep_monitoring.load(std::memory_order_relaxed)) { Monitor(); if (after_monitor_closure_for_testing_) { @@ -986,7 +1061,6 @@ void HangWatcher::DoDumpWithoutCrashing( capture_in_progress_.store(true, std::memory_order_relaxed); base::AutoLock scope_lock(capture_lock_); -#if !BUILDFLAG(IS_NACL) const std::string list_of_hung_thread_ids = watch_state_snapshot.PrepareHungThreadListCrashKey(); @@ -1005,7 +1079,6 @@ void HangWatcher::DoDumpWithoutCrashing( SCOPED_CRASH_KEY_BOOL("HangWatcher", "shutting-down", g_shutting_down.load(std::memory_order_relaxed)); -#endif // To avoid capturing more than one hang that blames a subset of the same // threads it's necessary to keep track of what is the furthest deadline diff --git a/naiveproxy/src/base/threading/hang_watcher.h b/naiveproxy/src/base/threading/hang_watcher.h index f7c25bd9f7..713e922263 100644 --- a/naiveproxy/src/base/threading/hang_watcher.h +++ b/naiveproxy/src/base/threading/hang_watcher.h @@ -257,10 +257,16 @@ class BASE_EXPORT HangWatcher : public DelegateSimpleThread::Delegate { // Begin executing the monitoring loop on the HangWatcher thread. void Start(); + // Stop all monitoring and join the HangWatcher thread. + void Stop(); + // Returns true if Start() has been called and Stop() has not been called // since. bool IsStarted() const { return thread_started_; } + // Returns `true` if this HangWatcher watches threads. + bool IsWatchingThreads() LOCKS_EXCLUDED(watch_state_lock_); + // Returns the value of the crash key with the time since last system power // resume. std::string GetTimeSinceLastSystemPowerResumeCrashKeyValue() const; @@ -280,12 +286,10 @@ class BASE_EXPORT HangWatcher : public DelegateSimpleThread::Delegate { void OnMemoryPressure( base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level); -#if !BUILDFLAG(IS_NACL) // Returns a ScopedCrashKeyString that sets the crash key with the time since // last critical memory pressure signal. [[nodiscard]] debug::ScopedCrashKeyString GetTimeSinceLastCriticalMemoryPressureCrashKey(); -#endif // Invoke base::debug::DumpWithoutCrashing() insuring that the stack frame // right under it in the trace belongs to HangWatcher for easier attribution. @@ -355,9 +359,6 @@ class BASE_EXPORT HangWatcher : public DelegateSimpleThread::Delegate { void DoDumpWithoutCrashing(const WatchStateSnapShot& watch_state_snapshot) EXCLUSIVE_LOCKS_REQUIRED(watch_state_lock_) LOCKS_EXCLUDED(capture_lock_); - // Stop all monitoring and join the HangWatcher thread. - void Stop(); - // Wait until it's time to monitor. void Wait(); @@ -371,8 +372,6 @@ class BASE_EXPORT HangWatcher : public DelegateSimpleThread::Delegate { // appropriate monitoring frequency. WaitableEvent should_monitor_; - bool IsWatchListEmpty() LOCKS_EXCLUDED(watch_state_lock_); - // Stops hang watching on the calling thread by removing the entry from the // watch list. void UnregisterThread() LOCKS_EXCLUDED(watch_state_lock_); diff --git a/naiveproxy/src/base/threading/platform_thread.cc b/naiveproxy/src/base/threading/platform_thread.cc index 2e4f7d9e26..2ed43104f4 100644 --- a/naiveproxy/src/base/threading/platform_thread.cc +++ b/naiveproxy/src/base/threading/platform_thread.cc @@ -29,12 +29,9 @@ void PlatformThreadBase::SetCurrentThreadType(ThreadType thread_type) { MessagePumpType message_pump_type = MessagePumpType::DEFAULT; if (CurrentIOThread::IsSet()) { message_pump_type = MessagePumpType::IO; - } -#if !BUILDFLAG(IS_NACL) - else if (CurrentUIThread::IsSet()) { + } else if (CurrentUIThread::IsSet()) { message_pump_type = MessagePumpType::UI; } -#endif internal::SetCurrentThreadType(thread_type, message_pump_type); } diff --git a/naiveproxy/src/base/threading/platform_thread_android.cc b/naiveproxy/src/base/threading/platform_thread_android.cc index 2339153e4c..29317cffa0 100644 --- a/naiveproxy/src/base/threading/platform_thread_android.cc +++ b/naiveproxy/src/base/threading/platform_thread_android.cc @@ -15,7 +15,6 @@ #include "base/android/build_info.h" #include "base/android/jni_android.h" #include "base/feature_list.h" -#include "base/lazy_instance.h" #include "base/logging.h" #include "base/threading/platform_thread_internal_posix.h" #include "base/threading/thread_id_name_manager.h" diff --git a/naiveproxy/src/base/threading/platform_thread_internal_posix.cc b/naiveproxy/src/base/threading/platform_thread_internal_posix.cc index 68a8784444..25e766f7ee 100644 --- a/naiveproxy/src/base/threading/platform_thread_internal_posix.cc +++ b/naiveproxy/src/base/threading/platform_thread_internal_posix.cc @@ -31,11 +31,6 @@ ThreadPriorityForTest NiceValueToThreadPriorityForTest(int nice_value) { } int GetCurrentThreadNiceValue() { -#if BUILDFLAG(IS_NACL) - NOTIMPLEMENTED(); - return 0; -#else - // Need to clear errno before calling getpriority(): // http://man7.org/linux/man-pages/man2/getpriority.2.html errno = 0; @@ -47,7 +42,6 @@ int GetCurrentThreadNiceValue() { } return nice_value; -#endif } } // namespace base::internal diff --git a/naiveproxy/src/base/threading/platform_thread_posix.cc b/naiveproxy/src/base/threading/platform_thread_posix.cc index e72da9ea29..09c17bc298 100644 --- a/naiveproxy/src/base/threading/platform_thread_posix.cc +++ b/naiveproxy/src/base/threading/platform_thread_posix.cc @@ -28,7 +28,7 @@ #include "build/build_config.h" #include "partition_alloc/buildflags.h" -#if !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_FUCHSIA) && !BUILDFLAG(IS_NACL) +#if !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_FUCHSIA) #include "base/posix/can_lower_nice_to.h" #endif @@ -83,7 +83,6 @@ void* ThreadFunc(void* params) { partition_alloc::internal::StackTopRegistry::Get().NotifyThreadCreated(); #endif -#if !BUILDFLAG(IS_NACL) #if BUILDFLAG(IS_APPLE) PlatformThread::SetCurrentThreadRealtimePeriodValue( delegate->GetRealtimePeriod()); @@ -93,7 +92,6 @@ void* ThreadFunc(void* params) { // where they were created. This explicitly sets the priority of all new // threads. PlatformThread::SetCurrentThreadType(thread_params->thread_type); -#endif // !BUILDFLAG(IS_NACL) } ThreadIdNameManager::GetInstance()->RegisterThread( @@ -265,11 +263,7 @@ PlatformThreadId PlatformThreadBase::CurrentId() { return PlatformThreadId(id); #elif BUILDFLAG(IS_SOLARIS) || BUILDFLAG(IS_QNX) return PlatformThreadId(pthread_self()); -#elif BUILDFLAG(IS_NACL) && defined(__GLIBC__) - return PlatformThreadId(pthread_self()); -#elif BUILDFLAG(IS_NACL) && !defined(__GLIBC__) - // Pointers are 32-bits in NaCl. - return PlatformThreadId(reinterpret_cast(pthread_self())); + #elif BUILDFLAG(IS_POSIX) && BUILDFLAG(IS_AIX) return PlatformThreadId(pthread_self()); #elif BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_AIX) @@ -365,9 +359,6 @@ void PlatformThreadBase::Detach(PlatformThreadHandle thread_handle) { // static bool PlatformThreadBase::CanChangeThreadType(ThreadType from, ThreadType to) { -#if BUILDFLAG(IS_NACL) - return false; -#else if (from >= to) { // Decreasing thread priority on POSIX is always allowed. return true; @@ -377,16 +368,12 @@ bool PlatformThreadBase::CanChangeThreadType(ThreadType from, ThreadType to) { } return internal::CanLowerNiceTo(internal::ThreadTypeToNiceValue(to)); -#endif // BUILDFLAG(IS_NACL) } namespace internal { void SetCurrentThreadTypeImpl(ThreadType thread_type, MessagePumpType pump_type_hint) { -#if BUILDFLAG(IS_NACL) - NOTIMPLEMENTED(); -#else if (internal::SetCurrentThreadTypeForPlatform(thread_type, pump_type_hint)) { return; } @@ -402,17 +389,12 @@ void SetCurrentThreadTypeImpl(ThreadType thread_type, DVPLOG(1) << "Failed to set nice value of thread (" << PlatformThread::CurrentId() << ") to " << nice_setting; } -#endif // BUILDFLAG(IS_NACL) } } // namespace internal // static ThreadPriorityForTest PlatformThreadBase::GetCurrentThreadPriorityForTest() { -#if BUILDFLAG(IS_NACL) - NOTIMPLEMENTED(); - return ThreadPriorityForTest::kNormal; -#else // Mirrors SetCurrentThreadPriority()'s implementation. auto platform_specific_priority = internal::GetCurrentThreadPriorityForPlatformForTest(); // IN-TEST @@ -423,7 +405,6 @@ ThreadPriorityForTest PlatformThreadBase::GetCurrentThreadPriorityForTest() { int nice_value = internal::GetCurrentThreadNiceValue(); return internal::NiceValueToThreadPriorityForTest(nice_value); // IN-TEST -#endif // !BUILDFLAG(IS_NACL) } #endif // !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_FUCHSIA) diff --git a/naiveproxy/src/base/threading/scoped_blocking_call_internal.cc b/naiveproxy/src/base/threading/scoped_blocking_call_internal.cc index 1d1ea81c69..8955e4f3ab 100644 --- a/naiveproxy/src/base/threading/scoped_blocking_call_internal.cc +++ b/naiveproxy/src/base/threading/scoped_blocking_call_internal.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/threading/scoped_blocking_call_internal.h" #include @@ -284,7 +279,7 @@ void IOJankMonitoringWindow::AddJank(int local_jank_start_index, // ~IOJankMonitoringWindow(). AutoLock lock(intervals_lock_); for (int i = local_jank_start_index; i < local_jank_end_index; ++i) { - ++intervals_jank_count_[i]; + ++UNSAFE_TODO(intervals_jank_count_[i]); } } diff --git a/naiveproxy/src/base/threading/scoped_thread_priority.cc b/naiveproxy/src/base/threading/scoped_thread_priority.cc index caec5b8e1d..5d9f2ddfb1 100644 --- a/naiveproxy/src/base/threading/scoped_thread_priority.cc +++ b/naiveproxy/src/base/threading/scoped_thread_priority.cc @@ -34,6 +34,33 @@ ScopedBoostPriority::~ScopedBoostPriority() { } } +TaskMonitoringScopedBoostPriority::TaskMonitoringScopedBoostPriority( + ThreadType target_thread_type, + RepeatingCallback should_boost_callback) + : target_thread_type_(target_thread_type), + should_boost_callback_(std::move(should_boost_callback)) { + CHECK(should_boost_callback_); +} + +TaskMonitoringScopedBoostPriority::~TaskMonitoringScopedBoostPriority() { + scoped_boost_priority_.reset(); +} + +void TaskMonitoringScopedBoostPriority::WillProcessTask( + const PendingTask& pending_task, + bool was_blocked_or_low_priority) { + bool should_boost = should_boost_callback_.Run(); + if (scoped_boost_priority_.has_value() == should_boost) { + return; + } + + if (should_boost) { + scoped_boost_priority_.emplace(target_thread_type_); + } else { + scoped_boost_priority_.reset(); + } +} + namespace internal { ScopedMayLoadLibraryAtBackgroundPriority:: diff --git a/naiveproxy/src/base/threading/scoped_thread_priority.h b/naiveproxy/src/base/threading/scoped_thread_priority.h index e57fd6957f..14500aac93 100644 --- a/naiveproxy/src/base/threading/scoped_thread_priority.h +++ b/naiveproxy/src/base/threading/scoped_thread_priority.h @@ -13,6 +13,7 @@ #include "base/location.h" #include "base/macros/uniquify.h" #include "base/memory/raw_ptr.h" +#include "base/task/task_observer.h" #include "build/build_config.h" namespace base { @@ -66,6 +67,31 @@ class BASE_EXPORT ScopedBoostPriority { std::optional original_thread_type_; }; +// This wraps ScopedBoostPriority with a callback to determine whether +// the priority should be boosted or not before every task execution. +class BASE_EXPORT TaskMonitoringScopedBoostPriority : public TaskObserver { + public: + explicit TaskMonitoringScopedBoostPriority( + ThreadType target_thread_type, + RepeatingCallback should_boost_callback); + ~TaskMonitoringScopedBoostPriority() override; + + TaskMonitoringScopedBoostPriority(const TaskMonitoringScopedBoostPriority&) = + delete; + TaskMonitoringScopedBoostPriority& operator=( + const TaskMonitoringScopedBoostPriority&) = delete; + + // TaskObserver implementation: + void WillProcessTask(const PendingTask& pending_task, + bool was_blocked_or_low_priority) override; + void DidProcessTask(const PendingTask& pending_task) override {} + + private: + std::optional scoped_boost_priority_; + ThreadType target_thread_type_; + RepeatingCallback should_boost_callback_; +}; + namespace internal { class BASE_EXPORT ScopedMayLoadLibraryAtBackgroundPriority { diff --git a/naiveproxy/src/base/threading/thread.cc b/naiveproxy/src/base/threading/thread.cc index 3a2ea84774..84efab98e0 100644 --- a/naiveproxy/src/base/threading/thread.cc +++ b/naiveproxy/src/base/threading/thread.cc @@ -28,7 +28,7 @@ #include "build/build_config.h" #include "third_party/abseil-cpp/absl/base/dynamic_annotations.h" -#if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) #include #include "base/files/file_descriptor_watcher_posix.h" @@ -58,13 +58,17 @@ class SequenceManagerThreadDelegate : public Thread::Delegate { public: explicit SequenceManagerThreadDelegate( MessagePumpType message_pump_type, - OnceCallback()> message_pump_factory) + OnceCallback()> message_pump_factory, + std::unique_ptr + sequence_manager_settings) : sequence_manager_( sequence_manager::internal::CreateUnboundSequenceManagerImpl( PassKey(), - sequence_manager::SequenceManager::Settings::Builder() - .SetMessagePumpType(message_pump_type) - .Build())), + sequence_manager_settings + ? std::move(sequence_manager_settings->settings) + : sequence_manager::SequenceManager::Settings::Builder() + .SetMessagePumpType(message_pump_type) + .Build())), default_task_queue_(sequence_manager_->CreateTaskQueue( sequence_manager::TaskQueue::Spec( sequence_manager::QueueName::DEFAULT_TQ))), @@ -98,6 +102,10 @@ class SequenceManagerThreadDelegate : public Thread::Delegate { std::move(message_pump_factory_).Run()); } + void AddTaskObserver(TaskObserver* observer) override { + sequence_manager_->AddTaskObserver(observer); + } + private: std::unique_ptr sequence_manager_; @@ -120,7 +128,9 @@ Thread::Options::Options(Options&& other) message_pump_factory(std::move(other.message_pump_factory)), stack_size(std::move(other.stack_size)), thread_type(std::move(other.thread_type)), - joinable(std::move(other.joinable)) { + joinable(std::move(other.joinable)), + sequence_manager_settings(std::move(other.sequence_manager_settings)), + task_observer(std::move(other.task_observer)) { other.moved_from = true; } @@ -133,6 +143,7 @@ Thread::Options& Thread::Options::operator=(Thread::Options&& other) { stack_size = std::move(other.stack_size); thread_type = std::move(other.thread_type); joinable = std::move(other.joinable); + task_observer = std::move(other.task_observer); other.moved_from = true; return *this; @@ -192,12 +203,18 @@ bool Thread::StartWithOptions(Options options) { delegate_ = std::move(options.delegate); } else if (options.message_pump_factory) { delegate_ = std::make_unique( - MessagePumpType::CUSTOM, options.message_pump_factory); + MessagePumpType::CUSTOM, options.message_pump_factory, + std::move(options.sequence_manager_settings)); } else { delegate_ = std::make_unique( options.message_pump_type, BindOnce([](MessagePumpType type) { return MessagePump::Create(type); }, - options.message_pump_type)); + options.message_pump_type), + std::move(options.sequence_manager_settings)); + } + + if (options.task_observer) { + delegate_->AddTaskObserver(options.task_observer); } start_event_.Reset(); @@ -385,14 +402,14 @@ void Thread::ThreadMain() { delegate_->BindToCurrentThread(); DCHECK(CurrentThread::Get()); DCHECK(SingleThreadTaskRunner::HasCurrentDefault()); -#if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) // Allow threads running a MessageLoopForIO to use FileDescriptorWatcher API. std::unique_ptr file_descriptor_watcher; if (CurrentIOThread::IsSet()) { file_descriptor_watcher = std::make_unique( delegate_->GetDefaultTaskRunner()); } -#endif // (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#endif // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) #if BUILDFLAG(IS_WIN) std::unique_ptr com_initializer; diff --git a/naiveproxy/src/base/threading/thread.h b/naiveproxy/src/base/threading/thread.h index 16b59dc960..3c90ce32cc 100644 --- a/naiveproxy/src/base/threading/thread.h +++ b/naiveproxy/src/base/threading/thread.h @@ -26,8 +26,13 @@ namespace base { +namespace sequence_manager { +struct SequenceManagerSettings; +} + class MessagePump; class RunLoop; +class TaskObserver; // IMPORTANT: Instead of creating a base::Thread, consider using // base::ThreadPool::Create(Sequenced|SingleThread)TaskRunner(). @@ -68,6 +73,9 @@ class BASE_EXPORT Thread : PlatformThread::Delegate { // Binds a RunLoop::Delegate and task runner CurrentDefaultHandle to the // thread. virtual void BindToCurrentThread() = 0; + + // Adds a TaskObserver to the sequence manager of the thread. + virtual void AddTaskObserver(TaskObserver* observer) = 0; }; struct BASE_EXPORT Options { @@ -112,6 +120,14 @@ class BASE_EXPORT Thread : PlatformThread::Delegate { // user-after-frees (proposal @ https://crbug.com/629139#c14) bool joinable = true; + // Custom settings for the SequenceManager created for this thread, if any. + // Allows overriding default SequenceManager behavior. + std::unique_ptr + sequence_manager_settings; + + // A TaskObserver needed be added at the start of a thread. + raw_ptr task_observer = nullptr; + bool IsValid() const { return !moved_from; } private: diff --git a/naiveproxy/src/base/threading/thread_local_storage.cc b/naiveproxy/src/base/threading/thread_local_storage.cc index a70e9ea231..ff27132ef3 100644 --- a/naiveproxy/src/base/threading/thread_local_storage.cc +++ b/naiveproxy/src/base/threading/thread_local_storage.cc @@ -467,9 +467,7 @@ bool ThreadLocalStorage::HasBeenDestroyed() { void ThreadLocalStorage::Slot::Initialize(TLSDestructorFunc destructor) { // The heap sampler uses TLS internally. Disable allocation sampling before // allocating TLS-internal structures, to safeguard against reentrancy. -#if BUILDFLAG(IS_NACL) - // Heap sampler isn't built under NACL. -#elif BUILDFLAG(IS_IOS) && !PA_BUILDFLAG(USE_ALLOCATOR_SHIM) +#if BUILDFLAG(IS_IOS) && !PA_BUILDFLAG(USE_ALLOCATOR_SHIM) // Heap sampler is only built on IOS when the allocator shim is enabled. #else base::PoissonAllocationSampler::ScopedMuteThreadSamples mute_heap_sampler; diff --git a/naiveproxy/src/base/threading/thread_restrictions.h b/naiveproxy/src/base/threading/thread_restrictions.h index b1abcfaab5..f9e528588b 100644 --- a/naiveproxy/src/base/threading/thread_restrictions.h +++ b/naiveproxy/src/base/threading/thread_restrictions.h @@ -163,7 +163,9 @@ bool HasWaylandDisplay(base::Environment* env); namespace android_webview { class AwBrowserContext; +class AwBrowserContextStore; class AwFormDatabaseService; +class AwMetricsServiceClient; class CookieManager; class JsSandboxIsolate; class OverlayProcessorWebView; @@ -346,7 +348,6 @@ namespace memory_pressure { class UserLevelMemoryPressureSignalGenerator; } namespace metrics { -class AndroidMetricsServiceClient; class CleanExitBeacon; } // namespace metrics namespace midi { @@ -446,12 +447,6 @@ class VrShell; namespace web { class WebMainLoop; } // namespace web -namespace weblayer { -class BrowserContextImpl; -class ContentBrowserClientImpl; -class ProfileImpl; -class WebLayerPathProvider; -} // namespace weblayer // NOTE: Please do not append entries here. Put them in the list above and keep // the list sorted. @@ -507,7 +502,7 @@ class Thread; // NaCL doesn't support stack capture. // Android can hang in stack capture (crbug.com/959139). -#if BUILDFLAG(IS_NACL) || BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(IS_ANDROID) #define CAPTURE_THREAD_RESTRICTIONS_STACK_TRACES() false #else // Stack capture is slow. Only enable it in developer builds, to avoid user @@ -582,6 +577,9 @@ class BASE_EXPORT ScopedAllowBlocking { friend class ::StartupTabProviderImpl; friend class ::WebEngineBrowserMainParts; friend class android_webview::AwBrowserContext; + friend class android_webview::AwBrowserContextStore; + friend class android_webview::AwMetricsServiceClient; + friend class android_webview::CookieManager; friend class android_webview::ScopedAllowInitGLBindings; friend class ash::LoginEventRecorder; friend class ash::StartupCustomizationDocument; // http://crosbug.com/11103 @@ -623,7 +621,6 @@ class BASE_EXPORT ScopedAllowBlocking { friend class media::FileVideoCaptureDeviceFactory; friend class memory_instrumentation::OSMetrics; friend class memory_pressure::UserLevelMemoryPressureSignalGenerator; - friend class metrics::AndroidMetricsServiceClient; friend class metrics::CleanExitBeacon; friend class module_installer::ScopedAllowModulePakLoad; friend class net::GSSAPISharedLibrary; // http://crbug.com/66702 @@ -644,10 +641,6 @@ class BASE_EXPORT ScopedAllowBlocking { friend class ui::DrmDisplayHostManager; friend class ui::ScopedAllowBlockingForGbmSurface; friend class ui::SelectFileDialogLinux; - friend class weblayer::BrowserContextImpl; - friend class weblayer::ContentBrowserClientImpl; - friend class weblayer::ProfileImpl; - friend class weblayer::WebLayerPathProvider; #if BUILDFLAG(IS_MAC) friend class printing::PrintBackendServiceImpl; #endif diff --git a/naiveproxy/src/base/threading/threading_features.h b/naiveproxy/src/base/threading/threading_features.h index 23f3056d39..445fb0378a 100644 --- a/naiveproxy/src/base/threading/threading_features.h +++ b/naiveproxy/src/base/threading/threading_features.h @@ -28,6 +28,27 @@ BASE_EXPORT BASE_DECLARE_FEATURE(kUserInteractiveCompositingMac); #endif BASE_EXPORT BASE_DECLARE_FEATURE(kEnableHangWatcher); +BASE_EXPORT BASE_DECLARE_FEATURE(kEnableHangWatcherOnGpuProcess); +BASE_EXPORT extern const char kHangWatcherMonitoringPeriodParam[]; + +// Hang watcher log levels. +BASE_EXPORT extern const char kBrowserProcessIoThreadLogLevelParam[]; +BASE_EXPORT extern const char kBrowserProcessUiThreadLogLevelParam[]; +BASE_EXPORT extern const char kBrowserProcessThreadPoolLogLevelParam[]; + +BASE_EXPORT extern const char kGpuProcessIoThreadLogLevelParam[]; +BASE_EXPORT extern const char kGpuProcessMainThreadLogLevelParam[]; +BASE_EXPORT extern const char kGpuProcessCompositorThreadLogLevelParam[]; +BASE_EXPORT extern const char kGpuProcessThreadPoolLogLevelParam[]; + +BASE_EXPORT extern const char kRendererProcessIoThreadLogLevelParam[]; +BASE_EXPORT extern const char kRendererProcessMainThreadLogLevelParam[]; +BASE_EXPORT extern const char kRendererProcessThreadPoolLogLevelParam[]; +BASE_EXPORT extern const char kRendererProcessCompositorThreadLogLevelParam[]; + +BASE_EXPORT extern const char kUtilityProcessIoThreadLogLevelParam[]; +BASE_EXPORT extern const char kUtilityProcessMainThreadLogLevelParam[]; +BASE_EXPORT extern const char kUtilityProcessThreadPoolLogLevelParam[]; } // namespace base diff --git a/naiveproxy/src/base/time/time_exploded_posix.cc b/naiveproxy/src/base/time/time_exploded_posix.cc index 86ebdacdaf..4aa65fb138 100644 --- a/naiveproxy/src/base/time/time_exploded_posix.cc +++ b/naiveproxy/src/base/time/time_exploded_posix.cc @@ -19,9 +19,6 @@ #if BUILDFLAG(IS_ANDROID) && !defined(__LP64__) #include #endif -#if BUILDFLAG(IS_NACL) -#include "base/os_compat_nacl.h" -#endif namespace { @@ -186,7 +183,7 @@ bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) { timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this timestruct.tm_yday = 0; // mktime/timegm ignore this timestruct.tm_isdst = -1; // attempt to figure it out -#if !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_SOLARIS) && !BUILDFLAG(IS_AIX) +#if !BUILDFLAG(IS_SOLARIS) && !BUILDFLAG(IS_AIX) timestruct.tm_gmtoff = 0; // not a POSIX field, so mktime/timegm ignore timestruct.tm_zone = nullptr; // not a POSIX field, so mktime/timegm ignore #endif diff --git a/naiveproxy/src/base/time/time_now_posix.cc b/naiveproxy/src/base/time/time_now_posix.cc index 11caba7fe3..88a80e8e2b 100644 --- a/naiveproxy/src/base/time/time_now_posix.cc +++ b/naiveproxy/src/base/time/time_now_posix.cc @@ -26,13 +26,6 @@ #error "This implementation is for POSIX platforms other than Fuchsia or Mac." #endif -// NaCl doesn't support CLOCK_MONOTONIC_COARSE. -#if BUILDFLAG(IS_NACL) -#define TIMETICKS_LOW_RESOLUTION_CLOCK CLOCK_MONOTONIC -#else -#define TIMETICKS_LOW_RESOLUTION_CLOCK CLOCK_MONOTONIC_COARSE -#endif - namespace { int64_t ConvertTimespecToMicros(const struct timespec& ts) { @@ -117,7 +110,7 @@ std::optional MaybeTimeTicksNowIgnoringOverride() { } TimeTicks TimeTicksLowResolutionNowIgnoringOverride() { - return TimeTicks() + Microseconds(ClockNow(TIMETICKS_LOW_RESOLUTION_CLOCK)); + return TimeTicks() + Microseconds(ClockNow(CLOCK_MONOTONIC_COARSE)); } } // namespace subtle diff --git a/naiveproxy/src/base/time/time_win.cc b/naiveproxy/src/base/time/time_win.cc index 475ebf31c4..7727ed7e25 100644 --- a/naiveproxy/src/base/time/time_win.cc +++ b/naiveproxy/src/base/time/time_win.cc @@ -835,7 +835,8 @@ ThreadTicks ThreadTicks::GetForThread( ::GetThreadTimes(thread_handle.platform_handle(), &creation_time, &exit_time, &kernel_time, &user_time); - const int64_t us = FileTimeToMicroseconds(user_time); + const int64_t us = + FileTimeToMicroseconds(user_time) + FileTimeToMicroseconds(kernel_time); #else // Get the number of TSC ticks used by the current thread. ULONG64 thread_cycle_time = 0; diff --git a/naiveproxy/src/base/timer/timer.h b/naiveproxy/src/base/timer/timer.h index 2a1fbc4675..96781894ba 100644 --- a/naiveproxy/src/base/timer/timer.h +++ b/naiveproxy/src/base/timer/timer.h @@ -294,7 +294,8 @@ class BASE_EXPORT RepeatingTimer : public internal::DelayTimerBase { TimeDelta delay, Receiver* receiver, void (Receiver::*method)()) { - Start(posted_from, delay, BindRepeating(method, Unretained(receiver))); + Start(posted_from, delay, + base::BindRepeating(method, base::Unretained(receiver))); } const RepeatingClosure& user_task() const LIFETIME_BOUND { diff --git a/naiveproxy/src/base/trace_event/auto_open_close_event.h b/naiveproxy/src/base/trace_event/auto_open_close_event.h index 5862d16244..daa507626d 100644 --- a/naiveproxy/src/base/trace_event/auto_open_close_event.h +++ b/naiveproxy/src/base/trace_event/auto_open_close_event.h @@ -10,6 +10,7 @@ #include "base/threading/thread_checker.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" +#include "base/trace_event/trace_log.h" namespace base { namespace trace_event { diff --git a/naiveproxy/src/base/trace_event/builtin_categories.h b/naiveproxy/src/base/trace_event/builtin_categories.h index 467ce5cd72..6c811af11e 100644 --- a/naiveproxy/src/base/trace_event/builtin_categories.h +++ b/naiveproxy/src/base/trace_event/builtin_categories.h @@ -26,7 +26,7 @@ PERFETTO_DEFINE_TEST_CATEGORY_PREFIXES("cat", // the name. // See https://perfetto.dev/docs/instrumentation/track-events. // -// Naming Convention: Follow the `component.category(.sub_category)(.debug)` +// Naming Convention: Follow the `namespace.category(.sub_category)(.debug)` // naming convention for new categories. // Example: `base.scheduling`, `base.scheduling.debug` // @@ -86,6 +86,9 @@ PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE_WITH_ATTRS( perfetto::Category("blink.worker"), perfetto::Category("blink_style"), perfetto::Category("Blob"), + perfetto::Category("base.power").SetDescription( + "Events about global system power and battery/thermal state.") + .SetTags("toplevel"), perfetto::Category("browser").SetTags("navigation"), perfetto::Category("browsing_data"), perfetto::Category("CacheStorage"), @@ -197,9 +200,10 @@ PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE_WITH_ATTRS( "ScenarioScope::kCurrentProcess are emitted to an async track under " "each process track, and events for ScenarioScope::kGlobal are emitted " "to global async tracks."), + perfetto::Category("performance_manager.cpu_metrics").SetDescription( + "Events reporting cpu metrics computed in performance_manager"), perfetto::Category("persistent_cache"), perfetto::Category("PlatformMalloc"), - perfetto::Category("power"), perfetto::Category("ppapi"), perfetto::Category("ppapi_proxy"), perfetto::Category("print"), @@ -249,19 +253,23 @@ PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE_WITH_ATTRS( perfetto::Category("wayland"), perfetto::Category("webaudio").SetTags("audio"), perfetto::Category("webengine.fidl"), - perfetto::Category("weblayer"), perfetto::Category("WebCore"), perfetto::Category("webnn"), perfetto::Category("webrtc").SetTags("audio", "video"), perfetto::Category("webrtc_stats"), perfetto::Category("xr"), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("android_view_hierarchy")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("animation-worklet")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("audio")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("audio.latency")), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("android_view_hierarchy")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("animation-worklet")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("audio")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("audio.latency")) + .SetTags("slow"), perfetto::Category(TRACE_DISABLED_BY_DEFAULT("audio-worklet")) - .SetTags("audio"), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("base")), + .SetTags("audio", "slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("base")) + .SetTags("slow"), perfetto::Category(TRACE_DISABLED_BY_DEFAULT("blink.debug")) .SetTags("debug"), perfetto::Category(TRACE_DISABLED_BY_DEFAULT("blink.debug.display_lock")) @@ -270,13 +278,19 @@ PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE_WITH_ATTRS( .SetTags("debug"), perfetto::Category(TRACE_DISABLED_BY_DEFAULT("blink.debug.layout.trees")) .SetTags("debug"), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("blink.feature_usage")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("blink.image_decoding")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("blink.invalidation")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("identifiability")), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("blink.feature_usage")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("blink.image_decoding")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("blink.invalidation")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("identifiability")) + .SetTags("slow"), perfetto::Category( - TRACE_DISABLED_BY_DEFAULT("identifiability.high_entropy_api")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("cc")), + TRACE_DISABLED_BY_DEFAULT("identifiability.high_entropy_api")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("cc")) + .SetTags("slow"), perfetto::Category(TRACE_DISABLED_BY_DEFAULT("cc.debug")).SetTags("debug"), perfetto::Category(TRACE_DISABLED_BY_DEFAULT("cc.debug.cdp-perf")) .SetTags("debug"), @@ -292,102 +306,158 @@ PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE_WITH_ATTRS( .SetTags("debug"), perfetto::Category(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.now")) .SetTags("debug"), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("content.verbose")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("cpu_profiler")), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("content.verbose")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("cpu_profiler")) + .SetTags("slow"), perfetto::Category(TRACE_DISABLED_BY_DEFAULT("cpu_profiler.debug")) .SetTags("debug"), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("crypto.dpapi")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("devtools.screenshot")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("devtools.timeline")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.frame")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.inputs")), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("crypto.dpapi")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("devtools.screenshot")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("devtools.timeline")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.frame")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.inputs")) + .SetTags("slow"), perfetto::Category( - TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.layers")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.picture")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("devtools.target-rundown")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("devtools.v8-source-rundown")), + TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.layers")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.picture")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("devtools.target-rundown")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("devtools.v8-source-rundown")) + .SetTags("slow"), perfetto::Category( - TRACE_DISABLED_BY_DEFAULT("devtools.v8-source-rundown-sources")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("file")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("fonts")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("gpu_cmd_queue")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("gpu.dawn")), + TRACE_DISABLED_BY_DEFAULT("devtools.v8-source-rundown-sources")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("file")).SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("fonts")).SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("gpu_cmd_queue")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("gpu.dawn")).SetTags("slow"), perfetto::Category(TRACE_DISABLED_BY_DEFAULT("gpu.debug")).SetTags("debug"), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("gpu.decoder")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("gpu.device")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("gpu.graphite.dawn")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("gpu.service")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("gpu.vulkan.vma")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("histogram_samples")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("java-heap-profiler")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("layer-element")), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("gpu.decoder")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("gpu.device")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("gpu.graphite.dawn")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("gpu.service")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("gpu.vulkan.vma")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("histogram_samples")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("java-heap-profiler")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("layer-element")) + .SetTags("slow"), perfetto::Category(TRACE_DISABLED_BY_DEFAULT("layout_shift.debug")) .SetTags("debug"), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("lifecycles")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("loading")), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("lifecycles")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("loading")).SetTags("slow"), perfetto::Category(TRACE_DISABLED_BY_DEFAULT("mediastream")) - .SetTags("audio"), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("memory-infra")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("memory-infra.v8.code_stats")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("mojom")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("navigation")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("net")), + .SetTags("audio", "slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("memory-infra")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("memory-infra.v8.code_stats")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("mojom")).SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("navigation")).SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("net")).SetTags("slow"), perfetto::Category(TRACE_DISABLED_BY_DEFAULT("netlog.sensitive")).SetTags( - "navigation", "sensitive").SetDescription( + "navigation", "sensitive", "slow").SetDescription( "NetLog events and metadata, including sensitive information such as " "hostnames, URLs, HTTP headers and other identifiable information. " "Describes the operation of the //net network stack, e.g. HTTP requests, " "TLS, DNS, connections, sockets, etc."), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("network")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("paint-worklet")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("power")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("system_metrics")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler")), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("network")).SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("paint-worklet")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("power")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("system_metrics")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler")) + .SetTags("slow"), perfetto::Category(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler.debug")) .SetTags("debug"), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("sequence_manager")), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("sequence_manager")) + .SetTags("slow"), perfetto::Category(TRACE_DISABLED_BY_DEFAULT("sequence_manager.debug")) .SetTags("debug"), perfetto::Category( - TRACE_DISABLED_BY_DEFAULT("sequence_manager.verbose_snapshots")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("skia")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("skia.gpu")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("skia.gpu.cache")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("skia.shaders")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("skottie")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("SyncFileSystem")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("system_power")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("thread_pool_diagnostics")), + TRACE_DISABLED_BY_DEFAULT("sequence_manager.verbose_snapshots")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("skia")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("skia.gpu")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("skia.gpu.cache")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("skia.shaders")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("skottie")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("SyncFileSystem")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("system_power")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("thread_pool_diagnostics")) + .SetTags("slow"), perfetto::Category(TRACE_DISABLED_BY_DEFAULT("toplevel.ipc")) - .SetTags("ipc"), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("user_action_samples")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("v8.compile")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("v8.inspector")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("v8.runtime")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("v8.runtime_stats")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("v8.runtime_stats_sampling")), + .SetTags("ipc", "slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("user_action_samples")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("v8.compile")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("v8.inspector")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("v8.runtime")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("v8.runtime_stats")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("v8.runtime_stats_sampling")) + .SetTags("slow"), perfetto::Category(TRACE_DISABLED_BY_DEFAULT("video_and_image_capture")) - .SetTags("video"), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("display.framedisplayed")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("viz.gpu_composite_time")), + .SetTags("video", "slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("display.framedisplayed")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("viz.gpu_composite_time")) + .SetTags("slow"), perfetto::Category(TRACE_DISABLED_BY_DEFAULT("viz.debug.overlay_planes")) .SetTags("debug"), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("viz.hit_testing_flow")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("viz.overdraw")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("viz.quads")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("viz.surface_id_flow")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("viz.surface_lifetime")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("viz.triangles")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("viz.visual_debugger")), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("viz.hit_testing_flow")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("viz.overdraw")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("viz.quads")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("viz.surface_id_flow")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("viz.surface_lifetime")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("viz.triangles")) + .SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("viz.visual_debugger")) + .SetTags("slow"), perfetto::Category(TRACE_DISABLED_BY_DEFAULT("webaudio.audionode")) - .SetTags("audio"), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("webgpu")), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("webnn")), + .SetTags("audio", "slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("webgpu")).SetTags("slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("webnn")).SetTags("slow"), perfetto::Category(TRACE_DISABLED_BY_DEFAULT("webrtc")) - .SetTags("audio", "video"), - perfetto::Category(TRACE_DISABLED_BY_DEFAULT("worker.scheduler")), + .SetTags("audio", "video", "slow"), + perfetto::Category(TRACE_DISABLED_BY_DEFAULT("worker.scheduler")) + .SetTags("slow"), perfetto::Category(TRACE_DISABLED_BY_DEFAULT("xr.debug")).SetTags("debug"), perfetto::Category::Group("android_webview,toplevel"), perfetto::Category::Group("android_webview.timeline,android.ui.jank"), diff --git a/naiveproxy/src/base/trace_event/common/trace_event_common.h b/naiveproxy/src/base/trace_event/common/trace_event_common.h index d392af2ea8..cae05f5413 100644 --- a/naiveproxy/src/base/trace_event/common/trace_event_common.h +++ b/naiveproxy/src/base/trace_event/common/trace_event_common.h @@ -74,11 +74,4 @@ struct BASE_EXPORT TraceTimestampTraits<::base::TimeTicks> { } // namespace perfetto -// This macro is still used in some components even when base tracing is -// disabled. -// TODO(crbug/336718643): Make sure no code affected by -// enable_base_tracing=false includes this file directly, then move the define -// to trace_event_stub.h. -#define TRACE_DISABLED_BY_DEFAULT(name) "disabled-by-default-" name - #endif // BASE_TRACE_EVENT_COMMON_TRACE_EVENT_COMMON_H_ diff --git a/naiveproxy/src/base/trace_event/cpufreq_monitor_android.cc b/naiveproxy/src/base/trace_event/cpufreq_monitor_android.cc index 87e3e8dfca..4317e2e6cd 100644 --- a/naiveproxy/src/base/trace_event/cpufreq_monitor_android.cc +++ b/naiveproxy/src/base/trace_event/cpufreq_monitor_android.cc @@ -2,15 +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/40284755): Remove this and spanify to fix the errors. -#pragma allow_unsafe_buffers -#endif - #include "base/trace_event/cpufreq_monitor_android.h" #include +#include "base/compiler_specific.h" #include "base/files/file_util.h" #include "base/files/scoped_file.h" #include "base/functional/bind.h" @@ -209,9 +205,9 @@ void CPUFreqMonitor::Sample( ssize_t bytes_read = read(fd, data, kNumBytesToReadForSampling); if (bytes_read > 0) { if (static_cast(bytes_read) < kNumBytesToReadForSampling) { - data[static_cast(bytes_read)] = '\0'; + UNSAFE_TODO(data[static_cast(bytes_read)]) = '\0'; } - int ret = sscanf(data, "%d", &freq); + int ret = UNSAFE_TODO(sscanf(data, "%d", &freq)); if (ret == 0 || ret == std::char_traits::eof()) { freq = 0; } diff --git a/naiveproxy/src/base/trace_event/heap_profiler_allocation_context.cc b/naiveproxy/src/base/trace_event/heap_profiler_allocation_context.cc index 532be7d912..5b691deb49 100644 --- a/naiveproxy/src/base/trace_event/heap_profiler_allocation_context.cc +++ b/naiveproxy/src/base/trace_event/heap_profiler_allocation_context.cc @@ -2,17 +2,13 @@ // 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/trace_event/heap_profiler_allocation_context.h" #include #include #include +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/hash/hash.h" @@ -32,7 +28,8 @@ bool operator==(const Backtrace& lhs, const Backtrace& rhs) { if (lhs.frame_count != rhs.frame_count) { return false; } - return std::equal(lhs.frames, lhs.frames + lhs.frame_count, rhs.frames); + return std::equal(lhs.frames, UNSAFE_TODO(lhs.frames + lhs.frame_count), + rhs.frames); } AllocationContext::AllocationContext() : type_name(nullptr) {} @@ -56,7 +53,7 @@ size_t hash::operator()(const StackFrame& frame) const { size_t hash::operator()(const Backtrace& backtrace) const { std::array values; for (size_t i = 0; i != backtrace.frame_count; ++i) { - values[i] = backtrace.frames[i].value; + values[i] = UNSAFE_TODO(backtrace.frames[i]).value; } return base::PersistentHash( base::as_bytes(base::span(values).first(backtrace.frame_count))); diff --git a/naiveproxy/src/base/trace_event/interned_args_helper.cc b/naiveproxy/src/base/trace_event/interned_args_helper.cc index b230b97a55..d4168157fe 100644 --- a/naiveproxy/src/base/trace_event/interned_args_helper.cc +++ b/naiveproxy/src/base/trace_event/interned_args_helper.cc @@ -43,7 +43,9 @@ void InternedSourceLocation::Add( if (location.function_name != nullptr) { msg->set_function_name(location.function_name); } - // TODO(ssid): Add line number once it is allowed in internal proto. + if (location.line_number != 0) { + msg->set_line_number(static_cast(location.line_number)); + } // TODO(ssid): Add program counter to the proto fields when // !BUILDFLAG(ENABLE_LOCATION_SOURCE). // TODO(http://crbug.com760702) remove file name and just pass the program diff --git a/naiveproxy/src/base/trace_event/memory_allocator_dump.cc b/naiveproxy/src/base/trace_event/memory_allocator_dump.cc index d624c24da0..d80f704b1e 100644 --- a/naiveproxy/src/base/trace_event/memory_allocator_dump.cc +++ b/naiveproxy/src/base/trace_event/memory_allocator_dump.cc @@ -2,15 +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/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "base/trace_event/memory_allocator_dump.h" #include +#include "base/compiler_specific.h" #include "base/format_macros.h" #include "base/memory/ptr_util.h" #include "base/notreached.h" @@ -146,7 +142,7 @@ uint64_t MemoryAllocatorDump::GetSizeInternal() const { } for (const auto& entry : entries_) { if (entry.entry_type == Entry::kUint64 && entry.units == kUnitsBytes && - strcmp(entry.name.c_str(), kNameSize) == 0) { + UNSAFE_TODO(strcmp(entry.name.c_str(), kNameSize)) == 0) { cached_size_ = entry.value_uint64; return entry.value_uint64; } diff --git a/naiveproxy/src/base/trace_event/memory_dump_manager.cc b/naiveproxy/src/base/trace_event/memory_dump_manager.cc index 6f9561cc8e..d12a8bf8e4 100644 --- a/naiveproxy/src/base/trace_event/memory_dump_manager.cc +++ b/naiveproxy/src/base/trace_event/memory_dump_manager.cc @@ -313,16 +313,6 @@ void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args, TRACE_ID_LOCAL(args.dump_guid), "dump_guid", TRACE_STR_COPY(guid_str)); - // If argument filter is enabled then only background mode dumps should be - // allowed. In case the trace config passed for background tracing session - // missed the allowed modes argument, it crashes here instead of creating - // unexpected dumps. - if (TraceLog::GetInstance() - ->GetCurrentTraceConfig() - .IsArgumentFilterEnabled()) { - CHECK_EQ(MemoryDumpLevelOfDetail::kBackground, args.level_of_detail); - } - std::unique_ptr pmd_async_state; { AutoLock lock(lock_); diff --git a/naiveproxy/src/base/trace_event/memory_dump_manager.h b/naiveproxy/src/base/trace_event/memory_dump_manager.h index ef12d9df76..4e9ccfa32f 100644 --- a/naiveproxy/src/base/trace_event/memory_dump_manager.h +++ b/naiveproxy/src/base/trace_event/memory_dump_manager.h @@ -9,7 +9,6 @@ #include #include -#include #include #include "base/base_export.h" @@ -20,6 +19,7 @@ #include "base/trace_event/memory_dump_provider_info.h" #include "base/trace_event/memory_dump_request_args.h" #include "base/trace_event/process_memory_dump.h" +#include "base/trace_event/trace_config.h" #include "base/trace_event/trace_event.h" namespace base { diff --git a/naiveproxy/src/base/trace_event/process_memory_dump.cc b/naiveproxy/src/base/trace_event/process_memory_dump.cc index c1896eb523..64bb018826 100644 --- a/naiveproxy/src/base/trace_event/process_memory_dump.cc +++ b/naiveproxy/src/base/trace_event/process_memory_dump.cc @@ -67,11 +67,9 @@ std::string GetSharedGlobalAllocatorDumpName( return "global/" + guid.ToString(); } -#if defined(COUNT_RESIDENT_BYTES_SUPPORTED) size_t GetSystemPageCount(size_t mapped_size, size_t page_size) { return (mapped_size + page_size - 1) / page_size; } -#endif UnguessableToken GetTokenForCurrentProcess() { static UnguessableToken instance = UnguessableToken::Create(); @@ -83,7 +81,6 @@ UnguessableToken GetTokenForCurrentProcess() { // static bool ProcessMemoryDump::is_black_hole_non_fatal_for_testing_ = false; -#if defined(COUNT_RESIDENT_BYTES_SUPPORTED) // static size_t ProcessMemoryDump::GetSystemPageSize() { #if BUILDFLAG(IS_IOS) @@ -271,8 +268,6 @@ std::optional ProcessMemoryDump::CountResidentBytesInSharedMemory( #endif // BUILDFLAG(IS_MAC) } -#endif // defined(COUNT_RESIDENT_BYTES_SUPPORTED) - ProcessMemoryDump::ProcessMemoryDump(const MemoryDumpArgs& dump_args) : process_token_(GetTokenForCurrentProcess()), dump_args_(dump_args) {} diff --git a/naiveproxy/src/base/trace_event/process_memory_dump.h b/naiveproxy/src/base/trace_event/process_memory_dump.h index d9915796c6..8bc08b0189 100644 --- a/naiveproxy/src/base/trace_event/process_memory_dump.h +++ b/naiveproxy/src/base/trace_event/process_memory_dump.h @@ -21,12 +21,6 @@ #include "base/trace_event/memory_dump_request_args.h" #include "build/build_config.h" -// Define COUNT_RESIDENT_BYTES_SUPPORTED if platform supports counting of the -// resident memory. -#if !BUILDFLAG(IS_NACL) -#define COUNT_RESIDENT_BYTES_SUPPORTED -#endif - namespace perfetto { namespace protos { namespace pbzero { @@ -66,7 +60,6 @@ class BASE_EXPORT ProcessMemoryDump { using AllocatorDumpEdgesMap = std::map; -#if defined(COUNT_RESIDENT_BYTES_SUPPORTED) // Returns the number of bytes in a kernel memory page. Some platforms may // have a different value for kernel page sizes from user page sizes. It is // important to use kernel memory page sizes for resident bytes calculation. @@ -85,7 +78,6 @@ class BASE_EXPORT ProcessMemoryDump { static std::optional CountResidentBytesInSharedMemory( void* start_address, size_t mapped_size); -#endif explicit ProcessMemoryDump(const MemoryDumpArgs& dump_args); ProcessMemoryDump(ProcessMemoryDump&&); diff --git a/naiveproxy/src/base/trace_event/trace_arguments.h b/naiveproxy/src/base/trace_event/trace_arguments.h index f4325bd1a4..dad1a04c68 100644 --- a/naiveproxy/src/base/trace_event/trace_arguments.h +++ b/naiveproxy/src/base/trace_event/trace_arguments.h @@ -19,6 +19,7 @@ #include #include "base/base_export.h" +#include "base/containers/span.h" #include "base/memory/raw_ptr_exclusion.h" #include "base/trace_event/common/trace_event_common.h" #include "base/tracing_buildflags.h" @@ -610,31 +611,6 @@ class BASE_EXPORT TraceArguments { const unsigned char* arg_types, const unsigned long long* arg_values); - // Constructor used to convert legacy set of arguments, where the - // convertable values are also provided by an array of CONVERTABLE_TYPE. - template - TraceArguments(int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - CONVERTABLE_TYPE* arg_convertables) { - static int max_args = static_cast(kMaxSize); - if (num_args > max_args) { - num_args = max_args; - } - size_ = static_cast(num_args); - for (size_t n = 0; n < size_; ++n) { - types_[n] = arg_types[n]; - names_[n] = arg_names[n]; - if (arg_types[n] == TRACE_VALUE_TYPE_CONVERTABLE) { - values_[n].Init( - std::forward(std::move(arg_convertables[n]))); - } else { - values_[n].as_uint = arg_values[n]; - } - } - } - // Destructor. NOTE: Intentionally inlined (see note above). ~TraceArguments() { for (size_t n = 0; n < size_; ++n) { diff --git a/naiveproxy/src/base/trace_event/trace_config.cc b/naiveproxy/src/base/trace_event/trace_config.cc index 6c1a1bea9a..a9012f23d9 100644 --- a/naiveproxy/src/base/trace_event/trace_config.cc +++ b/naiveproxy/src/base/trace_event/trace_config.cc @@ -317,7 +317,7 @@ TraceConfig& TraceConfig::operator=(const TraceConfig& rhs) { record_mode_ = rhs.record_mode_; trace_buffer_size_in_events_ = rhs.trace_buffer_size_in_events_; - trace_buffer_size_in_kb_ = rhs.trace_buffer_size_in_kb_; + trace_buffer_size_in_bytes_ = rhs.trace_buffer_size_in_bytes_; enable_systrace_ = rhs.enable_systrace_; enable_argument_filter_ = rhs.enable_argument_filter_; category_filter_ = rhs.category_filter_; @@ -410,7 +410,7 @@ void TraceConfig::Merge(const TraceConfig& config) { void TraceConfig::Clear() { record_mode_ = RECORD_UNTIL_FULL; trace_buffer_size_in_events_ = 0; - trace_buffer_size_in_kb_ = 0; + trace_buffer_size_in_bytes_ = ByteCount(0); enable_systrace_ = false; enable_argument_filter_ = false; enable_event_package_name_filter_ = false; @@ -425,7 +425,7 @@ void TraceConfig::Clear() { void TraceConfig::InitializeDefault() { record_mode_ = RECORD_UNTIL_FULL; trace_buffer_size_in_events_ = 0; - trace_buffer_size_in_kb_ = 0; + trace_buffer_size_in_bytes_ = ByteCount(0); enable_systrace_ = false; enable_argument_filter_ = false; enable_event_package_name_filter_ = false; @@ -447,8 +447,8 @@ void TraceConfig::InitializeFromConfigDict(const Value::Dict& dict) { } trace_buffer_size_in_events_ = base::saturated_cast( dict.FindInt(kTraceBufferSizeInEvents).value_or(0)); - trace_buffer_size_in_kb_ = base::saturated_cast( - dict.FindInt(kTraceBufferSizeInKb).value_or(0)); + trace_buffer_size_in_bytes_ = + KiB(dict.FindInt(kTraceBufferSizeInKb).value_or(0)); enable_systrace_ = dict.FindBool(kEnableSystraceParam).value_or(false); enable_argument_filter_ = @@ -508,7 +508,7 @@ void TraceConfig::InitializeFromStrings(std::string_view category_filter_string, record_mode_ = RECORD_UNTIL_FULL; trace_buffer_size_in_events_ = 0; - trace_buffer_size_in_kb_ = 0; + trace_buffer_size_in_bytes_ = ByteCount(0); enable_systrace_ = false; systrace_events_.clear(); enable_argument_filter_ = false; @@ -674,9 +674,9 @@ Value TraceConfig::ToValue() const { dict.Set(kTraceBufferSizeInEvents, base::checked_cast(trace_buffer_size_in_events_)); } - if (trace_buffer_size_in_kb_ > 0) { + if (trace_buffer_size_in_bytes_.InBytes() > 0) { dict.Set(kTraceBufferSizeInKb, - base::checked_cast(trace_buffer_size_in_kb_)); + base::checked_cast(trace_buffer_size_in_bytes_.InKiB())); } dict.Set(kEnableEventPackageNameFilterParam, diff --git a/naiveproxy/src/base/trace_event/trace_config.h b/naiveproxy/src/base/trace_event/trace_config.h index 01378e6ea1..04a6e9e94b 100644 --- a/naiveproxy/src/base/trace_event/trace_config.h +++ b/naiveproxy/src/base/trace_event/trace_config.h @@ -15,6 +15,7 @@ #include #include "base/base_export.h" +#include "base/byte_count.h" #include "base/compiler_specific.h" #include "base/gtest_prod_util.h" #include "base/trace_event/memory_dump_request_args.h" @@ -246,7 +247,9 @@ class BASE_EXPORT TraceConfig { size_t GetTraceBufferSizeInEvents() const { return trace_buffer_size_in_events_; } - size_t GetTraceBufferSizeInKb() const { return trace_buffer_size_in_kb_; } + ByteCount GetTraceBufferSizeInBytes() const { + return trace_buffer_size_in_bytes_; + } bool IsSystraceEnabled() const { return enable_systrace_; } bool IsArgumentFilterEnabled() const { return enable_argument_filter_; } @@ -254,7 +257,9 @@ class BASE_EXPORT TraceConfig { void SetTraceBufferSizeInEvents(size_t size) { trace_buffer_size_in_events_ = size; } - void SetTraceBufferSizeInKb(size_t size) { trace_buffer_size_in_kb_ = size; } + void SetTraceBufferSizeInBytes(ByteCount bytes) { + trace_buffer_size_in_bytes_ = bytes; + } void EnableSystrace() { enable_systrace_ = true; } void EnableSystraceEvent(const std::string& systrace_event); void EnableArgumentFilter() { enable_argument_filter_ = true; } @@ -361,7 +366,7 @@ class BASE_EXPORT TraceConfig { TraceRecordMode record_mode_; size_t trace_buffer_size_in_events_ = 0; // 0 specifies default size - size_t trace_buffer_size_in_kb_ = 0; // 0 specifies default size + ByteCount trace_buffer_size_in_bytes_; bool enable_systrace_ : 1; bool enable_argument_filter_ : 1; diff --git a/naiveproxy/src/base/trace_event/trace_config_category_filter.cc b/naiveproxy/src/base/trace_event/trace_config_category_filter.cc index 41d5df3d03..6750d4a1d9 100644 --- a/naiveproxy/src/base/trace_event/trace_config_category_filter.cc +++ b/naiveproxy/src/base/trace_event/trace_config_category_filter.cc @@ -5,6 +5,7 @@ #include "base/trace_event/trace_config_category_filter.h" #include +#include #include "base/memory/ptr_util.h" #include "base/strings/pattern.h" diff --git a/naiveproxy/src/base/trace_event/trace_event.h b/naiveproxy/src/base/trace_event/trace_event.h index a0db10752e..42dc76fe75 100644 --- a/naiveproxy/src/base/trace_event/trace_event.h +++ b/naiveproxy/src/base/trace_event/trace_event.h @@ -23,7 +23,7 @@ #include "base/trace_event/builtin_categories.h" #include "base/trace_event/common/trace_event_common.h" // IWYU pragma: export #include "base/trace_event/trace_arguments.h" -#include "base/trace_event/trace_log.h" +#include "base/trace_event/trace_event_impl.h" #include "base/trace_event/traced_value_support.h" #include "base/tracing_buildflags.h" diff --git a/naiveproxy/src/base/trace_event/trace_event_impl.cc b/naiveproxy/src/base/trace_event/trace_event_impl.cc index 828c62d531..bdee289797 100644 --- a/naiveproxy/src/base/trace_event/trace_event_impl.cc +++ b/naiveproxy/src/base/trace_event/trace_event_impl.cc @@ -2,17 +2,13 @@ // 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/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "base/trace_event/trace_event_impl.h" #include #include +#include "base/compiler_specific.h" #include "base/format_macros.h" #include "base/json/string_escape.h" #include "base/memory/ptr_util.h" @@ -169,7 +165,7 @@ void TraceEvent::AppendAsJSON( thread_id = thread_id_; } const char* category_group_name = - TraceLog::GetCategoryGroupName(category_group_enabled_); + TRACE_EVENT_API_GET_CATEGORY_GROUP_NAME(category_group_enabled_.get()); // The thread id might be an int64, however int64 values are not // representable in JS and JSON (cf. crbug.com/40228085) since JS @@ -185,7 +181,7 @@ void TraceEvent::AppendAsJSON( thread_id ? thread_id->truncate_to_int32_for_display_only() : -1; // Category group checked at category creation time. - DCHECK(!strchr(name_, '"')); + UNSAFE_TODO(DCHECK(!strchr(name_, '"'))); StringAppendF(out, "{\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 ",\"ph\":\"%c\",\"cat\":\"%s\",\"name\":", @@ -323,7 +319,8 @@ void TraceEvent::AppendAsJSON( void TraceEvent::AppendPrettyPrinted(std::ostringstream* out) const { *out << name_ << "["; - *out << TraceLog::GetCategoryGroupName(category_group_enabled_); + *out << TRACE_EVENT_API_GET_CATEGORY_GROUP_NAME( + category_group_enabled_.get()); *out << "]"; if (arg_size() > 0 && arg_name(0)) { *out << ", {"; diff --git a/naiveproxy/src/base/trace_event/trace_log.cc b/naiveproxy/src/base/trace_event/trace_log.cc index d5dddba559..910972916d 100644 --- a/naiveproxy/src/base/trace_event/trace_log.cc +++ b/naiveproxy/src/base/trace_event/trace_log.cc @@ -140,9 +140,8 @@ void WriteDebugAnnotations(base::trace_event::TraceEvent* trace_event, // using an override here. // TODO(crbug.com/343404899): Remove when all embedders migrate to Perfetto. void OnAddLegacyTraceEvent(TraceEvent* trace_event) { - perfetto::DynamicCategory category( - TraceLog::GetInstance()->GetCategoryGroupName( - trace_event->category_group_enabled())); + perfetto::DynamicCategory category(TRACE_EVENT_API_GET_CATEGORY_GROUP_NAME( + trace_event->category_group_enabled())); auto phase = trace_event->phase(); if (phase == TRACE_EVENT_PHASE_COMPLETE) { @@ -174,6 +173,11 @@ void OnAddLegacyTraceEvent(TraceEvent* trace_event) { default: break; } + if (trace_event->flags() & TRACE_EVENT_FLAG_HAS_PROCESS_ID) { + legacy_event->set_pid_override( + trace_event->thread_id().truncate_to_int32_for_display_only()); + legacy_event->set_tid_override(static_cast(-1)); + } }; auto flags = trace_event->flags(); @@ -199,7 +203,8 @@ void OnAddLegacyTraceEvent(TraceEvent* trace_event) { } } if (trace_event->thread_id() != kInvalidThreadId && - trace_event->thread_id() != base::PlatformThread::CurrentId()) { + trace_event->thread_id() != base::PlatformThread::CurrentId() && + !(trace_event->flags() & TRACE_EVENT_FLAG_HAS_PROCESS_ID)) { PERFETTO_INTERNAL_LEGACY_EVENT_ON_TRACK( phase, category, trace_event->name(), perfetto::ThreadTrack::ForThread(trace_event->thread_id().raw()), @@ -220,7 +225,7 @@ void OnUpdateLegacyTraceEventDuration( const TimeTicks& now, const ThreadTicks& thread_now) { perfetto::DynamicCategory category( - TraceLog::GetInstance()->GetCategoryGroupName(category_group_enabled)); + TRACE_EVENT_API_GET_CATEGORY_GROUP_NAME(category_group_enabled)); auto phase = TRACE_EVENT_PHASE_END; base::TimeTicks timestamp = explicit_timestamps ? now : TRACE_TIME_TICKS_NOW(); @@ -363,11 +368,7 @@ void TraceLog::ResetForTesting() { } TraceLog::TraceLog() : process_id_(base::kNullProcessId) { -#if BUILDFLAG(IS_NACL) // NaCl shouldn't expose the process id. - SetProcessID(0); -#else SetProcessID(GetCurrentProcId()); -#endif TrackEvent::AddSessionObserver(this); g_trace_log_for_testing = this; } @@ -376,16 +377,6 @@ TraceLog::~TraceLog() { TrackEvent::RemoveSessionObserver(this); } -const unsigned char* TraceLog::GetCategoryGroupEnabled( - const char* category_group) { - return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group); -} - -const char* TraceLog::GetCategoryGroupName( - const unsigned char* category_group_enabled) { - return TRACE_EVENT_API_GET_CATEGORY_GROUP_NAME(category_group_enabled); -} - void TraceLog::SetEnabled(const TraceConfig& trace_config) { DCHECK(trace_config.process_filter_config().IsEnabled(process_id_)); @@ -417,12 +408,12 @@ void TraceLog::SetEnabled(const TraceConfig& trace_config) { // TODO(khokhlov): Avoid duplication between this code and // services/tracing/public/cpp/perfetto/perfetto_config.cc. perfetto::TraceConfig perfetto_config; - size_t size_limit = trace_config.GetTraceBufferSizeInKb(); - if (size_limit == 0) { - size_limit = 200 * 1024; + ByteCount size_limit = trace_config.GetTraceBufferSizeInBytes(); + if (size_limit.is_zero()) { + size_limit = MiB(200); } auto* buffer_config = perfetto_config.add_buffers(); - buffer_config->set_size_kb(checked_cast(size_limit)); + buffer_config->set_size_kb(checked_cast(size_limit.InKiB())); switch (trace_config.GetTraceRecordMode()) { case base::trace_event::RECORD_UNTIL_FULL: case base::trace_event::RECORD_AS_MUCH_AS_POSSIBLE: @@ -483,15 +474,6 @@ std::vector TraceLog::GetTrackEventSessions() return track_event_sessions_; } -perfetto::DataSourceConfig TraceLog::GetCurrentTrackEventDataSourceConfig() - const { - AutoLock lock(track_event_lock_); - if (track_event_sessions_.empty()) { - return perfetto::DataSourceConfig(); - } - return track_event_sessions_[0].config; -} - void TraceLog::InitializePerfettoIfNeeded() { // When we're using the Perfetto client library, only tests should be // recording traces directly through TraceLog. Production code should instead @@ -569,12 +551,6 @@ MetadataFilterPredicate TraceLog::GetMetadataFilterPredicate() const { return metadata_filter_predicate_; } -TraceConfig TraceLog::GetCurrentTraceConfig() const { - const auto chrome_config = - GetCurrentTrackEventDataSourceConfig().chrome_config(); - return TraceConfig(chrome_config.trace_config()); -} - void TraceLog::SetDisabled() { AutoLock lock(lock_); SetDisabledWhileLocked(); diff --git a/naiveproxy/src/base/trace_event/trace_log.h b/naiveproxy/src/base/trace_event/trace_log.h index eeee810856..509e6d9092 100644 --- a/naiveproxy/src/base/trace_event/trace_log.h +++ b/naiveproxy/src/base/trace_event/trace_log.h @@ -48,9 +48,6 @@ class BASE_EXPORT TraceLog : public perfetto::TrackEventSessionObserver { TraceLog(const TraceLog&) = delete; TraceLog& operator=(const TraceLog&) = delete; - // Retrieves a copy (for thread-safety) of the current TraceConfig. - TraceConfig GetCurrentTraceConfig() const; - // See TraceConfig comments for details on how to control which categories // will be traced. void SetEnabled(const TraceConfig& trace_config); @@ -161,13 +158,6 @@ class BASE_EXPORT TraceLog : public perfetto::TrackEventSessionObserver { // Cancels tracing and discards collected data. void CancelTracing(const OutputCallback& cb); - // Called by TRACE_EVENT* macros, don't call this directly. - // The name parameter is a category group for example: - // TRACE_EVENT0("renderer,webkit", "WebViewImpl::HandleInputEvent") - static const unsigned char* GetCategoryGroupEnabled(const char* name); - static const char* GetCategoryGroupName( - const unsigned char* category_group_enabled); - ProcessId process_id() const { return process_id_; } // Exposed for unittesting: @@ -185,12 +175,6 @@ class BASE_EXPORT TraceLog : public perfetto::TrackEventSessionObserver { }; std::vector GetTrackEventSessions() const; - // DEPRECATED. In the presence of multiple simultaneous sessions, this method - // returns only the first session's config. When no tracing sessions are - // active, returns an empty config for compatibility with legacy code. - // TODO(khokhlov): Remove this method and migrate all its uses to - // GetTrackEventSessions(). - perfetto::DataSourceConfig GetCurrentTrackEventDataSourceConfig() const; void InitializePerfettoIfNeeded(); bool IsPerfettoInitializedByTraceLog() const; void SetEnabledImpl(const TraceConfig& trace_config, @@ -206,7 +190,7 @@ class BASE_EXPORT TraceLog : public perfetto::TrackEventSessionObserver { struct RegisteredAsyncObserver; - explicit TraceLog(); + TraceLog(); ~TraceLog() override; void SetDisabledWhileLocked() EXCLUSIVE_LOCKS_REQUIRED(lock_); diff --git a/naiveproxy/src/base/tracing/BUILD.gn b/naiveproxy/src/base/tracing/BUILD.gn index f550d1ac84..61bee55cc9 100644 --- a/naiveproxy/src/base/tracing/BUILD.gn +++ b/naiveproxy/src/base/tracing/BUILD.gn @@ -68,6 +68,7 @@ generate_wrapper("perfetto_diff_tests") { "//third_party/perfetto/protos/perfetto/metrics/chrome:descriptor", "//third_party/perfetto/protos/perfetto/trace:descriptor", "//third_party/perfetto/protos/perfetto/trace:test_extensions_descriptor", + "//third_party/perfetto/protos/perfetto/trace/android:winscope_descriptor", "//third_party/perfetto/src/trace_processor:trace_processor_shell", ] @@ -80,5 +81,6 @@ generate_wrapper("perfetto_diff_tests") { _metrics_descriptor, _all_chrome_metrics_descriptor, _chrome_track_event_descriptor, + _winscope_extensions_descriptor, ] } diff --git a/naiveproxy/src/base/tracing/perfetto_platform.cc b/naiveproxy/src/base/tracing/perfetto_platform.cc index 07a6a106c3..ee4539f198 100644 --- a/naiveproxy/src/base/tracing/perfetto_platform.cc +++ b/naiveproxy/src/base/tracing/perfetto_platform.cc @@ -9,18 +9,16 @@ #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "base/trace_event/trace_event.h" +#include "base/trace_event/trace_log.h" #include "base/tracing/perfetto_task_runner.h" #include "base/tracing_buildflags.h" #include "build/build_config.h" +#include "third_party/perfetto/include/perfetto/ext/base/thread_task_runner.h" #if BUILDFLAG(IS_ANDROID) #include "base/android/apk_info.h" #endif // BUILDFLAG(IS_ANDROID) -#if !BUILDFLAG(IS_NACL) -#include "third_party/perfetto/include/perfetto/ext/base/thread_task_runner.h" -#endif - namespace base::tracing { PerfettoPlatform::PerfettoPlatform( diff --git a/naiveproxy/src/base/tracing/perfetto_task_runner.cc b/naiveproxy/src/base/tracing/perfetto_task_runner.cc index 2a22e00523..6e6f049291 100644 --- a/naiveproxy/src/base/tracing/perfetto_task_runner.cc +++ b/naiveproxy/src/base/tracing/perfetto_task_runner.cc @@ -31,9 +31,9 @@ PerfettoTaskRunner::PerfettoTaskRunner( PerfettoTaskRunner::~PerfettoTaskRunner() { DCHECK(task_runner_->RunsTasksInCurrentSequence()); -#if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) fd_controllers_.clear(); -#endif // (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#endif // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) } void PerfettoTaskRunner::PostTask(std::function task) { @@ -77,7 +77,7 @@ bool PerfettoTaskRunner::RunsTasksOnCurrentThread() const { void PerfettoTaskRunner::AddFileDescriptorWatch( perfetto::base::PlatformHandle fd, std::function callback) { -#if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) DCHECK(task_runner_->RunsTasksInCurrentSequence()); DCHECK(!base::Contains(fd_controllers_, fd)); // Set up the |fd| in the map to signal intent to add a watch. We need to @@ -102,22 +102,22 @@ void PerfettoTaskRunner::AddFileDescriptorWatch( }, base::Unretained(this), fd, std::move(callback))); task_runner_->PostTask(FROM_HERE, fd_controllers_[fd].callback.callback()); -#else // (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#else // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) NOTREACHED(); -#endif // (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#endif // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) } void PerfettoTaskRunner::RemoveFileDescriptorWatch( perfetto::base::PlatformHandle fd) { -#if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) DCHECK(task_runner_->RunsTasksInCurrentSequence()); DCHECK(base::Contains(fd_controllers_, fd)); // This also cancels the base::FileDescriptorWatcher::WatchReadable() task if // it's pending. fd_controllers_.erase(fd); -#else // (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#else // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) NOTREACHED(); -#endif // (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#endif // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) } void PerfettoTaskRunner::ResetTaskRunner( @@ -130,13 +130,13 @@ void PerfettoTaskRunner::ResetTaskRunner( deferred_delayed_tasks_.clear(); } -#if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) PerfettoTaskRunner::FDControllerAndCallback::FDControllerAndCallback() = default; PerfettoTaskRunner::FDControllerAndCallback::~FDControllerAndCallback() = default; -#endif // (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#endif // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) PerfettoTaskRunner::DeferredTask::DeferredTask(std::function task, uint32_t delay) diff --git a/naiveproxy/src/base/tracing/perfetto_task_runner.h b/naiveproxy/src/base/tracing/perfetto_task_runner.h index 1e539a5fb2..72bcb196f6 100644 --- a/naiveproxy/src/base/tracing/perfetto_task_runner.h +++ b/naiveproxy/src/base/tracing/perfetto_task_runner.h @@ -16,13 +16,13 @@ #include "build/build_config.h" #include "third_party/perfetto/include/perfetto/base/task_runner.h" -#if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) // Needed for base::FileDescriptorWatcher::Controller and for implementing // AddFileDescriptorWatch & RemoveFileDescriptorWatch. #include #include "base/files/file_descriptor_watcher_posix.h" -#endif // (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#endif // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) namespace base { namespace tracing { @@ -76,7 +76,7 @@ class BASE_EXPORT PerfettoTaskRunner : public perfetto::base::TaskRunner { std::vector deferred_delayed_tasks_; bool defer_delayed_tasks_; -#if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) // FDControllerAndCallback keeps track of the state of FD watching: // * |controller| has value: FD watching is added. |callback| is nullopt. // * |controller| is nullptr: FD watching is pending for add. |callback| has @@ -92,7 +92,7 @@ class BASE_EXPORT PerfettoTaskRunner : public perfetto::base::TaskRunner { ~FDControllerAndCallback(); }; std::map fd_controllers_; -#endif // (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) +#endif // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) WeakPtrFactory weak_factory_{this}; }; diff --git a/naiveproxy/src/base/tracing/protos/BUILD.gn b/naiveproxy/src/base/tracing/protos/BUILD.gn index 1d16de6cbe..86a7a49f0b 100644 --- a/naiveproxy/src/base/tracing/protos/BUILD.gn +++ b/naiveproxy/src/base/tracing/protos/BUILD.gn @@ -7,16 +7,28 @@ import("//third_party/protobuf/proto_library.gni") import("//tools/grit/grit_rule.gni") import("sources.gni") +# Generates only a proto descriptor. This must only have a single entry in +# `sources`, because `generate_descriptor` adds a `--dependency_out` argument to +# protoc. With multiple sources protoc fails with the error: "Can only process +# one input file when using --dependency_out=FILE." proto_library("chrome_track_event") { proto_in_dir = "//" proto_out_dir = "base/tracing/protos" + sources = [ + # Wrapper file importing all files in `chrome_track_event_sources`. + chrome_track_event_descriptor_source, + ] import_dirs = [ "//third_party/perfetto/" ] - sources = chrome_track_event_sources generate_cc = false generate_python = false generate_descriptor = "chrome_track_event.descriptor" - deps = - [ "//third_party/perfetto/protos/perfetto/trace/track_event:source_set" ] + deps = [ + # To track build dependencies, this must depend on a proto library target + # listing `chrome_track_event_descriptor_source`'s imports as sources. + # Conveniently `chrome_track_event_zero` is just such a library. + ":chrome_track_event_zero", + "//third_party/perfetto/protos/perfetto/trace/track_event:source_set", + ] } protozero_library("chrome_track_event_zero") { diff --git a/naiveproxy/src/base/tracing/protos/chrome_track_event.proto b/naiveproxy/src/base/tracing/protos/chrome_track_event.proto index 759fd6f502..4f597eb359 100644 --- a/naiveproxy/src/base/tracing/protos/chrome_track_event.proto +++ b/naiveproxy/src/base/tracing/protos/chrome_track_event.proto @@ -40,6 +40,7 @@ message BlinkTaskScope { TASK_SCOPE_REQUEST_IDLE_CALLBACK = 7; TASK_SCOPE_XML_HTTP_REQUEST = 8; TASK_SCOPE_SOFT_NAVIGATION = 9; + TASK_SCOPE_MISC_EVENT = 10; } optional TaskScopeType type = 1; optional int64 scope_task_id = 2; @@ -115,15 +116,15 @@ message RenderFrameImplDeletion { // The intent for the deletion. optional FrameDeleteIntention intent = 1; - // Whether the frame that's about to be deleted has a pending navigation + // Whether the frame that is about to be deleted has a pending navigation // commit. optional bool has_pending_commit = 2; - // Whether the frame that's about to be deleted has a pending cross-document + // Whether the frame that is about to be deleted has a pending cross-document // navigation commit. optional bool has_pending_cross_document_commit = 3; - // The FrameTreeNode ID of the frame that's about to be deleted. + // The FrameTreeNode ID of the frame that is about to be deleted. optional uint64 frame_tree_node_id = 4; } @@ -704,6 +705,7 @@ message BackForwardCacheCanStoreDocumentResult { CACHE_CONTROL_NO_STORE_DEVICE_BOUND_SESSION_TERMINATED = 65; CACHE_LIMIT_PRUNED_ON_MODERATE_MEMORY_PRESSURE = 66; CACHE_LIMIT_PRUNED_ON_CRITICAL_MEMORY_PRESSURE = 67; + SHARED_WORKER_MESSAGE = 68; } optional BackForwardCacheNotRestoredReason @@ -800,6 +802,7 @@ message RendererMainThreadTaskExecution { TASK_TYPE_MACHINE_LEARNING = 86; TASK_TYPE_MAIN_THREAD_TASK_QUEUE_V8_BEST_EFFORT = 87; TASK_TYPE_INTERNAL_AUTOFILL = 88; + TASK_TYPE_BACK_FORWARD_CACHE_POSTED_MESSAGE = 89; } enum FrameType { @@ -1029,6 +1032,9 @@ message SequenceManagerTask { NETWORK_SERVICE_THREAD_HIGH_TQ = 58; NETWORK_SERVICE_THREAD_DEFAULT_TQ = 59; + + UI_STARTUP_TQ = 60; + IO_STARTUP_TQ = 61; } optional Priority priority = 1; @@ -1051,6 +1057,8 @@ message AndroidToolbar { BLOCKED_COMPOSITOR_IN_MOTION = 11; BLOCKED_NTP_Y_TRANSLATION = 12; BLOCKED_FULLSCREEN = 13; + BLOCKED_TABLET_BUTTON_ANIMATION_IN_PROGRESS = 14; + BLOCKED_LAYOUT_REQUESTED = 15; } enum AllowCaptureReason { ALLOWED_UNKNOWN = 0; diff --git a/naiveproxy/src/base/tracing/protos/chrome_track_event_import_wrapper.proto b/naiveproxy/src/base/tracing/protos/chrome_track_event_import_wrapper.proto new file mode 100644 index 0000000000..ba3ed79ab7 --- /dev/null +++ b/naiveproxy/src/base/tracing/protos/chrome_track_event_import_wrapper.proto @@ -0,0 +1,8 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +syntax = "proto2"; + +// Import all .proto files that should be included in the proto descriptor. +import public "base/tracing/protos/chrome_track_event.proto"; diff --git a/naiveproxy/src/base/tracing/protos/sources.gni b/naiveproxy/src/base/tracing/protos/sources.gni index 115ec4ba63..cc4762777b 100644 --- a/naiveproxy/src/base/tracing/protos/sources.gni +++ b/naiveproxy/src/base/tracing/protos/sources.gni @@ -9,3 +9,8 @@ # first in order to be useful. # TODO(b/181318121): Implement the support in Perfetto and remove the warning. chrome_track_event_sources = [ "chrome_track_event.proto" ] + +# protoc can generate a descriptor file from a single .proto file. If +# `chrome_track_event_sources` contains multiple files, add a single wrapper +# file that imports them all to generate the descriptor. +chrome_track_event_descriptor_source = "chrome_track_event_import_wrapper.proto" diff --git a/naiveproxy/src/base/traits_bag_nocompile.nc b/naiveproxy/src/base/traits_bag_nocompile.nc index 0fc23c118e..35ab9d2486 100644 --- a/naiveproxy/src/base/traits_bag_nocompile.nc +++ b/naiveproxy/src/base/traits_bag_nocompile.nc @@ -38,10 +38,9 @@ struct TestTraits { constexpr TestTraits traits = {}; // expected-error {{constexpr variable 'traits' must be initialized by a constant expression}} // expected-error@base/traits_bag.h:* {{The traits bag is missing a required trait.}} - // expected-error@*:* {{no matching constructor for initialization of 'base::trait_helpers::RequiredEnumTraitFilter'}} + // expected-error@*:* 1+ {{no matching constructor for initialization}} -constexpr TestTraits traits2 = {RequiredTrait::A, NotAValidTrait{}}; // expected-error {{no matching constructor for initialization of 'const TestTraits'}} - // expected-error@*:* {{type occurs more than once in type list}} +constexpr TestTraits traits2 = {RequiredTrait::A, NotAValidTrait{}}; // expected-error@*:* {{type occurs more than once in type list}} constexpr TestTraits traits3 = {RequiredTrait::A, RequiredTrait::B}; // expected-error {{constexpr variable 'traits3' must be initialized by a constant expression}} // expected-error@base/traits_bag.h:* {{The traits bag contains multiple traits of the same type.}} diff --git a/naiveproxy/src/base/types/cxx23_from_range.h b/naiveproxy/src/base/types/cxx23_from_range.h index b7a0a9dc0d..dc152fc0bb 100644 --- a/naiveproxy/src/base/types/cxx23_from_range.h +++ b/naiveproxy/src/base/types/cxx23_from_range.h @@ -13,7 +13,7 @@ namespace base { // // https://en.cppreference.com/w/cpp/ranges/from_range struct from_range_t { - explicit from_range_t() = default; + from_range_t() = default; }; // The instantiation of `from_range_t`, to be passed to constructors taking the diff --git a/naiveproxy/src/base/types/expected.h b/naiveproxy/src/base/types/expected.h index f3d308263c..a2b6ece738 100644 --- a/naiveproxy/src/base/types/expected.h +++ b/naiveproxy/src/base/types/expected.h @@ -146,9 +146,9 @@ class ok final { : value_(std::forward(args)...) {} template - constexpr explicit ok(std::in_place_t, - std::initializer_list il, - Args&&... args) noexcept + constexpr ok(std::in_place_t, + std::initializer_list il, + Args&&... args) noexcept : value_(il, std::forward(args)...) {} constexpr T& value() & noexcept { return value_; } @@ -175,7 +175,7 @@ template requires(std::is_void_v) class ok final { public: - constexpr explicit ok() noexcept = default; + constexpr ok() noexcept = default; std::string ToString() const { return "ok()"; } }; @@ -212,9 +212,9 @@ class unexpected final { : error_(std::forward(args)...) {} template - constexpr explicit unexpected(std::in_place_t, - std::initializer_list il, - Args&&... args) noexcept + constexpr unexpected(std::in_place_t, + std::initializer_list il, + Args&&... args) noexcept : error_(il, std::forward(args)...) {} // [expected.un.obs] Observers @@ -346,9 +346,9 @@ class [[nodiscard, gsl::Owner]] expected final { : impl_(kValTag, std::forward(args)...) {} template - constexpr explicit expected(std::in_place_t, - std::initializer_list il, - Args&&... args) noexcept + constexpr expected(std::in_place_t, + std::initializer_list il, + Args&&... args) noexcept : impl_(kValTag, il, std::forward(args)...) {} template @@ -356,9 +356,9 @@ class [[nodiscard, gsl::Owner]] expected final { : impl_(kErrTag, std::forward(args)...) {} template - constexpr explicit expected(unexpect_t, - std::initializer_list il, - Args&&... args) noexcept + constexpr expected(unexpect_t, + std::initializer_list il, + Args&&... args) noexcept : impl_(kErrTag, il, std::forward(args)...) {} // [expected.object.assign], assignment @@ -707,9 +707,9 @@ class [[nodiscard]] expected final { : impl_(kErrTag, std::forward(args)...) {} template - constexpr explicit expected(unexpect_t, - std::initializer_list il, - Args&&... args) noexcept + constexpr expected(unexpect_t, + std::initializer_list il, + Args&&... args) noexcept : impl_(kErrTag, il, std::forward(args)...) {} // [expected.void.assign], assignment diff --git a/naiveproxy/src/base/types/expected_internal.h b/naiveproxy/src/base/types/expected_internal.h index 49a45b9dcb..84dfa89718 100644 --- a/naiveproxy/src/base/types/expected_internal.h +++ b/naiveproxy/src/base/types/expected_internal.h @@ -15,6 +15,7 @@ #include #include "base/check.h" +#include "base/notreached.h" // This header defines type traits and aliases used for the implementation of // base::expected. @@ -27,7 +28,7 @@ template class unexpected; struct unexpect_t { - explicit unexpect_t() = default; + unexpect_t() = default; }; // in-place construction of unexpected values @@ -171,9 +172,9 @@ class ExpectedImpl : public ExpectedBase { : state_(State::kValue), storage_(kValTag, std::forward(args)...) {} template - constexpr explicit ExpectedImpl(decltype(kValTag), - std::initializer_list il, - Args&&... args) noexcept + constexpr ExpectedImpl(decltype(kValTag), + std::initializer_list il, + Args&&... args) noexcept : state_(State::kValue), storage_(kValTag, il, std::forward(args)...) {} @@ -182,9 +183,9 @@ class ExpectedImpl : public ExpectedBase { : state_(State::kError), storage_(kErrTag, std::forward(args)...) {} template - constexpr explicit ExpectedImpl(decltype(kErrTag), - std::initializer_list il, - Args&&... args) noexcept + constexpr ExpectedImpl(decltype(kErrTag), + std::initializer_list il, + Args&&... args) noexcept : state_(State::kError), storage_(kErrTag, il, std::forward(args)...) {} @@ -204,14 +205,15 @@ class ExpectedImpl : public ExpectedBase { switch (rhs.state_) { case State::kValue: emplace_value(rhs.storage_.value); - break; + return *this; case State::kError: emplace_error(rhs.storage_.error); - break; + return *this; case State::kMovedFromValue: case State::kMovedFromError: - CHECK(false); + break; } + NOTREACHED(); } return *this; } @@ -222,15 +224,16 @@ class ExpectedImpl : public ExpectedBase { case State::kValue: rhs.state_ = State::kMovedFromValue; emplace_value(std::move(rhs.storage_.value)); - break; + return *this; case State::kError: rhs.state_ = State::kMovedFromError; emplace_error(std::move(rhs.storage_.error)); - break; + return *this; case State::kMovedFromValue: case State::kMovedFromError: - CHECK(false); + break; } + NOTREACHED(); } return *this; } @@ -288,9 +291,9 @@ class ExpectedImpl : public ExpectedBase { case State::kMovedFromError: // This should never be reached; this condition should already be // caught above. - CHECK(false); + break; } - return; + NOTREACHED(); } ExpectedImpl tmp = std::move(*this); *this = std::move(rhs); @@ -345,18 +348,18 @@ class ExpectedImpl : public ExpectedBase { constexpr explicit Storage(decltype(kValTag), Args&&... args) : value(std::forward(args)...) {} template - constexpr explicit Storage(decltype(kValTag), - std::initializer_list il, - Args&&... args) + constexpr Storage(decltype(kValTag), + std::initializer_list il, + Args&&... args) : value(il, std::forward(args)...) {} template constexpr explicit Storage(decltype(kErrTag), Args&&... args) : error(std::forward(args)...) {} template - constexpr explicit Storage(decltype(kErrTag), - std::initializer_list il, - Args&&... args) + constexpr Storage(decltype(kErrTag), + std::initializer_list il, + Args&&... args) : error(il, std::forward(args)...) {} T value; @@ -372,8 +375,9 @@ class ExpectedImpl : public ExpectedBase { return Storage(kErrTag, rhs.storage_.error); case State::kMovedFromValue: case State::kMovedFromError: - CHECK(false); + break; } + NOTREACHED(); } template @@ -387,8 +391,9 @@ class ExpectedImpl : public ExpectedBase { return Storage(kErrTag, std::move(rhs.storage_.error)); case State::kMovedFromValue: case State::kMovedFromError: - CHECK(false); + break; } + NOTREACHED(); } constexpr bool is_moved_from() const noexcept { diff --git a/naiveproxy/src/base/types/optional_ref.h b/naiveproxy/src/base/types/optional_ref.h index 7b0a251dd4..c1ac3c2422 100644 --- a/naiveproxy/src/base/types/optional_ref.h +++ b/naiveproxy/src/base/types/optional_ref.h @@ -208,10 +208,8 @@ class optional_ref { const optional_ref y) requires std::three_way_comparable { - if (!x.ptr_ || !y.ptr_) { - return (!!x.ptr_) <=> (!!y.ptr_); - } - return *x.ptr_ <=> *y.ptr_; + return (!x.ptr_ || !y.ptr_) ? (!!x.ptr_) <=> (!!y.ptr_) + : *x.ptr_ <=> *y.ptr_; } private: diff --git a/naiveproxy/src/base/types/variant_util_nocompile.nc b/naiveproxy/src/base/types/variant_util_nocompile.nc index 7a56bddb29..80ae5bc350 100644 --- a/naiveproxy/src/base/types/variant_util_nocompile.nc +++ b/naiveproxy/src/base/types/variant_util_nocompile.nc @@ -15,11 +15,13 @@ namespace base { inline constexpr size_t kValue = VariantIndexOfType, int>(); // expected-error {{constexpr variable 'kValue' must be initialized by a constant expression}} // expected-error@base/types/variant_util.h:* {{Variant is not constructible from T}} // expected-error@base/types/variant_util.h:* {{no matching conversion for functional-style cast}} + // expected-error@base/types/variant_util.h:* 0-1 {{no matching constructor for initialization}} // Should fail if the type is not mentioned in the variant instantiation at // all. inline constexpr size_t kValue2 = VariantIndexOfType, bool>(); // expected-error {{constexpr variable 'kValue2' must be initialized by a constant expression}} // expected-error@base/types/variant_util.h:* {{Variant is not constructible from T}} // expected-error@base/types/variant_util.h:* {{no matching conversion for functional-style cast}} + // expected-error@base/types/variant_util.h:* 0-1 {{no matching constructor for initialization}} } // namespace base diff --git a/naiveproxy/src/base/unguessable_token.cc b/naiveproxy/src/base/unguessable_token.cc index ea33ca66f3..e996816597 100644 --- a/naiveproxy/src/base/unguessable_token.cc +++ b/naiveproxy/src/base/unguessable_token.cc @@ -11,10 +11,7 @@ #include "base/format_macros.h" #include "base/rand_util.h" #include "build/build_config.h" - -#if !BUILDFLAG(IS_NACL) #include "third_party/boringssl/src/include/openssl/mem.h" -#endif namespace base { @@ -58,14 +55,9 @@ std::optional UnguessableToken::DeserializeFromString( } bool operator==(const UnguessableToken& lhs, const UnguessableToken& rhs) { -#if BUILDFLAG(IS_NACL) - // BoringSSL is unavailable for NaCl builds so it remains timing dependent. - return lhs.token_ == rhs.token_; -#else auto bytes = lhs.token_.AsBytes(); auto other_bytes = rhs.token_.AsBytes(); return CRYPTO_memcmp(bytes.data(), other_bytes.data(), bytes.size()) == 0; -#endif } std::ostream& operator<<(std::ostream& out, const UnguessableToken& token) { diff --git a/naiveproxy/src/base/uuid.cc b/naiveproxy/src/base/uuid.cc index 753c5a13a7..9a45669bb2 100644 --- a/naiveproxy/src/base/uuid.cc +++ b/naiveproxy/src/base/uuid.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/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "base/uuid.h" #include @@ -15,6 +10,7 @@ #include #include +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/hash/hash.h" #include "base/rand_util.h" @@ -83,7 +79,7 @@ Uuid Uuid::FormatRandomDataAsV4Impl(base::span input) { DCHECK_EQ(input.size_bytes(), kGuidV4InputLength); uint64_t sixteen_bytes[2]; - memcpy(&sixteen_bytes, input.data(), sizeof(sixteen_bytes)); + UNSAFE_TODO(memcpy(&sixteen_bytes, input.data(), sizeof(sixteen_bytes))); // Set the Uuid to version 4 as described in RFC 4122, section 4.4. // The format of Uuid version 4 must be xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx, diff --git a/naiveproxy/src/base/values.h b/naiveproxy/src/base/values.h index a74850360e..79ccb4fc26 100644 --- a/naiveproxy/src/base/values.h +++ b/naiveproxy/src/base/values.h @@ -264,21 +264,8 @@ class BASE_EXPORT GSL_OWNER DictValue { // results in a faster initial sort operation. Takes move iterators to avoid // having to clone the input. template - explicit DictValue(std::move_iterator first, - std::move_iterator last) { - // Need to move into a vector first, since `storage_` currently uses - // unique_ptrs. - std::vector>> values; - for (auto current = first; current != last; ++current) { - // With move iterators, no need to call Clone(), but do need to move - // to a temporary first, as accessing either field individually will - // directly from the iterator will delete the other field. - auto value = *current; - values.emplace_back(std::move(value.first), - std::make_unique(std::move(value.second))); - } - storage_ = flat_map>(std::move(values)); - } + DictValue(std::move_iterator first, + std::move_iterator last); DictValue(PassKey, flat_map>); @@ -1094,6 +1081,24 @@ bool ListValue::contains(const T& val, }); } +template +DictValue::DictValue(std::move_iterator first, + std::move_iterator last) { + // Need to move into a vector first, since `storage_` currently uses + // unique_ptrs. + std::vector>> values; + values.reserve(static_cast(std::distance(first, last))); + for (auto current = first; current != last; ++current) { + // With move iterators, no need to call Clone(), but do need to move + // to a temporary first, as accessing either field individually will + // directly from the iterator will delete the other field. + auto value = *current; + values.emplace_back(std::move(value.first), + std::make_unique(std::move(value.second))); + } + storage_ = flat_map>(std::move(values)); +} + } // namespace base #endif // BASE_VALUES_H_ diff --git a/naiveproxy/src/base/win/access_token.cc b/naiveproxy/src/base/win/access_token.cc index cb77197af0..89e0b5cd27 100644 --- a/naiveproxy/src/base/win/access_token.cc +++ b/naiveproxy/src/base/win/access_token.cc @@ -10,6 +10,9 @@ #include "base/win/access_token.h" #include +#include + +#include #include #include @@ -24,6 +27,75 @@ namespace base::win { namespace { +// These are the NT versions of the AUTHZ_SECURITY_ATTRIBUTE* defines in authz.h +// and CLAIM_SECURITY_ATTRIBUTE* in winnt.h. We must use the TOKEN_ versions +// here as they use UNICODE_STRING instead of PWSTR. Where possible, +// static_asserts verify that the structures match the definitions from other +// header files and will fail if they ever changed, but the TOKEN_ versions are +// used here for self-consistency. +typedef struct _TOKEN_SECURITY_ATTRIBUTE_V1 { + UNICODE_STRING Name; + USHORT ValueType; + USHORT Reserved; + ULONG Flags; + ULONG ValueCount; + PLONG64 pInt64; +} TOKEN_SECURITY_ATTRIBUTE_V1, *PTOKEN_SECURITY_ATTRIBUTE_V1; + +#define TOKEN_SECURITY_ATTRIBUTES_INFORMATION_VERSION_V1 1 +static_assert(TOKEN_SECURITY_ATTRIBUTES_INFORMATION_VERSION_V1 == + AUTHZ_SECURITY_ATTRIBUTES_INFORMATION_VERSION_V1); + +typedef struct _TOKEN_SECURITY_ATTRIBUTES_INFORMATION { + USHORT Version; + USHORT Reserved; + ULONG AttributeCount; + PTOKEN_SECURITY_ATTRIBUTE_V1 pAttributeV1; +} TOKEN_SECURITY_ATTRIBUTES_INFORMATION, + *PTOKEN_SECURITY_ATTRIBUTES_INFORMATION; + +static_assert(sizeof(TOKEN_SECURITY_ATTRIBUTES_INFORMATION) == + sizeof(AUTHZ_SECURITY_ATTRIBUTES_INFORMATION)); +static_assert(offsetof(TOKEN_SECURITY_ATTRIBUTES_INFORMATION, Version) == + offsetof(AUTHZ_SECURITY_ATTRIBUTES_INFORMATION, Version)); +static_assert(offsetof(TOKEN_SECURITY_ATTRIBUTES_INFORMATION, AttributeCount) == + offsetof(AUTHZ_SECURITY_ATTRIBUTES_INFORMATION, AttributeCount)); +static_assert(offsetof(TOKEN_SECURITY_ATTRIBUTES_INFORMATION, pAttributeV1) == + offsetof(AUTHZ_SECURITY_ATTRIBUTES_INFORMATION, + Attribute.pAttributeV1)); + +typedef enum _TOKEN_SECURITY_ATTRIBUTE_OPERATION { + TOKEN_SECURITY_ATTRIBUTE_OPERATION_NONE, + TOKEN_SECURITY_ATTRIBUTE_OPERATION_REPLACE_ALL, + TOKEN_SECURITY_ATTRIBUTE_OPERATION_ADD, + TOKEN_SECURITY_ATTRIBUTE_OPERATION_DELETE, + TOKEN_SECURITY_ATTRIBUTE_OPERATION_REPLACE +} TOKEN_SECURITY_ATTRIBUTE_OPERATION, + *PTOKEN_SECURITY_ATTRIBUTE_OPERATION; + +// Only Add is used. +static_assert(int{TOKEN_SECURITY_ATTRIBUTE_OPERATION_ADD} == + int{AUTHZ_SECURITY_ATTRIBUTE_OPERATION_ADD}); + +// This structure is not reflected anywhere in Windows headers. +typedef struct _TOKEN_SECURITY_ATTRIBUTES_AND_OPERATION_INFORMATION { + PTOKEN_SECURITY_ATTRIBUTES_INFORMATION Attributes; + PTOKEN_SECURITY_ATTRIBUTE_OPERATION Operations; +} TOKEN_SECURITY_ATTRIBUTES_AND_OPERATION_INFORMATION, + *PTOKEN_SECURITY_ATTRIBUTES_AND_OPERATION_INFORMATION; + +#define TOKEN_SECURITY_ATTRIBUTE_TYPE_INT64 0x01 +static_assert(TOKEN_SECURITY_ATTRIBUTE_TYPE_INT64 == + AUTHZ_SECURITY_ATTRIBUTE_TYPE_INT64); + +#define TOKEN_SECURITY_ATTRIBUTE_NON_INHERITABLE 0x0001 +static_assert(TOKEN_SECURITY_ATTRIBUTE_NON_INHERITABLE == + AUTHZ_SECURITY_ATTRIBUTE_NON_INHERITABLE); + +#define TOKEN_SECURITY_ATTRIBUTE_MANDATORY 0x0020 +static_assert(TOKEN_SECURITY_ATTRIBUTE_MANDATORY == + CLAIM_SECURITY_ATTRIBUTE_MANDATORY); + // The SECURITY_IMPERSONATION_LEVEL type is an enum and therefore can't be // forward declared in windows_types.h. Ensure our separate definition matches // the existing values for simplicity. @@ -213,6 +285,7 @@ std::optional AdjustPrivilege(const ScopedHandle& token, } return attributes; } + } // namespace bool AccessToken::Group::IsIntegrity() const { @@ -659,6 +732,35 @@ bool AccessToken::RemoveAllPrivileges() { /*PreviousState=*/nullptr, /*ReturnLength=*/nullptr); } +bool AccessToken::AddSecurityAttribute(const std::wstring& name, bool inherit) { + TOKEN_SECURITY_ATTRIBUTE_V1 attr = {}; + + attr.Flags = TOKEN_SECURITY_ATTRIBUTE_MANDATORY; + if (!inherit) { + attr.Flags |= TOKEN_SECURITY_ATTRIBUTE_NON_INHERITABLE; + } + + ::RtlInitUnicodeString(&attr.Name, name.c_str()); + LONG64 value = 0; + attr.ValueCount = 1; + attr.ValueType = TOKEN_SECURITY_ATTRIBUTE_TYPE_INT64; + attr.pInt64 = &value; + + TOKEN_SECURITY_ATTRIBUTES_INFORMATION attrs = {}; + attrs.Version = TOKEN_SECURITY_ATTRIBUTES_INFORMATION_VERSION_V1; + attrs.AttributeCount = 1; + attrs.pAttributeV1 = &attr; + + TOKEN_SECURITY_ATTRIBUTE_OPERATION op = + TOKEN_SECURITY_ATTRIBUTE_OPERATION_ADD; + + TOKEN_SECURITY_ATTRIBUTES_AND_OPERATION_INFORMATION info = {}; + info.Attributes = &attrs; + info.Operations = &op; + + return Set(token_, TokenSecurityAttributes, info); +} + bool AccessToken::is_valid() const { return token_.is_valid(); } diff --git a/naiveproxy/src/base/win/access_token.h b/naiveproxy/src/base/win/access_token.h index 8e7baea2db..10599b1318 100644 --- a/naiveproxy/src/base/win/access_token.h +++ b/naiveproxy/src/base/win/access_token.h @@ -317,6 +317,15 @@ class BASE_EXPORT AccessToken { // The token must be opened with TOKEN_ADJUST_PRIVILEGES access. bool RemoveAllPrivileges(); + // Add a security attribute by name to the token. + // |name| the name of the attribute to add. + // The security attribute is added with a single 64-bit integer value. The + // purpose of this is to add a marker attribute for the purposes of access + // checking rather than for general use. + // The token must be opened with TOKEN_ADJUST_DEFAULT access. The caller must + // have SeTcbPrivilege enabled to successfully add the attribute. + bool AddSecurityAttribute(const std::wstring& name, bool inherit); + // Indicates if the AccessToken object is valid. bool is_valid() const; diff --git a/naiveproxy/src/base/win/elevation_util.cc b/naiveproxy/src/base/win/elevation_util.cc index 384f90a02d..32673300ca 100644 --- a/naiveproxy/src/base/win/elevation_util.cc +++ b/naiveproxy/src/base/win/elevation_util.cc @@ -12,6 +12,7 @@ #include #include +#include #include "base/base_paths.h" #include "base/command_line.h" @@ -44,30 +45,33 @@ bool IsProcessRunningAtMediumOrLower(ProcessId process_id) { // Based on // https://learn.microsoft.com/en-us/archive/blogs/aaron_margosis/faq-how-do-i-start-a-program-as-the-desktop-user-from-an-elevated-app. -Process RunDeElevated(const CommandLine& command_line) { +expected RunDeElevated(const CommandLine& command_line) { if (!::IsUserAnAdmin()) { - return LaunchProcess(command_line, {}); + if (auto process = LaunchProcess(command_line, {}); process.IsValid()) { + return ok(std::move(process)); + } + return unexpected(::GetLastError()); } ProcessId explorer_pid = GetExplorerPid(); if (!explorer_pid || !IsProcessRunningAtMediumOrLower(explorer_pid)) { - return Process(); + return unexpected(static_cast(ERROR_ACCESS_DENIED)); } auto shell_process = Process::OpenWithAccess(explorer_pid, PROCESS_QUERY_LIMITED_INFORMATION); if (!shell_process.IsValid()) { - return Process(); + return unexpected(::GetLastError()); } auto token = AccessToken::FromProcess( ::GetCurrentProcess(), /*impersonation=*/false, MAXIMUM_ALLOWED); if (!token) { - return Process(); + return unexpected(::GetLastError()); } auto previous_impersonate = token->SetPrivilege(SE_IMPERSONATE_NAME, true); if (!previous_impersonate) { - return Process(); + return unexpected(::GetLastError()); } absl::Cleanup restore_previous_privileges = [&] { token->SetPrivilege(SE_IMPERSONATE_NAME, *previous_impersonate); @@ -76,14 +80,14 @@ Process RunDeElevated(const CommandLine& command_line) { auto shell_token = AccessToken::FromProcess( shell_process.Handle(), /*impersonation=*/false, TOKEN_DUPLICATE); if (!shell_token) { - return Process(); + return unexpected(::GetLastError()); } auto duplicated_shell_token = shell_token->DuplicatePrimary( TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID); if (!duplicated_shell_token) { - return Process(); + return unexpected(::GetLastError()); } StartupInformation startupinfo; @@ -93,7 +97,7 @@ Process RunDeElevated(const CommandLine& command_line) { command_line.GetCommandLineString().data(), 0, nullptr, nullptr, startupinfo.startup_info(), &pi)) { - return Process(); + return unexpected(::GetLastError()); } ScopedProcessInformation process_info(pi); Process process(process_info.TakeProcessHandle()); @@ -105,7 +109,7 @@ Process RunDeElevated(const CommandLine& command_line) { VPLOG(1) << __func__ << ": ::AllowSetForegroundWindow failed"; } - return process; + return ok(std::move(process)); } HRESULT RunDeElevatedNoWait(const CommandLine& command_line) { diff --git a/naiveproxy/src/base/win/elevation_util.h b/naiveproxy/src/base/win/elevation_util.h index 27791f2290..bd32ff76fa 100644 --- a/naiveproxy/src/base/win/elevation_util.h +++ b/naiveproxy/src/base/win/elevation_util.h @@ -11,6 +11,7 @@ #include "base/base_export.h" #include "base/process/process.h" #include "base/process/process_handle.h" +#include "base/types/expected.h" #include "base/win/windows_types.h" namespace base { @@ -25,10 +26,10 @@ BASE_EXPORT ProcessId GetExplorerPid(); // Returns `true` if `process_id` is running at medium integrity. BASE_EXPORT bool IsProcessRunningAtMediumOrLower(ProcessId process_id); -// Runs `command_line` de-elevated and returns the spawned process. Returns an -// invalid process on failure. `::GetLastError` can be used to get the last -// error in the failure case. -BASE_EXPORT Process RunDeElevated(const CommandLine& command_line); +// Runs `command_line` de-elevated and returns the spawned process. Returns a +// Windows error code on failure. +BASE_EXPORT expected RunDeElevated( + const CommandLine& command_line); // Runs `command_line` de-elevated. The function does not wait for the spawned // process. diff --git a/naiveproxy/src/base/win/process_startup_helper.cc b/naiveproxy/src/base/win/process_startup_helper.cc index 1a700e8604..c9b90c27be 100644 --- a/naiveproxy/src/base/win/process_startup_helper.cc +++ b/naiveproxy/src/base/win/process_startup_helper.cc @@ -6,6 +6,7 @@ #include #include +#include #include "base/base_switches.h" #include "base/command_line.h" diff --git a/naiveproxy/src/base/win/shortcut.cc b/naiveproxy/src/base/win/shortcut.cc index 8b79d7e238..3cd0dee457 100644 --- a/naiveproxy/src/base/win/shortcut.cc +++ b/naiveproxy/src/base/win/shortcut.cc @@ -164,12 +164,10 @@ bool CreateOrUpdateShortcutLink(const FilePath& shortcut_path, bool has_app_id = (properties.options & ShortcutProperties::PROPERTIES_APP_ID) != 0; - bool has_dual_mode = - (properties.options & ShortcutProperties::PROPERTIES_DUAL_MODE) != 0; bool has_toast_activator_clsid = (properties.options & ShortcutProperties::PROPERTIES_TOAST_ACTIVATOR_CLSID) != 0; - if (has_app_id || has_dual_mode || has_toast_activator_clsid) { + if (has_app_id || has_toast_activator_clsid) { ComPtr property_store; if (FAILED(i_shell_link.As(&property_store)) || !property_store.Get()) { return false; @@ -179,11 +177,6 @@ bool CreateOrUpdateShortcutLink(const FilePath& shortcut_path, properties.app_id.c_str())) { return false; } - if (has_dual_mode && !SetBooleanValueForPropertyStore( - property_store.Get(), PKEY_AppUserModel_IsDualMode, - properties.dual_mode)) { - return false; - } if (has_toast_activator_clsid && !SetClsidForPropertyStore(property_store.Get(), PKEY_AppUserModel_ToastActivatorCLSID, @@ -289,7 +282,6 @@ bool ResolveShortcutProperties(const FilePath& shortcut_path, } if (options & (ShortcutProperties::PROPERTIES_APP_ID | - ShortcutProperties::PROPERTIES_DUAL_MODE | ShortcutProperties::PROPERTIES_TOAST_ACTIVATOR_CLSID)) { ComPtr property_store; if (FAILED(i_shell_link.As(&property_store))) { @@ -323,25 +315,6 @@ bool ResolveShortcutProperties(const FilePath& shortcut_path, } } - if (options & ShortcutProperties::PROPERTIES_DUAL_MODE) { - ScopedPropVariant pv_dual_mode; - if (property_store->GetValue(PKEY_AppUserModel_IsDualMode, - pv_dual_mode.Receive()) != S_OK) { - return false; - } - switch (pv_dual_mode.get().vt) { - case VT_EMPTY: - properties->set_dual_mode(false); - break; - case VT_BOOL: - properties->set_dual_mode(pv_dual_mode.get().boolVal == VARIANT_TRUE); - break; - default: - LOG(WARNING) << "Unexpected variant type: " << pv_dual_mode.get().vt; - break; - } - } - if (options & ShortcutProperties::PROPERTIES_TOAST_ACTIVATOR_CLSID) { ScopedPropVariant pv_toast_activator_clsid; if (property_store->GetValue(PKEY_AppUserModel_ToastActivatorCLSID, diff --git a/naiveproxy/src/base/win/shortcut.h b/naiveproxy/src/base/win/shortcut.h index 25f035b907..28260e316b 100644 --- a/naiveproxy/src/base/win/shortcut.h +++ b/naiveproxy/src/base/win/shortcut.h @@ -38,14 +38,13 @@ struct BASE_EXPORT ShortcutProperties { static constexpr IndividualProperties PROPERTIES_DESCRIPTION = 1U << 3; static constexpr IndividualProperties PROPERTIES_ICON = 1U << 4; static constexpr IndividualProperties PROPERTIES_APP_ID = 1U << 5; - static constexpr IndividualProperties PROPERTIES_DUAL_MODE = 1U << 6; static constexpr IndividualProperties PROPERTIES_TOAST_ACTIVATOR_CLSID = 1U - << 7; + << 6; // Be sure to update the values below when adding a new property. static constexpr IndividualProperties PROPERTIES_ALL = PROPERTIES_TARGET | PROPERTIES_WORKING_DIR | PROPERTIES_ARGUMENTS | PROPERTIES_DESCRIPTION | PROPERTIES_ICON | PROPERTIES_APP_ID | - PROPERTIES_DUAL_MODE | PROPERTIES_TOAST_ACTIVATOR_CLSID; + PROPERTIES_TOAST_ACTIVATOR_CLSID; ShortcutProperties(); ShortcutProperties(const ShortcutProperties& other); @@ -79,11 +78,6 @@ struct BASE_EXPORT ShortcutProperties { options |= PROPERTIES_APP_ID; } - void set_dual_mode(bool dual_mode_in) { - dual_mode = dual_mode_in; - options |= PROPERTIES_DUAL_MODE; - } - void set_toast_activator_clsid(const CLSID& toast_activator_clsid_in) { toast_activator_clsid = toast_activator_clsid_in; options |= PROPERTIES_TOAST_ACTIVATOR_CLSID; @@ -105,8 +99,6 @@ struct BASE_EXPORT ShortcutProperties { int icon_index = -1; // The app model id for the shortcut. std::wstring app_id; - // Whether this is a dual mode shortcut (Windows). - bool dual_mode = false; // The CLSID of the COM object registered with the OS via the shortcut. This // is for app activation via user interaction with a toast notification in the // Action Center. (Win10 version 1607, build 14393, and beyond). diff --git a/naiveproxy/src/build.sh b/naiveproxy/src/build.sh index 9e284728ea..d38c590d39 100755 --- a/naiveproxy/src/build.sh +++ b/naiveproxy/src/build.sh @@ -79,7 +79,6 @@ flags="$flags"' enable_backup_ref_ptr_support=false enable_dangling_raw_ptr_checks=false - enable_shadow_metadata=false ' if [ "$WITH_SYSROOT" ]; then diff --git a/naiveproxy/src/build/OWNERS b/naiveproxy/src/build/OWNERS index 57cc95c09b..7ff5916173 100644 --- a/naiveproxy/src/build/OWNERS +++ b/naiveproxy/src/build/OWNERS @@ -27,7 +27,7 @@ per-file mac_toolchain.py=file://build/mac/OWNERS per-file xcode_binaries.yaml=file://build/mac/OWNERS per-file .gitignore=* -per-file check_gn_headers_whitelist.txt=* +per-file check_gn_headers_allowlist.txt=* per-file whitespace_file.txt=* per-file OWNERS.status=* per-file OWNERS.setnoparent=set noparent diff --git a/naiveproxy/src/build/action_helpers.py b/naiveproxy/src/build/action_helpers.py index 48d8ae52a5..7399716cbb 100644 --- a/naiveproxy/src/build/action_helpers.py +++ b/naiveproxy/src/build/action_helpers.py @@ -103,7 +103,8 @@ def write_depfile(depfile_path: str, path = pathlib.Path(depfile_path) path.parent.mkdir(parents=True, exist_ok=True) - path.write_text(''.join(sb)) + with atomic_output(str(path), mode='w', encoding='utf-8') as w: + w.write(''.join(sb)) def parse_gn_list(value): diff --git a/naiveproxy/src/build/android/PRESUBMIT.py b/naiveproxy/src/build/android/PRESUBMIT.py index de064dfe16..1bee76d1d3 100644 --- a/naiveproxy/src/build/android/PRESUBMIT.py +++ b/naiveproxy/src/build/android/PRESUBMIT.py @@ -92,13 +92,11 @@ def CommonChecks(input_api, output_api, *, is_upload): J('gyp', 'compile_java_tests.py'), J('gyp', 'create_unwind_table_tests.py'), J('gyp', 'dex_test.py'), - J('gyp', 'extract_unwind_tables_tests.py'), J('gyp', 'gcc_preprocess_tests.py'), J('gyp', 'java_cpp_enum_tests.py'), J('gyp', 'java_cpp_features_tests.py'), J('gyp', 'java_cpp_strings_tests.py'), J('gyp', 'java_google_api_keys_tests.py'), - J('gyp', 'util', 'build_utils_test.py'), J('gyp', 'util', 'manifest_utils_test.py'), J('gyp', 'util', 'md5_check_test.py'), J('gyp', 'util', 'resource_utils_test.py'), diff --git a/naiveproxy/src/build/android/adb_system_webengine_command_line b/naiveproxy/src/build/android/adb_system_webengine_command_line deleted file mode 100755 index 2dce6d25fd..0000000000 --- a/naiveproxy/src/build/android/adb_system_webengine_command_line +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -# -# 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. - -# If no flags are given, prints the current content shell flags. -# -# Otherwise, the given flags are used to REPLACE (not modify) the content shell -# flags. For example: -# adb_system_webengine_command_line --enable-webgl -# -# To remove all content shell flags, pass an empty string for the flags: -# adb_system_webengine_command_line "" - -exec $(dirname $0)/adb_command_line.py --name weblayer-command-line "$@" diff --git a/naiveproxy/src/build/android/amd64/module.modulemap b/naiveproxy/src/build/android/amd64/module.modulemap new file mode 100644 index 0000000000..3fb3faea02 --- /dev/null +++ b/naiveproxy/src/build/android/amd64/module.modulemap @@ -0,0 +1,94 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module sysroot_features [system] [extern_c] { + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/linux/limits.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/features.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/sys/cdefs.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/versioning.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/api-level.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/ndk-version.h" +} + +module sysroot [system] [extern_c] { + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/alloca.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/legacy_stdlib_inlines.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/bits/mbstate_t.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/linux/compiler.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/linux/compiler_types.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/linux/errno.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/linux/posix_types.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/linux/sched.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/linux/signal.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/linux/stddef.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/linux/time.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/linux/time_types.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/linux/types.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/linux/wait.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/locale.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/malloc.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/pthread.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/sched.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/signal.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/stdio.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/stdlib.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/strings.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/sys/select.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/sys/signal.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/sys/time.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/sys/types.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/sys/ucontext.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/sys/user.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/time.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/wchar.h" + header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/xlocale.h" + + export * +} + +// The following are all textual because they are the subject of include_next from a non-textual module. +// eg. usr/include/errno.h is included by std_errno_h +module sysroot_ctype [system] [extern_c] { + textual header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/ctype.h" +} + +module sysroot_errno [system] [extern_c] { + textual header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/errno.h" +} + +module sysroot_fenv [system] [extern_c] { + textual header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/fenv.h" +} + +module sysroot_limits [system] [extern_c] { + textual header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/limits.h" +} + +module sysroot_math [system] [extern_c] { + textual header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/math.h" +} + +module sysroot_inttypes [system] [extern_c] { + textual header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/inttypes.h" +} + +module sysroot_string [system] [extern_c] { + textual header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/string.h" +} + +module sysroot_stdatomic [system] [extern_c] { + textual header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/stdatomic.h" +} + +module sysroot_stdint [system] [extern_c] { + textual header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/stdint.h" +} + +module sysroot_uchar [system] [extern_c] { + textual header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/uchar.h" +} + +module sysroot_wctype [system] [extern_c] { + textual header "../../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/wctype.h" +} diff --git a/naiveproxy/src/build/android/fast_local_dev_server.py b/naiveproxy/src/build/android/fast_local_dev_server.py index 1134877609..b9f6caaa4c 100755 --- a/naiveproxy/src/build/android/fast_local_dev_server.py +++ b/naiveproxy/src/build/android/fast_local_dev_server.py @@ -84,21 +84,23 @@ def _exception_hook(exctype: type, exc: Exception, tb): # Stores global options so as to not keep passing along and storing options # everywhere. class OptionsManager: - _options = None + _quiet = None + _should_remote_print = None @classmethod - def set_options(cls, options): - cls._options = options + def set_options(cls, *, quiet, should_remote_print): + cls._quiet = quiet + cls._should_remote_print = should_remote_print @classmethod def is_quiet(cls): - assert cls._options is not None - return cls._options.quiet + assert cls._quiet is not None + return cls._quiet @classmethod def should_remote_print(cls): - assert cls._options is not None - return not cls._options.no_remote_print + assert cls._should_remote_print is not None + return cls._should_remote_print class LogfileManager: @@ -567,7 +569,8 @@ class TaskManager: class Task: """Class to represent one task and operations on it.""" - def __init__(self, name: str, build: Build, cmd: List[str], stamp_file: str): + def __init__(self, name: str, build: Build, cmd: List[str], + stamp_file: Optional[str]): self.name = name self.build = build self.cmd = cmd @@ -688,7 +691,7 @@ class Task: # output/text already on the remote tty we are printing to. self.build.stdout.write(f'\n{remote_message}') self.build.stdout.flush() - if delete_stamp: + if delete_stamp and self.stamp_file: # Force siso to consider failed targets as dirty. try: os.unlink(os.path.join(self.build.cwd, self.stamp_file)) @@ -703,8 +706,10 @@ def _handle_add_task(data, current_tasks: Dict[Tuple[str, str], Task]): build = BuildManager.get_build(build_id) BuildManager.maybe_init_cwd(build, data.get('cwd')) - new_task = Task(name=data['name'], - cmd=data['cmd'], + cmd = data['cmd'] + name = data.get('name') or shlex.join(cmd) + new_task = Task(name=name, + cmd=cmd, build=build, stamp_file=data['stamp_file']) existing_task = current_tasks.get(new_task.key) @@ -756,6 +761,14 @@ def _handle_cancel_build(data): BuildManager.update_remote_titles('') +def _handle_stop_server(): + """Handle messages of type STOP_SERVER.""" + server_log('STOPPING SERVER...') + TaskManager.deactivate() + server_log('STOPPED') + sys.exit(0) + + def _listen_for_request_data(sock: socket.socket): """Helper to encapsulate getting a new message.""" while True: @@ -795,9 +808,7 @@ def _process_requests(sock: socket.socket, exit_on_idle: bool): # Since dicts in python can contain anything, explicitly type tasks to help # make static type checking more useful. tasks: Dict[Tuple[str, str], Task] = {} - server_log( - 'READY... Remember to set android_static_analysis="build_server" in ' - 'args.gn files') + server_log(f'Server started. PID={os.getpid()}') _register_cleanup_signal_handlers() # pylint: disable=too-many-nested-blocks while True: @@ -817,6 +828,9 @@ def _process_requests(sock: socket.socket, exit_on_idle: bool): elif message_type == server_utils.CANCEL_BUILD: connection.close() _handle_cancel_build(data) + elif message_type == server_utils.STOP_SERVER: + connection.close() + _handle_stop_server() else: connection.close() except TimeoutError: @@ -901,21 +915,6 @@ def _wait_for_idle(): time.sleep(0.5) -def _check_if_running(): - """Communicates with the main server to make sure its running.""" - with socket.socket(socket.AF_UNIX) as sock: - try: - sock.connect(server_utils.SOCKET_ADDRESS) - except OSError: - print('Build server is not running and ' - 'android_static_analysis="build_server" is set.\nPlease run ' - 'this command in a separate terminal:\n\n' - '$ build/android/fast_local_dev_server.py\n') - return 1 - else: - return 0 - - def _send_message_and_close(message_dict): with contextlib.closing(socket.socket(socket.AF_UNIX)) as sock: sock.connect(server_utils.SOCKET_ADDRESS) @@ -939,7 +938,20 @@ def _send_cancel_build(build_id): return 0 -def _register_builder(build_id, builder_pid, output_directory): +def _send_stop_server(): + try: + _send_message_and_close({ + 'message_type': server_utils.STOP_SERVER, + }) + except socket.error as e: + if e.errno == 111: + sys.stderr.write('No running build server found.\n') + return 1 + raise + return 0 + + +def _register_build(builder_pid, output_directory): if output_directory is not None: output_directory = str(pathlib.Path(output_directory).absolute()) for _attempt in range(3): @@ -957,7 +969,7 @@ def _register_builder(build_id, builder_pid, output_directory): return 0 except OSError: time.sleep(0.05) - print(f'Failed to register builer for build_id={build_id}.') + print('Failed to register build. No server running?') return 1 @@ -999,12 +1011,12 @@ def _print_build_status_all(): status = 'Finished without any jobs' else: if active: - status = 'Siso still running' + status = 'Main build is still running' else: - status = 'Siso finished' + status = 'Main build completed' if out_dir: status += f' in {out_dir}' - status += f'. Completed [{completed_tasks}/{total_tasks}].' + status += f'. Tasks completed: {completed_tasks}/{total_tasks}' if completed_tasks < total_tasks: status += f' {len(active_tasks)} task(s) currently executing' print(f'{build_id}: {status}') @@ -1045,7 +1057,8 @@ def _print_build_status(build_id): return 0 -def _wait_for_task_requests(exit_on_idle): +def _start_server(exit_on_idle): + sys.excepthook = _exception_hook with socket.socket(socket.AF_UNIX) as sock: sock.settimeout(_SOCKET_TIMEOUT) try: @@ -1064,13 +1077,37 @@ def _wait_for_task_requests(exit_on_idle): return 0 -def main(): - # pylint: disable=too-many-return-statements +def _add_task(cmd): + build_id = f'default-{time.time()}' + os.environ['AUTONINJA_BUILD_ID'] = build_id + tty = os.readlink('/proc/self/fd/1') + if os.path.exists(tty): + os.environ['AUTONINJA_STDOUT_NAME'] = tty + else: + os.environ['AUTONINJA_STDOUT_NAME'] = '/dev/null' + + if code := _register_build(os.getpid(), os.getcwd()): + return code + + try: + _send_message_and_close({ + 'name': None, + 'message_type': server_utils.ADD_TASK, + 'cmd': cmd, + 'cwd': os.getcwd(), + 'build_id': build_id, + 'stamp_file': None, + }) + return 0 + except socket.error as e: + if e.errno == 111: + sys.stderr.write('No running build server found.\n') + return 1 + raise + + +def _main_old(): parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument( - '--fail-if-not-running', - action='store_true', - help='Used by GN to fail fast if the build server is not running.') parser.add_argument( '--exit-on-idle', action='store_true', @@ -1107,10 +1144,10 @@ def main(): metavar='BUILD_ID', help='Cancel all pending and running tasks for BUILD_ID.') args = parser.parse_args() - OptionsManager.set_options(args) - if args.fail_if_not_running: - return _check_if_running() + OptionsManager.set_options(quiet=args.quiet, + should_remote_print=not args.no_remote_print) + if args.wait_for_build: return _wait_for_build(args.wait_for_build) if args.wait_for_idle: @@ -1120,13 +1157,106 @@ def main(): if args.print_status_all: return _print_build_status_all() if args.register_build_id: - return _register_builder(args.register_build_id, args.builder_pid, - args.output_directory) + return _register_build(args.builder_pid, args.output_directory) if args.cancel_build: return _send_cancel_build(args.cancel_build) - return _wait_for_task_requests(args.exit_on_idle) + return _start_server(args.exit_on_idle) + + +def _main_new(): + parser = argparse.ArgumentParser(description=__doc__) + sub_parsers = parser.add_subparsers(dest='command') + + sub_parser = sub_parsers.add_parser('start', help='Start the server') + sub_parser.add_argument('--quiet', + action='store_true', + help='Do not output status updates.') + sub_parser.add_argument('--no-remote-print', + action='store_true', + help='Do not output errors to remote terminals.') + sub_parser.add_argument( + '--exit-on-idle', + action='store_true', + help='Server started on demand. Exit when all tasks run out.') + + sub_parser = sub_parsers.add_parser('stop', + help='Stops the server if it is running') + + sub_parser = sub_parsers.add_parser( + 'register-build', help='Tell a running server about a new ninja session') + sub_parser.add_argument('--output-directory', + required=True, + help='CWD for the build') + sub_parser.add_argument('--builder-pid', + required=True, + help='Builder process\'s PID.') + + sub_parser = sub_parsers.add_parser( + 'unregister-build', + help='Tell a running server a ninja session has finished') + sub_parser.add_argument('--build-id', + required=True, + help='The AUTONINJA_BUILD_ID') + sub_parser.add_argument('--verbose', + action='store_true', + help='Print status if jobs exist.') + sub_parser.add_argument('--cancel-jobs', + action='store_true', + help='Cancel pending jobs') + + sub_parser = sub_parsers.add_parser('status', help='Print status and exit') + sub_parser.add_argument('--build-id', + help='The AUTONINJA_BUILD_ID of the session to query ' + '(otherwise prints all sessions).') + + sub_parser = sub_parsers.add_parser('wait', help='Wait for jobs to complete') + sub_parser.add_argument( + '--build-id', + help='The AUTONINJA_BUILD_ID of the session to wait for ' + '(otherwise waits for all sessions).') + + sub_parser = sub_parsers.add_parser('run', help='Adds a task.') + sub_parser.add_argument('cmd', nargs='+', help='The command to run') + + args = parser.parse_args() + + ret = 0 + if args.command == 'start': + OptionsManager.set_options(quiet=args.quiet, + should_remote_print=not args.no_remote_print) + ret = _start_server(args.exit_on_idle) + elif args.command == 'stop': + ret = _send_stop_server() + elif args.command == 'register-build': + ret = _register_build(args.builder_pid, args.output_directory) + elif args.command == 'unregister-build': + if args.verbose: + ret = _print_build_status(args.build_id) + if args.cancel_jobs: + ret = _send_cancel_build(args.cancel_build) + elif args.command == 'status': + if args.build_id: + ret = _print_build_status(args.build_id) + else: + ret = _print_build_status_all() + elif args.command == 'wait': + if args.build_id: + ret = _wait_for_build(args.build_id) + else: + ret = _wait_for_idle() + elif args.command == 'run': + ret = _add_task(args.cmd) + else: + parser.print_help() + return 1 + return ret + + +def main(): + if len(sys.argv) <= 1 or not sys.argv[1].startswith('-'): + return _main_new() + return _main_old() if __name__ == '__main__': - sys.excepthook = _exception_hook sys.exit(main()) diff --git a/naiveproxy/src/build/android/fast_local_dev_server_test.py b/naiveproxy/src/build/android/fast_local_dev_server_test.py index 5724ac67f7..9773cfb0dd 100755 --- a/naiveproxy/src/build/android/fast_local_dev_server_test.py +++ b/naiveproxy/src/build/android/fast_local_dev_server_test.py @@ -237,7 +237,7 @@ class ServerStartedTest(unittest.TestCase): proc_result = callServer(['--print-status-all']) self.assertIn('has 1 registered build', proc_result.stdout) - self.assertIn('[1/1]', proc_result.stdout) + self.assertIn('1/1', proc_result.stdout) with blockingFifo() as fifo_path: # cat gets stuck until we open the other end of the fifo. @@ -246,7 +246,7 @@ class ServerStartedTest(unittest.TestCase): self.assertIn('is still 1 static analysis job', proc_result.stdout) self.assertIn('--wait-for-idle', proc_result.stdout) proc_result = callServer(['--print-status-all']) - self.assertIn('[1/2]', proc_result.stdout) + self.assertIn('1/2', proc_result.stdout) self.waitForTasksDone() callServer(['--cancel-build', self._build_id]) @@ -255,7 +255,7 @@ class ServerStartedTest(unittest.TestCase): self.assertEqual('', proc_result.stdout) proc_result = callServer(['--print-status-all']) - self.assertIn('Siso finished', proc_result.stdout) + self.assertIn('Main build completed', proc_result.stdout) def testServerCancelsRunningTasks(self): output_stamp = pathlib.Path('/tmp/.deleteme.stamp') diff --git a/naiveproxy/src/build/android/gradle/generate_gradle.py b/naiveproxy/src/build/android/gradle/generate_gradle.py index 456e86b956..6fe86bba84 100755 --- a/naiveproxy/src/build/android/gradle/generate_gradle.py +++ b/naiveproxy/src/build/android/gradle/generate_gradle.py @@ -29,6 +29,7 @@ from pylib.constants import host_paths sys.path.append(os.path.join(_BUILD_ANDROID, 'gyp')) import jinja_template from util import build_utils +from util import params_json_util from util import resource_utils sys.path.append(os.path.dirname(_BUILD_ANDROID)) @@ -36,9 +37,9 @@ import gn_helpers # Typically these should track the versions that works on the slowest release # channel, i.e. Android Studio stable. -_DEFAULT_ANDROID_GRADLE_PLUGIN_VERSION = '7.3.1' +_DEFAULT_ANDROID_GRADLE_PLUGIN_VERSION = '7.4.2' _DEFAULT_KOTLIN_GRADLE_PLUGIN_VERSION = '1.8.0' -_DEFAULT_GRADLE_WRAPPER_VERSION = '7.4' +_DEFAULT_GRADLE_WRAPPER_VERSION = '8.9' _DEPOT_TOOLS_PATH = os.path.join(host_paths.DIR_SOURCE_ROOT, 'third_party', 'depot_tools') @@ -129,7 +130,7 @@ def _BuildTargets(output_dir, args): def _QueryForAllGnTargets(output_dir): cmd = [ os.path.join(_BUILD_ANDROID, 'list_java_targets.py'), '--gn-labels', - '--nested', '--build', '--output-directory', output_dir + '--nested', '--output-directory', output_dir ] logging.info('Running: %r', cmd) return subprocess.check_output(cmd, encoding='UTF-8').splitlines() @@ -143,14 +144,16 @@ class _ProjectEntry: def __init__(self, gn_target): # Use _ProjectEntry.FromGnTarget instead for caching. self._gn_target = gn_target - self._build_config = None self._java_files = None self._all_entries = None + self._params = None + self._gradle_params = None self.android_test_entries = [] @classmethod def FromGnTarget(cls, gn_target): - assert gn_target.startswith('//'), gn_target + assert gn_target.startswith('//'), ( + f'Expected fully-qualified target name. Found: {gn_target}') if ':' not in gn_target: gn_target = '%s:%s' % (gn_target, os.path.basename(gn_target)) if gn_target not in cls._cached_entries: @@ -158,9 +161,10 @@ class _ProjectEntry: return cls._cached_entries[gn_target] @classmethod - def FromBuildConfigPath(cls, path): + def FromParams(cls, params): + path = params.path prefix = 'gen/' - suffix = '.build_config.json' + suffix = '.params.json' assert path.startswith(prefix) and path.endswith(suffix), path subdir = path[len(prefix):-len(suffix)] gn_target = '//%s:%s' % (os.path.split(subdir)) @@ -178,8 +182,8 @@ class _ProjectEntry: def NinjaTarget(self): return self._gn_target[2:] - def BuildConfigPath(self): - return os.path.join('gen', self.GradleSubdir() + '.build_config.json') + def ParamsJsonPath(self): + return os.path.join('gen', self.GradleSubdir() + '.params.json') def GetName(self): return self._gn_target.split(':')[-1] @@ -200,22 +204,15 @@ class _ProjectEntry: """Returns the Gradle project name.""" return self.GradleSubdir().replace(os.path.sep, '.') - def BuildConfig(self): - """Reads and returns the project's .build_config.json JSON.""" - if not self._build_config: - path = _RebasePath(self.BuildConfigPath()) - config = _ReadJson(path.replace('.build_config.json', '.params.json')) - config.update(_ReadJson(path)) - config['path'] = path - self._build_config = config - return self._build_config - - def Gradle(self): - return self.BuildConfig()['gradle'] + def Params(self): + """Reads and returns the target's .params.json.""" + if not self._params: + self._params = params_json_util.get_params(self.ParamsJsonPath()) + return self._params def GetType(self): """Returns the target type from its .build_config.""" - return self.BuildConfig()['type'] + return self.Params().type def IsValid(self): return self.GetType() in ( @@ -228,11 +225,11 @@ class _ProjectEntry: ) def ResSources(self): - return self.BuildConfig().get('lint_resource_sources', []) + return self.Params().deps().collect('res_sources_path') def JavaFiles(self): if self._java_files is None: - target_sources_file = self.BuildConfig().get('target_sources_file') + target_sources_file = self.Params().get('target_sources_file') java_files = [] if target_sources_file: target_sources_file = _RebasePath(target_sources_file) @@ -241,23 +238,18 @@ class _ProjectEntry: return self._java_files def PrebuiltJars(self): - return self.Gradle().get('dependent_prebuilt_jars', []) + filt = lambda p: p.get('is_prebuilt') or p.get('gradle_treat_as_prebuilt') + return self.Params().deps().of_type('java_library').filter(filt).collect( + 'unprocessed_jar_path') - def AllEntries(self): - """Returns a list of all entries that the current entry depends on. - - This includes the entry itself to make iterating simpler.""" + def RecursiveLibraryDeps(self): + """Returns a list of all entries that the current entry depends on.""" if self._all_entries is None: logging.debug('Generating entries for %s', self.GnTarget()) - deps = [_ProjectEntry.FromBuildConfigPath(p) - for p in self.Gradle()['dependent_android_projects']] - deps.extend(_ProjectEntry.FromBuildConfigPath(p) - for p in self.Gradle()['dependent_java_projects']) - all_entries = set() - for dep in deps: - all_entries.update(dep.AllEntries()) - all_entries.add(self) - self._all_entries = list(all_entries) + deps = self.Params().deps().recursive().of_type('java_library') + deps = deps.filter(lambda x: not x.get('is_prebuilt') and not x.get( + 'gradle_treat_as_prebuilt')) + self._all_entries = [_ProjectEntry.FromParams(p) for p in deps] return self._all_entries @@ -277,7 +269,7 @@ class _ProjectContextGenerator: def _GenJniLibs(self, root_entry): libraries = [] for entry in self._GetEntries(root_entry): - libraries += entry.BuildConfig().get('native', {}).get('libraries', []) + libraries += entry.Params().native_libraries() if libraries: return _CreateJniLibsDir(constants.GetOutDirectory(), self.EntryOutputDir(root_entry), libraries) @@ -298,19 +290,14 @@ class _ProjectContextGenerator: to generate a custom manifest if we let gradle process resources. We cannot simply set android.defaultConfig.applicationId because it is not supported for library targets.""" - resource_packages = entry.BuildConfig().get('resource_packages') - if not resource_packages: + package_name = entry.Params().get('package_name') + if not package_name: logging.debug( 'Target %s includes resources from unknown package. ' 'Unable to process with gradle.', entry.GnTarget()) return _DEFAULT_ANDROID_MANIFEST_PATH - if len(resource_packages) > 1: - logging.debug( - 'Target %s includes resources from multiple packages. ' - 'Unable to process with gradle.', entry.GnTarget()) - return _DEFAULT_ANDROID_MANIFEST_PATH - variables = {'package': resource_packages[0]} + variables = {'package': package_name} data = self.jinja_processor.Render(_TemplatePath('manifest'), variables) output_file = os.path.join( self.EntryOutputDir(entry), 'AndroidManifest.xml') @@ -324,7 +311,7 @@ class _ProjectContextGenerator: def _GetEntries(self, entry): if self.split_projects: return [entry] - return entry.AllEntries() + return [entry] + entry.RecursiveLibraryDeps() def EntryOutputDir(self, entry): return os.path.join(self.project_dir, entry.GradleSubdir()) @@ -336,7 +323,7 @@ class _ProjectContextGenerator: return generated_inputs def GenerateManifest(self, root_entry): - android_manifest = root_entry.BuildConfig().get('android_manifest') + android_manifest = root_entry.Params().get('android_manifest') if not android_manifest: android_manifest = self._GenCustomManifest(root_entry) return self._Relativize(root_entry, android_manifest) @@ -363,18 +350,20 @@ class _ProjectContextGenerator: res_sources = [] for res_sources_file in res_sources_files: res_sources.extend(build_utils.ReadSourcesList(res_sources_file)) - res_dirs = resource_utils.DeduceResourceDirsFromFileList(res_sources) + res_dirs = resource_utils.DeduceResourceDirsFromFileList(res_sources, + validate=False) # Do not add generated resources for the all module since it creates many # duplicates, and currently resources are only used for editing. self.processed_res_dirs.update(res_dirs) variables['res_dirs'] = self._Relativize(root_entry, res_dirs) if self.split_projects: - deps = [_ProjectEntry.FromBuildConfigPath(p) - for p in root_entry.Gradle()['dependent_android_projects']] - variables['android_project_deps'] = [d.ProjectName() for d in deps] - deps = [_ProjectEntry.FromBuildConfigPath(p) - for p in root_entry.Gradle()['dependent_java_projects']] - variables['java_project_deps'] = [d.ProjectName() for d in deps] + deps = root_entry.RecursiveLibraryDeps() + variables['android_project_deps'] = [ + e.ProjectName() for e in deps if e.Params().requires_android() + ] + variables['java_project_deps'] = [ + e.ProjectName() for e in deps if not e.Params().requires_android() + ] return variables @@ -441,8 +430,10 @@ def _ComputeJavaSourceDirsAndExcludes(output_dir, source_files): all_found_source_files = set() for directory, files in computed_dirs.items(): - found_source_files = (build_utils.FindInDirectory(directory, '*.java') + - build_utils.FindInDirectory(directory, '*.kt')) + found_source_files = [ + p for p in build_utils.FindInDirectory(directory, '*') + if p.endswith(('.java', '.kt')) + ] all_found_source_files.update(found_source_files) unwanted_source_files = set(found_source_files) - set(files) if unwanted_source_files: @@ -534,6 +525,8 @@ def _GenerateGradleProperties(): '', '# Tells Gradle to show warnings during project sync.', 'org.gradle.warning.mode=all', + '# Needed when using --split-projects.', + 'org.gradle.jvmargs=-Xmx2048m', '', ]) @@ -555,25 +548,26 @@ def _GenerateBaseVars(generator, build_vars): def _GenerateGradleFile(entry, generator, build_vars, jinja_processor): """Returns the data for a project's build.gradle.""" - config = entry.BuildConfig() + params = entry.Params() + logging.info('Generating for %s', entry.GnTarget()) variables = _GenerateBaseVars(generator, build_vars) sourceSetName = 'main' - if config['type'] == 'android_apk': + if params.is_apk(): target_type = 'android_apk' - elif config['type'] in ('java_library', 'java_annotation_processor'): - is_prebuilt = config.get('is_prebuilt', False) - gradle_treat_as_prebuilt = config.get('gradle_treat_as_prebuilt', False) + elif params.type in ('java_library', 'java_annotation_processor'): + is_prebuilt = params.get('is_prebuilt', False) + gradle_treat_as_prebuilt = params.get('gradle_treat_as_prebuilt', False) if is_prebuilt or gradle_treat_as_prebuilt: return None - if config['requires_android']: + if params.requires_android(): target_type = 'android_library' else: target_type = 'java_library' - elif config['type'] == 'java_binary': + elif params.type == 'java_binary': target_type = 'java_binary' - variables['main_class'] = config.get('main_class') - elif config['type'] == 'robolectric_binary': + variables['main_class'] = params.get('main_class') + elif params.type == 'robolectric_binary': target_type = 'android_junit' sourceSetName = 'test' else: @@ -714,21 +708,6 @@ def _GenerateSettingsGradle(project_entries): return '\n'.join(lines) -def _FindAllProjectEntries(main_entries): - """Returns the list of all _ProjectEntry instances given the root project.""" - found = set() - to_scan = list(main_entries) - while to_scan: - cur_entry = to_scan.pop() - if cur_entry in found: - continue - found.add(cur_entry) - sub_config_paths = cur_entry.BuildConfig()['deps_configs'] - to_scan.extend( - _ProjectEntry.FromBuildConfigPath(p) for p in sub_config_paths) - return list(found) - - def _CombineTestEntries(entries): """Combines test apks into the androidTest source set of their target. @@ -742,8 +721,8 @@ def _CombineTestEntries(entries): for entry in entries: target_name = entry.GnTarget() if (target_name.endswith(_INSTRUMENTATION_TARGET_SUFFIX) - and 'apk_under_test' in entry.Gradle()): - apk_name = entry.Gradle()['apk_under_test'] + and entry.Params().apk_under_test()): + apk_name = entry.Params().apk_under_test()['apk_path'] android_test_entries[apk_name].append(entry) else: combined_entries.append(entry) @@ -809,6 +788,7 @@ def main(): constants.CheckOutputDirectory() output_dir = constants.GetOutDirectory() devil_chromium.Initialize(output_directory=output_dir) + params_json_util.set_output_dir(output_dir) run_tests_helper.SetLogLevel(args.verbose_count) if args.use_gradle_process_resources: @@ -832,12 +812,7 @@ def main(): if args.all: if args.native_targets: _RunGnGen(output_dir, ['--ide=json']) - elif not os.path.exists(os.path.join(output_dir, 'build.ninja')): - _RunGnGen(output_dir) - else: - # Faster than running "gn gen" in the no-op case. - _BuildTargets(output_dir, ['build.ninja']) - # Query ninja for all __build_config_crbug_908819 targets. + # Query siso for all __build_config_crbug_908819 targets. targets = _QueryForAllGnTargets(output_dir) else: assert not args.native_targets, 'Native editing requires --all.' @@ -851,11 +826,6 @@ def main(): _RunGnGen(output_dir) main_entries = [_ProjectEntry.FromGnTarget(t) for t in targets] - if not args.all: - # list_java_targets.py takes care of building .build_config.json in the - # --all case. - _BuildTargets(output_dir, [t.BuildConfigPath() for t in main_entries]) - build_vars = gn_helpers.ReadBuildVars(output_dir) jinja_processor = jinja_template.JinjaProcessor(_FILE_DIR) generator = _ProjectContextGenerator(_gradle_output_dir, build_vars, @@ -875,14 +845,12 @@ def main(): ] if args.split_projects: - main_entries = _FindAllProjectEntries(main_entries) - - logging.info('Generating for %d targets.', len(main_entries)) + deps_list = params_json_util.DepsList(e.Params() for e in main_entries) + main_entries = [_ProjectEntry.FromParams(x) for x in deps_list.recursive()] entries = [e for e in _CombineTestEntries(main_entries) if e.IsValid()] - logging.info('Creating %d projects for targets.', len(entries)) + logging.warning('Generating for %d targets.', len(entries)) - logging.warning('Writing .gradle files...') project_entries = [] # When only one entry will be generated we want it to have a valid # build.gradle file with its own AndroidManifest. @@ -934,6 +902,7 @@ def main(): p for p in _RebasePath(generated_inputs, output_dir) if not p.startswith(os.pardir) ] + logging.warning('Building generated sources.') _BuildTargets(output_dir, targets) print('Generated projects for Android Studio.') diff --git a/naiveproxy/src/build/android/gyp/compile_resources.py b/naiveproxy/src/build/android/gyp/compile_resources.py index 4c5f8fe955..ac225ad175 100755 --- a/naiveproxy/src/build/android/gyp/compile_resources.py +++ b/naiveproxy/src/build/android/gyp/compile_resources.py @@ -63,7 +63,6 @@ def _ParseArgs(args): 'against. Can be specified multiple times.') input_opts.add_argument( '--dependencies-res-zips', - default=[], help='Resources zip archives from dependents. Required to ' 'resolve @type/foo references into dependent libraries.') input_opts.add_argument( @@ -155,6 +154,7 @@ def _ParseArgs(args): 'when --resource-exclusion-regex is set.') input_opts.add_argument( '--dependencies-res-zip-overlays', + action='append', help='GN list with subset of --dependencies-res-zips to use overlay ' 'semantics for.') input_opts.add_argument( @@ -613,8 +613,8 @@ def _CompileDeps(aapt2_path, dep_subdirs, dep_subdir_overlay_set, temp_dir, return partials_cmd -def _CreateResourceInfoFile(path_info, info_path, dependencies_res_zips): - for zip_file in dependencies_res_zips: +def _CreateResourceInfoFile(path_info, info_path, all_res_zips): + for zip_file in all_res_zips: zip_info_file_path = zip_file + '.info' if os.path.exists(zip_info_file_path): path_info.MergeInfoFile(zip_info_file_path) @@ -705,13 +705,16 @@ def _PackageApk(options, build): The manifest package name for the APK. """ logging.debug('Extracting resource .zips') + all_res_zips = (options.dependencies_res_zips + + options.dependencies_res_zip_overlays) + overlay_zips = set(options.dependencies_res_zip_overlays) dep_subdirs = [] dep_subdir_overlay_set = set() - for dependency_res_zip in options.dependencies_res_zips: + for dependency_res_zip in all_res_zips: extracted_dep_subdirs = resource_utils.ExtractDeps([dependency_res_zip], build.deps_dir) dep_subdirs += extracted_dep_subdirs - if dependency_res_zip in options.dependencies_res_zip_overlays: + if dependency_res_zip in overlay_zips: dep_subdir_overlay_set.update(extracted_dep_subdirs) logging.debug('Applying locale transformations') @@ -804,8 +807,7 @@ def _PackageApk(options, build): # Create .res.info file in parallel. if options.info_path: logging.debug('Creating .res.info file') - _CreateResourceInfoFile(path_info, build.info_path, - options.dependencies_res_zips) + _CreateResourceInfoFile(path_info, build.info_path, all_res_zips) exit_code = link_proc.wait() assert exit_code == 0, f'aapt2 link cmd failed with {exit_code=}' @@ -839,19 +841,6 @@ def _PackageApk(options, build): build.proto_path, build.arsc_path ]) - # Workaround for b/147674078. This is only needed for WebLayer and does not - # affect WebView usage, since WebView does not used dynamic attributes. - if options.shared_resources: - logging.debug('Hardcoding dynamic attributes') - protoresources.HardcodeSharedLibraryDynamicAttributes( - build.proto_path, options.is_bundle_module, - options.shared_resources_allowlist) - - build_utils.CheckOutput([ - options.aapt2_path, 'convert', '--output-format', 'binary', '-o', - build.arsc_path, build.proto_path - ]) - # Sanity check that the created resources have the expected package ID. logging.debug('Performing sanity check') _, actual_package_id = resource_utils.ExtractArscPackage( @@ -952,11 +941,6 @@ def main(args): rjava_build_options.ExportSomeResources( options.shared_resources_allowlist) rjava_build_options.GenerateOnResourcesLoaded() - if options.shared_resources: - # The final resources will only be used in WebLayer, so hardcode the - # package ID to be what WebLayer expects. - rjava_build_options.SetFinalPackageId( - protoresources.SHARED_LIBRARY_HARDCODED_ID) elif options.shared_resources or options.app_as_shared_lib: rjava_build_options.ExportAllResources() rjava_build_options.GenerateOnResourcesLoaded() diff --git a/naiveproxy/src/build/android/gyp/create_app_bundle.py b/naiveproxy/src/build/android/gyp/create_app_bundle.py index c698149f4d..e05e17d134 100755 --- a/naiveproxy/src/build/android/gyp/create_app_bundle.py +++ b/naiveproxy/src/build/android/gyp/create_app_bundle.py @@ -69,6 +69,7 @@ _COMPONENT_TYPES = ('activity', 'provider', 'receiver', 'service') _DEDUPE_ENTRY_TYPES = _COMPONENT_TYPES + ('activity-alias', 'meta-data') _ROTATION_METADATA_KEY = 'com.google.play.apps.signing/RotationConfig.textproto' +_JAVALESS_SERVICE_NAME = 'org.chromium.content.app.NativeServiceSandboxedProcessService' _ALLOWLISTED_NON_BASE_SERVICES = { # Only on API level 33+ which is past the fix for b/169196314. @@ -456,6 +457,10 @@ def _ClassesFromZip(module_zip): return classes +def _IsJavalessService(service_name): + return service_name.startswith(_JAVALESS_SERVICE_NAME) + + def _ValidateSplits(bundle_path, module_zips): logging.info('Reading manifests and running dexdump') base_zip = next(p for p in module_zips if os.path.basename(p) == 'base.zip') @@ -495,7 +500,7 @@ def _ValidateSplits(bundle_path, module_zips): # Ensure components defined in base manifest exist in base dex. for (kind, component), module_name in splits_by_component.items(): if module_name == 'base' and kind in _COMPONENT_TYPES: - if component not in base_classes: + if component not in base_classes and not _IsJavalessService(component): errors.append(f"{component} is defined in the base manfiest, " f"but the class does not exist in the base splits' dex") @@ -524,7 +529,8 @@ def _ValidateSplits(bundle_path, module_zips): for module_name, cur_manifest in manifests_by_name.items(): for service_name in _GetComponentNames(cur_manifest, 'service'): if (service_name not in base_classes - and service_name not in _ALLOWLISTED_NON_BASE_SERVICES): + and service_name not in _ALLOWLISTED_NON_BASE_SERVICES + and not _IsJavalessService(service_name)): errors.append(f'Service {service_name} should be declared in the base' f' manifest, but is in "{module_name}" module. For' ' details, see b/169196314.') diff --git a/naiveproxy/src/build/android/gyp/create_test_apk_wrapper_script.py b/naiveproxy/src/build/android/gyp/create_test_apk_wrapper_script.py index b4d18ec24c..8fb1187d0d 100755 --- a/naiveproxy/src/build/android/gyp/create_test_apk_wrapper_script.py +++ b/naiveproxy/src/build/android/gyp/create_test_apk_wrapper_script.py @@ -12,7 +12,7 @@ import sys from util import build_utils SCRIPT_TEMPLATE = string.Template("""\ -#!/usr/bin/env python3 +#!/usr/bin/env vpython3 # # This file was generated by build/android/gyp/create_test_apk_wrapper_script.py diff --git a/naiveproxy/src/build/android/gyp/dist_aar.py b/naiveproxy/src/build/android/gyp/dist_aar.py index 54a10cf26c..58c9211f3a 100755 --- a/naiveproxy/src/build/android/gyp/dist_aar.py +++ b/naiveproxy/src/build/android/gyp/dist_aar.py @@ -72,7 +72,9 @@ def main(args): action_helpers.add_depfile_arg(parser) parser.add_argument('--output', required=True, help='Path to output aar.') parser.add_argument('--jars', required=True, help='GN list of jar inputs.') - parser.add_argument('--dependencies-res-zips', required=True, + parser.add_argument('--dependencies-res-zips', + required=True, + action='append', help='GN list of resource zips') parser.add_argument('--r-text-files', required=True, help='GN list of R.txt files to merge') @@ -84,8 +86,8 @@ def main(args): default=os.path.join(_ANDROID_BUILD_DIR, 'AndroidManifest.xml')) parser.add_argument('--native-libraries', default='', - help='GN list of native libraries. If non-empty then \ - ABI must be specified.') + help='GN list of native libraries. If non-empty then ' + 'ABI must be specified.') parser.add_argument('--abi', help='ABI (e.g. armeabi-v7a) for native libraries.') parser.add_argument( diff --git a/naiveproxy/src/build/android/gyp/errorprone.py b/naiveproxy/src/build/android/gyp/errorprone.py index e73ad459de..4ca5baef53 100755 --- a/naiveproxy/src/build/android/gyp/errorprone.py +++ b/naiveproxy/src/build/android/gyp/errorprone.py @@ -126,6 +126,11 @@ ERRORPRONE_WARNINGS_TO_DISABLE = [ # Assigning to fields marked as @Mock or @Spy. Suggested fix is to delete # assignments, which would break tests in many cases. 'UnnecessaryAssignment', + # Serveral instances of using a string right before the String.format(), + # which seems better than inlining. + 'InlineFormatString', + # Low priority. + 'EffectivelyPrivate', ] # Full list of checks: https://errorprone.info/bugpatterns @@ -153,9 +158,6 @@ ERRORPRONE_WARNINGS_TO_ENABLE = [ def main(): parser = argparse.ArgumentParser() - parser.add_argument('--skip-build-server', - action='store_true', - help='Avoid using the build server.') parser.add_argument('--use-build-server', action='store_true', help='Always use the build server.') @@ -173,11 +175,11 @@ def main(): compile_java_argv += ['--jar-path', options.stamp] # Use the build server for errorprone runs. - if not options.skip_build_server and (server_utils.MaybeRunCommand( + if server_utils.MaybeRunCommand( name=options.stamp, argv=sys.argv, stamp_file=options.stamp, - use_build_server=options.use_build_server)): + use_build_server=options.use_build_server): compile_java.main(compile_java_argv, write_depfile_only=True) return diff --git a/naiveproxy/src/build/android/gyp/extract_unwind_tables.py b/naiveproxy/src/build/android/gyp/extract_unwind_tables.py deleted file mode 100755 index a940cf2917..0000000000 --- a/naiveproxy/src/build/android/gyp/extract_unwind_tables.py +++ /dev/null @@ -1,281 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2018 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Extracts the unwind tables in from breakpad symbol files - -Runs dump_syms on the given binary file and extracts the CFI data into the -given output file. -The output file is a binary file containing CFI rows ordered based on function -address. The output file only contains rows that match the most popular rule -type in CFI table, to reduce the output size and specify data in compact format. -See doc https://github.com/google/breakpad/blob/main/docs/symbol_files.md. -1. The CFA rules should be of postfix form "SP +". -2. The RA rules should be of postfix form "CFA + ^". -Note: breakpad represents dereferencing address with '^' operator. - -The output file has 2 tables UNW_INDEX and UNW_DATA, inspired from ARM EHABI -format. The first table contains function addresses and an index into the -UNW_DATA table. The second table contains one or more rows for the function -unwind information. - -The output file starts with 4 bytes counting the number of entries in UNW_INDEX. -Then UNW_INDEX table and UNW_DATA table. - -UNW_INDEX contains two columns of N rows each, where N is the number of -functions. - 1. First column 4 byte rows of all the function start address as offset from - start of the binary, in sorted order. - 2. For each function addr, the second column contains 2 byte indices in order. - The indices are offsets (in count of 2 bytes) of the CFI data from start of - UNW_DATA. -The last entry in the table always contains CANT_UNWIND index to specify the -end address of the last function. - -UNW_DATA contains data of all the functions. Each function data contains N rows. -The data found at the address pointed from UNW_INDEX will be: - 2 bytes: N - number of rows that belong to current function. - N * 4 bytes: N rows of data. 16 bits : Address offset from function start. - 14 bits : CFA offset / 4. - 2 bits : RA offset / 4. - -The function is not added to the unwind table in following conditions: -C1. If length of the function code (number of instructions) is greater than - 0xFFFF (2 byte address span). This is because we use 16 bits to refer to - offset of instruction from start of the address. -C2. If the function moves the SP by more than 0xFFFF bytes. This is because we - use 14 bits to denote CFA offset (last 2 bits are 0). -C3. If the Return Address is stored at an offset >= 16 from the CFA. Some - functions which have variable arguments can have offset upto 16. - TODO(ssid): We can actually store offset 16 by subtracting 1 from RA/4 since - we never have 0. -C4: Some functions do not have unwind information defined in dwarf info. These - functions have index value CANT_UNWIND(0xFFFF) in UNW_INDEX table. - - -Usage: - extract_unwind_tables.py --input_path [root path to unstripped chrome.so] - --output_path [output path] --dump_syms_path [path to dump_syms binary] -""" - -import argparse -import re -import struct -import subprocess -import sys - - -_CFA_REG = '.cfa' -_RA_REG = '.ra' - -_ADDR_ENTRY = 0 -_LENGTH_ENTRY = 1 - -_CANT_UNWIND = 0xFFFF - - -def _Write4Bytes(output_file, val): - """Writes a 32 bit unsigned integer to the given output file.""" - output_file.write(struct.pack(' R2: ". - """ - out = [] - found_register = False - for part in cfi_row: - if found_register: - if part[-1] == ':': - break - out.append(part) - elif part == reg + ':': - found_register = True - return ' '.join(out) - - -def _GetCfaAndRaOffset(cfi_row): - """Returns a tuple with 2 numbers (cfa_offset, ra_offset). - - Returns right values if rule matches the predefined criteria. Returns (0, 0) - otherwise. The criteria for CFA rule is postfix form "SP +" and RA rule - is postfix form "CFA - + ^". - """ - cfa_offset = 0 - ra_offset = 0 - cfa_rule = _FindRuleForRegister(cfi_row, _CFA_REG) - ra_rule = _FindRuleForRegister(cfi_row, _RA_REG) - if cfa_rule and re.match(r'sp [0-9]+ \+', cfa_rule): - cfa_offset = int(cfa_rule.split()[1], 10) - if ra_rule: - if not re.match(r'.cfa -[0-9]+ \+ \^', ra_rule): - return (0, 0) - ra_offset = -1 * int(ra_rule.split()[1], 10) - return (cfa_offset, ra_offset) - - -def GetAllCfiRows(symbol_file): - """Returns parsed CFI data from given symbol_file. - - Each entry in the cfi data dictionary returned is a map from function start - address to array of function rows, starting with FUNCTION type, followed by - one or more CFI rows. - """ - cfi_data = {} - current_func = [] - for line in symbol_file: - if 'STACK CFI' not in line: - continue - - parts = line.split() - data = {} - if parts[2] == 'INIT': - # Add the previous function to the output - if len(current_func) > 1: - cfi_data[current_func[0][_ADDR_ENTRY]] = current_func - current_func = [] - - # The function line is of format "STACK CFI INIT ..." - data[_ADDR_ENTRY] = int(parts[3], 16) - data[_LENGTH_ENTRY] = int(parts[4], 16) - - # Condition C1: Skip if length is large. - if data[_LENGTH_ENTRY] == 0 or data[_LENGTH_ENTRY] > 0xffff: - continue # Skip the current function. - else: - # The current function is skipped. - if len(current_func) == 0: - continue - - # The CFI row is of format "STACK CFI .cfa: .ra: ..." - data[_ADDR_ENTRY] = int(parts[2], 16) - (data[_CFA_REG], data[_RA_REG]) = _GetCfaAndRaOffset(parts) - - # Condition C2 and C3: Skip based on limits on offsets. - if data[_CFA_REG] == 0 or data[_RA_REG] >= 16 or data[_CFA_REG] > 0xffff: - current_func = [] - continue - assert data[_CFA_REG] % 4 == 0 - # Since we skipped functions with code size larger than 0xffff, we should - # have no function offset larger than the same value. - assert data[_ADDR_ENTRY] - current_func[0][_ADDR_ENTRY] < 0xffff - - if data[_ADDR_ENTRY] == 0: - # Skip current function, delete all previous entries. - current_func = [] - continue - assert data[_ADDR_ENTRY] % 2 == 0 - current_func.append(data) - - # Condition C4: Skip function without CFI rows. - if len(current_func) > 1: - cfi_data[current_func[0][_ADDR_ENTRY]] = current_func - return cfi_data - - -def WriteCfiData(cfi_data, out_file): - """Writes the CFI data in defined format to out_file.""" - # Stores the final data that will be written to UNW_DATA table, in order - # with 2 byte items. - unw_data = [] - - # Represent all the CFI data of functions as set of numbers and map them to an - # index in the |unw_data|. This index is later written to the UNW_INDEX table - # for each function. This map is used to find index of the data for functions. - data_to_index = {} - # Store mapping between the functions to the index. - func_addr_to_index = {} - previous_func_end = 0 - for addr, function in sorted(cfi_data.items()): - # Add an empty function entry when functions CFIs are missing between 2 - # functions. - if previous_func_end != 0 and addr - previous_func_end > 4: - func_addr_to_index[previous_func_end + 2] = _CANT_UNWIND - previous_func_end = addr + cfi_data[addr][0][_LENGTH_ENTRY] - - assert len(function) > 1 - func_data_arr = [] - func_data = 0 - # The first row contains the function address and length. The rest of the - # rows have CFI data. Create function data array as given in the format. - for row in function[1:]: - addr_offset = row[_ADDR_ENTRY] - addr - cfa_offset = (row[_CFA_REG]) | (row[_RA_REG] // 4) - - func_data_arr.append(addr_offset) - func_data_arr.append(cfa_offset) - - # Consider all the rows in the data as one large integer and add it as a key - # to the |data_to_index|. - for data in func_data_arr: - func_data = (func_data << 16) | data - - row_count = len(func_data_arr) // 2 - if func_data not in data_to_index: - # When data is not found, create a new index = len(unw_data), and write - # the data to |unw_data|. - index = len(unw_data) - data_to_index[func_data] = index - unw_data.append(row_count) - for row in func_data_arr: - unw_data.append(row) - else: - # If the data was found, then use the same index for the function. - index = data_to_index[func_data] - assert row_count == unw_data[index] - func_addr_to_index[addr] = data_to_index[func_data] - - # Mark the end end of last function entry. - func_addr_to_index[previous_func_end + 2] = _CANT_UNWIND - - # Write the size of UNW_INDEX file in bytes. - _Write4Bytes(out_file, len(func_addr_to_index)) - - # Write the UNW_INDEX table. First list of addresses and then indices. - sorted_unw_index = sorted(func_addr_to_index.items()) - for addr, index in sorted_unw_index: - _Write4Bytes(out_file, addr) - for addr, index in sorted_unw_index: - _Write2Bytes(out_file, index) - - # Write the UNW_DATA table. - for data in unw_data: - _Write2Bytes(out_file, data) - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument( - '--input_path', required=True, - help='The input path of the unstripped binary') - parser.add_argument( - '--output_path', required=True, - help='The path of the output file') - parser.add_argument( - '--dump_syms_path', required=True, - help='The path of the dump_syms binary') - - args = parser.parse_args() - cmd = ['./' + args.dump_syms_path, args.input_path, '-v'] - with subprocess.Popen(cmd, stdout=subprocess.PIPE, encoding='utf-8') as proc: - cfi_data = GetAllCfiRows(proc.stdout) - if proc.returncode: - sys.stderr.write('dump_syms exited with code {} after {} symbols\n'.format( - proc.returncode, len(cfi_data))) - sys.exit(proc.returncode) - with open(args.output_path, 'wb') as out_file: - WriteCfiData(cfi_data, out_file) - - -if __name__ == '__main__': - main() diff --git a/naiveproxy/src/build/android/gyp/extract_unwind_tables_tests.py b/naiveproxy/src/build/android/gyp/extract_unwind_tables_tests.py deleted file mode 100755 index b656c088a6..0000000000 --- a/naiveproxy/src/build/android/gyp/extract_unwind_tables_tests.py +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2018 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Tests for extract_unwind_tables.py - -This test suite contains various tests for extracting CFI tables from breakpad -symbol files. -""" - -import io -import os -import struct -import sys -import unittest - -import extract_unwind_tables - -sys.path.append(os.path.join(os.path.dirname(__file__), "gyp")) - - -class TestExtractUnwindTables(unittest.TestCase): - def testExtractCfi(self): - test_data_lines = """ -MODULE Linux arm CDE12FE1DF2B37A9C6560B4CBEE056420 lib_chrome.so -INFO CODE_ID E12FE1CD2BDFA937C6560B4CBEE05642 -FILE 0 ../../base/allocator/allocator_check.cc -FILE 1 ../../base/allocator/allocator_shim.cc -FUNC 1adcb60 54 0 i2d_name_canon -1adcb60 1a 509 17054 -3b94c70 2 69 40 -PUBLIC e17001 0 assist_ranker::(anonymous namespace)::FakePredict::Initialize() -PUBLIC e17005 0 (anonymous namespace)::FileDeleter(base::File) -STACK CFI INIT e17000 4 .cfa: sp 0 + .ra: lr -STACK CFI INIT 0 4 .cfa: sp 0 + .ra: lr -STACK CFI 2 .cfa: sp 4 + -STACK CFI 4 .cfa: sp 12 + .ra: .cfa -8 + ^ r7: .cfa -12 + ^ -STACK CFI 6 .cfa: sp 16 + -STACK CFI INIT e1a96e 20 .cfa: sp 0 + .ra: lr -STACK CFI e1a970 .cfa: sp 4 + -STACK CFI e1a972 .cfa: sp 12 + .ra: .cfa -8 + ^ r7: .cfa -12 + ^ -STACK CFI e1a974 .cfa: sp 16 + -STACK CFI INIT e1a1e4 b0 .cfa: sp 0 + .ra: lr -STACK CFI e1a1e6 .cfa: sp 16 + .ra: .cfa -4 + ^ r4: .cfa -16 + ^ r5: .cfa -12 + -STACK CFI e1a1e8 .cfa: sp 80 + -STACK CFI INIT 0 4 .cfa: sp 0 + .ra: lr -STACK CFI INIT 3b92e24 3c .cfa: sp 0 + .ra: lr -STACK CFI 3b92e4c .cfa: sp 16 + .ra: .cfa -12 + ^ -STACK CFI INIT e17004 0 .cfa: sp 0 + .ra: lr -STACK CFI e17004 2 .cfa: sp 0 + .ra: lr -STACK CFI INIT 3b92e70 38 .cfa: sp 0 + .ra: lr -STACK CFI 3b92e74 .cfa: sp 8 + .ra: .cfa -4 + ^ r4: .cfa -8 + ^ -STACK CFI 3b92e90 .cfa: sp 0 + .ra: .ra r4: r4 -STACK CFI INIT 3b93114 6c .cfa: sp 0 + .ra: lr -STACK CFI 3b93118 .cfa: r7 16 + .ra: .cfa -4 + ^ -STACK CFI INIT 3b92114 6c .cfa: sp 0 + .ra: lr -STACK CFI 3b92118 .cfa: r7 16 + .ra: .cfa -20 + ^ -STACK CFI INIT 3b93214 fffff .cfa: sp 0 + .ra: lr -STACK CFI 3b93218 .cfa: r7 16 + .ra: .cfa -4 + ^ -""".splitlines() - cfi_data = extract_unwind_tables.GetAllCfiRows(test_data_lines) - out_file = io.BytesIO() - extract_unwind_tables.WriteCfiData(cfi_data, out_file) - - expected_cfi_data = { - 0xe1a1e4: [0x2, 0x11, 0x4, 0x50], - 0xe1a296: [], - 0xe1a96e: [0x2, 0x4, 0x4, 0xe, 0x6, 0x10], - 0xe1a990: [], - 0x3b92e24: [0x28, 0x13], - 0x3b92e62: [], - } - expected_function_count = len(expected_cfi_data) - - actual_output = [] - out_file.seek(0) - while True: - read = out_file.read(2) - if not read: - break - actual_output.append(struct.unpack('H', read)[0]) - - # First value is size of unw_index table. - unw_index_size = actual_output[1] << 16 | actual_output[0] - # |unw_index_size| should match entry count. - self.assertEqual(expected_function_count, unw_index_size) - # |actual_output| is in blocks of 2 bytes. Skip first 4 bytes representing - # size. - unw_index_start = 2 - unw_index_addr_end = unw_index_start + expected_function_count * 2 - unw_index_end = unw_index_addr_end + expected_function_count - unw_index_addr_col = actual_output[unw_index_start:unw_index_addr_end] - unw_index_index_col = actual_output[unw_index_addr_end:unw_index_end] - - unw_data_start = unw_index_end - unw_data = actual_output[unw_data_start:] - - for func_iter in range(0, expected_function_count): - func_addr = (unw_index_addr_col[func_iter * 2 + 1] << 16 - | unw_index_addr_col[func_iter * 2]) - index = unw_index_index_col[func_iter] - # If index is CANT_UNWIND then invalid function. - if index == 0xFFFF: - self.assertEqual(expected_cfi_data[func_addr], []) - continue - - func_start = index + 1 - func_end = func_start + unw_data[index] * 2 - self.assertEqual(len(expected_cfi_data[func_addr]), func_end - func_start) - func_cfi = unw_data[func_start:func_end] - self.assertEqual(expected_cfi_data[func_addr], func_cfi) - - -if __name__ == '__main__': - unittest.main() diff --git a/naiveproxy/src/build/android/gyp/generate_linker_version_script.py b/naiveproxy/src/build/android/gyp/generate_linker_version_script.py index 6502ce4ad5..3d0ad2652b 100755 --- a/naiveproxy/src/build/android/gyp/generate_linker_version_script.py +++ b/naiveproxy/src/build/android/gyp/generate_linker_version_script.py @@ -55,7 +55,11 @@ def main(): # JNI_OnLoad is always exported. # CrashpadHandlerMain() is the entry point to the Crashpad handler, required # for libcrashpad_handler_trampoline.so. - symbol_list = ['CrashpadHandlerMain', 'JNI_OnLoad'] + # NativeChildProcessService_onCreate export is for native-only services, + # which have a symbol exposed in our AndroidManifest which Android calls. + symbol_list = [ + 'CrashpadHandlerMain', 'JNI_OnLoad', 'NativeChildProcessService_onCreate' + ] if options.export_fortesting_java_symbols or options.jni_multiplexing: symbol_list.append('Java_*') diff --git a/naiveproxy/src/build/android/gyp/lint.py b/naiveproxy/src/build/android/gyp/lint.py index 8868e5399f..fb030010c2 100755 --- a/naiveproxy/src/build/android/gyp/lint.py +++ b/naiveproxy/src/build/android/gyp/lint.py @@ -27,10 +27,10 @@ _DISABLED_ALWAYS = [ "AppLinkUrlError", # As a browser, we have intent filters without a host. "Assert", # R8 --force-enable-assertions is used to enable java asserts. "InflateParams", # Null is ok when inflating views for dialogs. - # Android apps are associated with domains of the same owner. Chrome uses the - # Credential Manager API to support filling *any* site with a third party - # password manager. Therefore, the list of sign-in domains would be infinite - # and this warning must be suppressed. + # Android apps are associated with domains of the same owner. Chrome uses + # the Credential Manager API to support filling *any* site with a third + # party password manager. Therefore, the list of sign-in domains would be + # infinite and this warning must be suppressed. "CredentialManagerMisuse", "CredManMissingDal", # Has false-positives, TODO(crbug.com/420855219). "InlinedApi", # Constants are copied so they are always available. @@ -150,15 +150,22 @@ def _GenerateConfigXmlTree(orig_config_path, backported_methods): return root_node -def _GenerateAndroidManifest(original_manifest_path, extra_manifest_paths, - min_sdk_version, android_sdk_version): +def _GenerateAndroidManifest(manifest_paths, min_sdk_version, + android_sdk_version): + + if not manifest_paths: + root_manifest = os.path.join(build_utils.DIR_SOURCE_ROOT, 'build', + 'android', 'AndroidManifest.xml') + else: + root_manifest = manifest_paths[0] + manifest_paths = manifest_paths[1:] # Set minSdkVersion in the manifest to the correct value. - doc, manifest, app_node = manifest_utils.ParseManifest(original_manifest_path) + doc, manifest, app_node = manifest_utils.ParseManifest(root_manifest) # TODO(crbug.com/40148088): Should this be done using manifest merging? # Add anything in the application node of the extra manifests to the main # manifest to prevent unused resource errors. - for path in extra_manifest_paths: + for path in manifest_paths: _, _, extra_app_node = manifest_utils.ParseManifest(path) for node in extra_app_node: app_node.append(node) @@ -189,8 +196,7 @@ def _RunLint(custom_lint_jar_path, lint_jar_path, backported_methods_path, config_path, - manifest_path, - extra_manifest_paths, + manifest_paths, sources, classpath, cache_dir, @@ -261,10 +267,6 @@ def _RunLint(custom_lint_jar_path, ','.join(_DISABLED_ALWAYS), ] - if not manifest_path: - manifest_path = os.path.join(build_utils.DIR_SOURCE_ROOT, 'build', - 'android', 'AndroidManifest.xml') - logging.info('Generating config.xml') backported_methods = _RetrieveBackportedMethods(backported_methods_path) config_xml_node = _GenerateConfigXmlTree(config_path, backported_methods) @@ -273,8 +275,7 @@ def _RunLint(custom_lint_jar_path, cmd.extend(['--config', generated_config_path]) logging.info('Generating Android manifest file') - android_manifest_tree = _GenerateAndroidManifest(manifest_path, - extra_manifest_paths, + android_manifest_tree = _GenerateAndroidManifest(manifest_paths, min_sdk_version, android_sdk_version) # Just use a hardcoded name, since we may have different target names (and @@ -393,9 +394,6 @@ def _ParseArgs(argv): parser = argparse.ArgumentParser() action_helpers.add_depfile_arg(parser) parser.add_argument('--target-name', help='Fully qualified GN target name.') - parser.add_argument('--skip-build-server', - action='store_true', - help='Avoid using the build server.') parser.add_argument('--use-build-server', action='store_true', help='Always use the build server.') @@ -435,12 +433,9 @@ def _ParseArgs(argv): 'files.') parser.add_argument('--aars', help='GN list of included aars.') parser.add_argument('--srcjars', help='GN list of included srcjars.') - parser.add_argument('--manifest-path', - help='Path to original AndroidManifest.xml') - parser.add_argument('--extra-manifest-paths', + parser.add_argument('--manifest-paths', action='append', - help='GYP-list of manifest paths to merge into the ' - 'original AndroidManifest.xml') + help='GYP-list of manifest paths, with base being first') parser.add_argument('--resource-sources', default=[], action='append', @@ -462,8 +457,7 @@ def _ParseArgs(argv): args.aars = action_helpers.parse_gn_list(args.aars) args.srcjars = action_helpers.parse_gn_list(args.srcjars) args.resource_sources = action_helpers.parse_gn_list(args.resource_sources) - args.extra_manifest_paths = action_helpers.parse_gn_list( - args.extra_manifest_paths) + args.manifest_paths = action_helpers.parse_gn_list(args.manifest_paths) args.resource_zips = action_helpers.parse_gn_list(args.resource_zips) args.classpath = action_helpers.parse_gn_list(args.classpath) @@ -488,9 +482,8 @@ def main(): resource_sources.extend(build_utils.ReadSourcesList(resource_sources_file)) possible_depfile_deps = (args.srcjars + args.resource_zips + sources + - resource_sources + [ + resource_sources + args.manifest_paths + [ args.baseline, - args.manifest_path, ]) depfile_deps = [p for p in possible_depfile_deps if p] @@ -502,7 +495,7 @@ def main(): # 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 + if (not args.create_cache and server_utils.MaybeRunCommand(name=args.target_name, argv=sys.argv, stamp_file=args.stamp, @@ -513,8 +506,7 @@ def main(): args.lint_jar_path, args.backported_methods, args.config_path, - args.manifest_path, - args.extra_manifest_paths, + args.manifest_paths, sources, args.classpath, args.cache_dir, diff --git a/naiveproxy/src/build/android/gyp/nocompile_test.py b/naiveproxy/src/build/android/gyp/nocompile_test.py index e758641e79..0abf0e662b 100755 --- a/naiveproxy/src/build/android/gyp/nocompile_test.py +++ b/naiveproxy/src/build/android/gyp/nocompile_test.py @@ -12,13 +12,13 @@ import re from util import build_utils _CHROMIUM_SRC = os.path.normpath(os.path.join(__file__, '..', '..', '..', '..')) -_NINJA_PATH = os.path.join(_CHROMIUM_SRC, 'third_party', 'ninja', 'ninja') +_SISO_PATH = os.path.join(_CHROMIUM_SRC, 'third_party', 'siso', 'cipd', 'siso') # Relative to _CHROMIUM_SRC _GN_SRC_REL_PATH = os.path.join('buildtools', 'linux64', 'gn') # Regex for determining whether compile failed because 'gn gen' needs to be run. -_GN_GEN_REGEX = re.compile(r'ninja: (error|fatal):') +_GN_GEN_REGEX = re.compile(r'Error: build.ninja not found') def _raise_command_exception(args, returncode, output): @@ -101,17 +101,7 @@ def _find_regex_in_test_failure_output(test_output, regex): return False failure_message = test_output[failed_index:] - if regex.find('\n') >= 0: - return re.search(regex, failure_message) - return _search_regex_in_list(failure_message.split('\n'), regex) - - -def _search_regex_in_list(value, regex): - for line in value: - if re.search(regex, line): - return True - return False - + return re.search(regex, failure_message) def _do_build_get_failure_output(gn_path, gn_cmd, options): # Extract directory from test target. As all of the test targets are declared @@ -125,7 +115,7 @@ def _do_build_get_failure_output(gn_path, gn_cmd, options): ] _run_command(gn_args, cwd=_CHROMIUM_SRC) - ninja_args = [_NINJA_PATH, '-C', options.out_dir, gn_path] + ninja_args = [_SISO_PATH, 'ninja', '-C', options.out_dir, gn_path] return _run_command_get_failure_output(ninja_args) @@ -177,8 +167,7 @@ def main(): test_output = _do_build_get_failure_output(gn_path, None, options) # 'gn gen' takes > 1s to run. Only run 'gn gen' if it is needed for compile. - if (test_output - and _search_regex_in_list(test_output.split('\n'), _GN_GEN_REGEX)): + if (test_output and _GN_GEN_REGEX.search(test_output)): assert not ran_gn_gen ran_gn_gen = True test_output = _do_build_get_failure_output(gn_path, 'gen', options) diff --git a/naiveproxy/src/build/android/gyp/proguard.py b/naiveproxy/src/build/android/gyp/proguard.py index e0514b45ff..de84397b81 100755 --- a/naiveproxy/src/build/android/gyp/proguard.py +++ b/naiveproxy/src/build/android/gyp/proguard.py @@ -20,10 +20,6 @@ import action_helpers # build_utils adds //build to sys.path. import zip_helpers _IGNORE_WARNINGS = ( - # E.g. Triggers for weblayer_instrumentation_test_apk since both it and its - # apk_under_test have no shared_libraries. - # https://crbug.com/1364192 << To fix this in a better way. - r'Missing class org.chromium.build.NativeLibraries', # Caused by protobuf runtime using -identifiernamestring in a way that # doesn't work with R8. Looks like: # Rule matches the static final field `...`, which may have been inlined... @@ -52,6 +48,8 @@ _IGNORE_WARNINGS = ( r'EditorDialogToolbar', # https://crbug.com/1441226 r'PaymentRequest[BH]', + # This service is defined in Native not Java. + r'NativeServiceSandboxedProcessService', ]) + ')', # We enforce that this class is removed via -checkdiscard. r'FastServiceLoader\.class:.*Could not inline ServiceLoader\.load', @@ -78,6 +76,10 @@ _IGNORE_WARNINGS = ( # androidx/test/espresso/web/internal/deps/guava/collect/Maps$1.class:" # Also happens in espresso core. r'Warning in .*:androidx/test/espresso/.*/guava/collect/.*', + # Likely caused by version skew with internal code. We don't use it though, + # so safe to ignore. b/431248021 + r'.*AndroidComposeUiTestEnvironment.*', + r'.*ComposeUiTest.*', ) _BLOCKLISTED_EXPECTATION_PATHS = [ diff --git a/naiveproxy/src/build/android/gyp/util/build_utils.py b/naiveproxy/src/build/android/gyp/util/build_utils.py index 9da32d0c5d..f6f2fd6543 100644 --- a/naiveproxy/src/build/android/gyp/util/build_utils.py +++ b/naiveproxy/src/build/android/gyp/util/build_utils.py @@ -5,7 +5,6 @@ """Contains common helpers for GN action()s.""" import atexit -import collections import contextlib import fnmatch import json @@ -327,34 +326,6 @@ def MatchesGlob(path, filters): return filters and any(fnmatch.fnmatch(path, f) for f in filters) -def GetSortedTransitiveDependencies(top, deps_func): - """Gets the list of all transitive dependencies in sorted order. - - There should be no cycles in the dependency graph (crashes if cycles exist). - - Args: - top: A list of the top level nodes - deps_func: A function that takes a node and returns a list of its direct - dependencies. - Returns: - A list of all transitive dependencies of nodes in top, in order (a node will - appear in the list at a higher index than all of its dependencies). - """ - # Find all deps depth-first, maintaining original order in the case of ties. - deps_map = collections.OrderedDict() - - def discover(nodes): - for node in nodes: - if node in deps_map: - continue - deps = deps_func(node) - discover(deps) - deps_map[node] = deps - - discover(top) - return list(deps_map) - - def InitLogging(enabling_env): logging.basicConfig( level=logging.DEBUG if os.environ.get(enabling_env) else logging.WARNING, diff --git a/naiveproxy/src/build/android/gyp/util/build_utils_test.py b/naiveproxy/src/build/android/gyp/util/build_utils_test.py deleted file mode 100755 index 44528c9215..0000000000 --- a/naiveproxy/src/build/android/gyp/util/build_utils_test.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2018 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import collections -import os -import sys -import unittest - -sys.path.insert( - 0, os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))) -from util import build_utils - -_DEPS = collections.OrderedDict() -_DEPS['a'] = [] -_DEPS['b'] = [] -_DEPS['c'] = ['a'] -_DEPS['d'] = ['a'] -_DEPS['e'] = ['f'] -_DEPS['f'] = ['a', 'd'] -_DEPS['g'] = [] -_DEPS['h'] = ['d', 'b', 'f'] -_DEPS['i'] = ['f'] - - -class BuildUtilsTest(unittest.TestCase): - def testGetSortedTransitiveDependencies_all(self): - TOP = _DEPS.keys() - EXPECTED = ['a', 'b', 'c', 'd', 'f', 'e', 'g', 'h', 'i'] - actual = build_utils.GetSortedTransitiveDependencies(TOP, _DEPS.get) - self.assertEqual(EXPECTED, actual) - - def testGetSortedTransitiveDependencies_leaves(self): - TOP = ['c', 'e', 'g', 'h', 'i'] - EXPECTED = ['a', 'c', 'd', 'f', 'e', 'g', 'b', 'h', 'i'] - actual = build_utils.GetSortedTransitiveDependencies(TOP, _DEPS.get) - self.assertEqual(EXPECTED, actual) - - def testGetSortedTransitiveDependencies_leavesReverse(self): - TOP = ['i', 'h', 'g', 'e', 'c'] - EXPECTED = ['a', 'd', 'f', 'i', 'b', 'h', 'g', 'e', 'c'] - actual = build_utils.GetSortedTransitiveDependencies(TOP, _DEPS.get) - self.assertEqual(EXPECTED, actual) - - -if __name__ == '__main__': - unittest.main() diff --git a/naiveproxy/src/build/android/gyp/util/diff_utils.py b/naiveproxy/src/build/android/gyp/util/diff_utils.py index 83a98848f3..5566e5cefe 100644 --- a/naiveproxy/src/build/android/gyp/util/diff_utils.py +++ b/naiveproxy/src/build/android/gyp/util/diff_utils.py @@ -134,7 +134,8 @@ END_DIFF ############ END ############ If you are running this locally, you can `export REBASELINE_PROGUARD=1` to -automatically apply this patch. +automatically apply this patch, but you must use `--offline` as an arg to +autoninja. """.format(custom_msg, diff_text) sys.stderr.write(fail_msg) diff --git a/naiveproxy/src/build/android/gyp/util/params_json_util.py b/naiveproxy/src/build/android/gyp/util/params_json_util.py new file mode 100644 index 0000000000..3f0a17d39a --- /dev/null +++ b/naiveproxy/src/build/android/gyp/util/params_json_util.py @@ -0,0 +1,518 @@ +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""Provides functions for reading and parsing .params.json files. + +This module is used by build scripts to access parameters of GN targets and +their transitive dependencies. + +It exposes helper methods to: + * Read and cache JSON files. + * Access transitive dependencies. + * Filter and collect information from dependencies. + +The main entry point is `get_params()`, which returns a `ParamsJson` object. +This object is a dictionary-like view of a .params.json file with added helper +methods for dependency traversal. +""" + +import functools +import json +import os + +# Types that should never be used as a dependency of another build config. +_ROOT_TYPES = frozenset([ + 'android_apk', 'java_binary', 'java_annotation_processor', + 'robolectric_binary', 'android_app_bundle' +]) +# Types that should not allow code deps to pass through. +_RESOURCE_TYPES = frozenset(['android_assets', 'android_resources']) + +_COMPILE_RESOURCES_TYPES = frozenset([ + 'android_apk', + 'android_app_bundle_module', + 'robolectric_binary', +]) + +_MERGES_MANIFESTS_TYPES = _COMPILE_RESOURCES_TYPES + +_COLLECTS_NATIVE_LIBRARIES_TYPES = frozenset([ + 'android_apk', + 'android_app_bundle_module', + 'robolectric_binary', +]) + +_CLASSPATH_TYPES = frozenset([ + 'android_apk', + 'android_app_bundle_module', + 'dist_aar', + 'dist_jar', + 'java_annotation_processor', + 'java_binary', + 'robolectric_binary', +]) + +# Track inputs for use in depfiles. +_input_paths = [] + +# By default scripts are run from the output directory, otherwise call +# set_output_dir() before using methods in this module. +_output_dir_path = '' + + +def set_output_dir(path): + """Resolve paths relative to this directory.""" + global _output_dir_path + _output_dir_path = path + + +def all_read_file_paths(): + """Returns a list of all paths read by _get_json().""" + return list(_input_paths) + + +def _get_json(path): + """Reads a JSON file and records the path for depfile tracking.""" + path = os.path.join(_output_dir_path, path) + _input_paths.append(path) + with open(path, encoding='utf-8') as f: + config = json.load(f) + return config + + +@functools.cache # pylint: disable=method-cache-max-size-none +def get_build_config(path): + """Cached version of _get_json() for .build_config.json files.""" + return _get_json(path) + + +@functools.cache # pylint: disable=method-cache-max-size-none +def get_params(path): + """Returns a cached, dictionary-like object for a .params.json file.""" + # It's important to cache the ParamsJson object rather than the json dict + # because some ParamsJson methods use @cache. + return ParamsJson(path, _get_json(path)) + + +def _topological_walk(top, deps_func): + """Gets the list of all transitive dependencies in topological order. + + Args: + top: A list of the top level nodes + deps_func: A function that takes a node and returns a list of its direct + dependencies. + Returns: + A list of all transitive dependencies of nodes in top in order (a node will + appear in the list at a lower index than all of its dependencies). + """ + seen = {} + + def discover(nodes): + for node in nodes: + if node in seen: + continue + deps = deps_func(node) + discover(deps) + seen[node] = True + + discover(top) + return list(reversed(seen)) + + +def _filter_deps(deps, restrict_to_resource_types=False): + """Filters dependencies based on their type.""" + if restrict_to_resource_types: + # Root types are never is_resource_type(). + keep_func = lambda x: x.is_resource_type() or x.is_group() + else: + keep_func = lambda x: not x.is_root_type() + + return [d for d in deps if keep_func(d)] + + +def _collect_public_deps(deps): + """Recursively collects all public_deps from a list of dependencies.""" + ret = [] + # public_deps() contains public_deps of public_deps, so no need to recurse. + for x in deps: + ret += x.public_deps() + return ret + + +def _deps_for_traversal(dep): + """Returns the direct dependencies of a node for traversal.""" + # Do not let restrict_to_resource_types targets traverse groups directly. + # rely on the group's public_deps (which are filtered by + # restrict_to_resource_types) to surface the deps. + return [] if dep.is_group() else dep.deps() + + +class _HashableList(list): + """A list that can be used in a set / dict key.""" + + def __init__(self, *args, sealed=False, **kwargs): + super().__init__(*args, **kwargs) + self._sealed = sealed + + def __hash__(self): + self._sealed = True + return id(self) + + def __iadd__(self, other): + self._check_not_sealed() + return super().__iadd__(other) + + def __add__(self, other): + return DepsList(super().__add__(other)) + + def _check_not_sealed(self): + assert not self._sealed, 'Cannot mutate a DepsList after it has been used.' + + def append(self, value): + self._check_not_sealed() + return super().append(value) + + def extend(self, iterable): + self._check_not_sealed() + return super().extend(iterable) + + def insert(self, index, value): + self._check_not_sealed() + return super().insert(index, value) + + def remove(self, value): + self._check_not_sealed() + return super().remove(value) + + def pop(self, index=-1): + self._check_not_sealed() + return super().pop(index) + + def clear(self): + self._check_not_sealed() + return super().clear() + + def sort(self, *, key=None, reverse=False): + self._check_not_sealed() + return super().sort(key=key, reverse=reverse) + + def reverse(self): + self._check_not_sealed() + return super().reverse() + + +class DepsList(_HashableList): + """A list of ParamsJson objects with helper methods for traversal.""" + + def __repr__(self): + return ','.join(repr(x) for x in self) + + @functools.cache # pylint: disable=method-cache-max-size-none + def recursive(self): + """Returns all transitive dependencies.""" + # Reverse so that deps appear with higher indices. + return self.walk(lambda x: True) + + @functools.cache # pylint: disable=method-cache-max-size-none + def recursive_resource_deps(self): + """Returns all transitive resource dependencies. + + This is a special traversal for resources, which have different rules + for how they depend on other targets. + """ + + def helper(x): + if not x.get('recursive_resource_deps'): + return True + # Get unfiltered deps so that libraries come through. + ret = [get_params(p) for p in x.get('public_deps_configs', [])] + ret += _collect_public_deps(ret) + return ret + + return self.walk(helper) + + def of_type(self, target_type): + """Filters the list to dependencies of a specific GN target type.""" + return DepsList(d for d in self if d.type == target_type) + + def not_of_type(self, target_type): + """Filters the list to dependencies not of a specific GN target type.""" + return DepsList(d for d in self if d.type != target_type) + + def filter(self, cond): + """Filters the list based on a custom condition.""" + return DepsList(p for p in self if cond(p)) + + def walk(self, visit_func): + """Performs a topological walk, allowing for custom traversal logic. + + Args: + visit_func: A function called for each node. It can return: + * True (or None): Recurse normally. + * False: Prune this node and its descendants from the result. + * A list: Use this list as the node's children instead of its + actual dependencies. + """ + to_prune = set() + + def deps_func(dep): + children = visit_func(dep) + + if children in (None, True): + children = _deps_for_traversal(dep) + if children is False: + to_prune.add(dep) + children = [] + return children + + ret = _topological_walk(self, deps_func) + if to_prune: + ret = [x for x in ret if x not in to_prune] + return DepsList(ret) + + def collect(self, key_name, flatten=False): + """Collects values for a given key from all dependencies in the list. + + Args: + key_name: The key to look up in each dependency's params. + flatten: If True, and the values are lists, flatten them into a + single list. + """ + if flatten: + ret = [] + for p in self: + if values := p.get(key_name): + ret += values + return ret + + return [p[key_name] for p in self if key_name in p] + + +def _extract_native_libraries_from_runtime_deps(path): + """Extracts a list of .so paths from a runtime_deps file.""" + with open(os.path.join(_output_dir_path, path), encoding='utf-8') as f: + lines = f.read().splitlines() + ret = [ + os.path.normpath(l.replace('lib.unstripped/', '')) for l in lines + if l.endswith('.so') + ] + ret.reverse() + return ret + + +class ParamsJson(dict): + """A dictionary-like view of a .params.json file with helper methods.""" + + def __init__(self, path, json_dict): + super().__init__(json_dict) + self.path = path + self.type = self['type'] + + def __hash__(self): + return id(self) + + def __eq__(self, other): + return self is other + + def __repr__(self): + return f'<{self.path}>' + + def build_config_path(self): + """Returns the corresponding .build_config.json path.""" + return self.path.replace('.params.json', '.build_config.json') + + def build_config_json(self): + """Returns the parsed JSON of the corresponding .build_config.json.""" + return get_build_config(self.build_config_path()) + + def is_root_type(self): + """Returns True if the target type is a "root" type (e.g., an APK).""" + return self.type in _ROOT_TYPES + + def collects_resources(self): + """Returns True if the target type collects Android resources.""" + return self.compiles_resources() or self.type == 'dist_aar' + + def compiles_resources(self): + """Returns True if the target type runs compile_resources.py.""" + return self.type in _COMPILE_RESOURCES_TYPES + + def merges_manifests(self): + """Returns True if the target type runs manifest_merger.py.""" + return self.type in _MERGES_MANIFESTS_TYPES + + def collects_dex_paths(self): + """Returns True if the target type collects transitive .dex files.""" + if self.type in ('dist_aar', 'dist_jar'): + return self.supports_android() + if self.is_bundle_module(): + return not self.get('proguard_enabled') + return self.is_apk() + + def collects_processed_classpath(self): + """Returns True if the target type collects the processed classpath.""" + if self.get('dex_needs_classpath'): + return True + if self.type in ('dist_aar', 'dist_jar', 'java_binary', + 'robolectric_binary'): + return True + if self.is_apk() or self.is_bundle() or self.is_bundle_module(): + # Required for is_bundle_module only because write_build_config.py uses + # them as inputs. + return self.get('proguard_enabled', False) + return False + + def collects_native_libraries(self): + """Returns True if the target type collects native libraries.""" + return self.type in _COLLECTS_NATIVE_LIBRARIES_TYPES + + def has_classpath(self): + """Returns True if the target type has a classpath.""" + if self.is_library(): + return self.get('dex_needs_classpath') or not self.get('is_prebuilt') + return self.type in _CLASSPATH_TYPES + + def is_resource_type(self): + """Returns True if the target is an Android resource type.""" + return self.type in _RESOURCE_TYPES + + def is_apk(self): + return self.type == 'android_apk' + + def is_bundle(self): + return self.type == 'android_app_bundle' + + def is_bundle_module(self): + return self.type == 'android_app_bundle_module' + + def is_dist_jar(self): + return self.type == 'dist_jar' + + def is_group(self): + return self.type == 'group' + + def is_library(self): + return self.type == 'java_library' + + def is_system_library(self): + return self.type == 'system_java_library' + + def requires_android(self): + """Returns True if the target requires the Android platform.""" + if self.type.startswith('android') or self.type == 'dist_aar': + return True + return self.is_resource_type or self.get('requires_android', False) + + def supports_android(self): + """Returns True if the target supports the Android platform.""" + return self.requires_android() or self.get('supports_android', True) + + def _direct_deps(self): + """Returns only the direct dependencies (from `deps_configs`).""" + # android_resources use only public_dep_configs, so no need for + # restrict_to_resource_types. + return [get_params(p) for p in self.get('deps_configs', [])] + + @functools.cache # pylint: disable=method-cache-max-size-none + def _cached_direct_public_deps(self): + """Returns only the direct public dependencies.""" + deps = [get_params(p) for p in self.get('public_deps_configs', [])] + return _filter_deps(deps, + restrict_to_resource_types=self.is_resource_type()) + + @functools.cache # pylint: disable=method-cache-max-size-none + def deps(self): + """Returns all dependencies, from both deps and public_deps.""" + deps = DepsList(self._direct_deps()) + deps += self._cached_direct_public_deps() + deps += _filter_deps(_collect_public_deps(deps), + restrict_to_resource_types=self.is_resource_type()) + # Return a cached DepsList so that multiple calls to .deps().recursive() + # result in a cache hit. + return DepsList(dict.fromkeys(deps), sealed=True) + + @functools.cache # pylint: disable=method-cache-max-size-none + def public_deps(self): + """Returns direct public dependencies and their transitive public_deps.""" + deps = self._cached_direct_public_deps() + deps = deps + _filter_deps( + _collect_public_deps(deps), + restrict_to_resource_types=self.is_resource_type()) + return DepsList(deps, sealed=True) + + @functools.cache # pylint: disable=method-cache-max-size-none + def processor_deps(self): + """Returns all transitive annotation processor dependencies.""" + deps = [get_params(p) for p in self.get('processor_configs', [])] + deps += _filter_deps(_collect_public_deps(deps)) + return DepsList(dict.fromkeys(deps), sealed=True) + + def apk_under_test(self): + """Returns the ParamsJson for the apk_under_test, or None.""" + if path := self.get('apk_under_test_config'): + return get_params(path) + return None + + @functools.cache # pylint: disable=method-cache-max-size-none + def module_deps(self): + """For a bundle, returns the ParamsJson for all module dependencies.""" + deps = sorted(self.deps().of_type('android_app_bundle_module'), + key=lambda x: x['module_name']) + if not self.is_bundle(): + return deps + base_module = self.base_module() + ret = {base_module: 1} + ret.update( + dict.fromkeys(x for x in deps if x.parent_module() is base_module)) + ret.update(dict.fromkeys(deps)) + return list(ret) + + def parent_module(self): + """For a bundle module, returns its direct parent module.""" + assert self.is_bundle_module(), 'got: ' + self.type + module_deps = self.module_deps() + + if self['module_name'] == 'base': + assert not module_deps, ('Base module should not depend on ' + + ','.join(module_deps.collect('module_name'))) + return None + + assert len(module_deps) != 0, 'Should depend on base module' + assert len(module_deps) == 1, ( + 'Can depend on only one parent module. Found: ' + + ','.join(module_deps.collect('module_name'))) + return module_deps[0] + + def base_module(self): + """For a bundle module, returns the root 'base' module.""" + if self.is_bundle(): + return next(x for x in self.deps() if x.get('module_name') == 'base') + + assert self.is_bundle_module(), 'got: ' + self.type + # Find the base split. + ret = self + while not ret.is_base_module(): + ret = ret.parent_module() + return ret + + def is_base_module(self): + """Returns True if this is the base module of an app bundle.""" + return self.is_bundle_module() and self.parent_module() is None + + def resource_deps(self): + """Returns the transitive resource dependencies.""" + # For Java libraries, restrict to resource targets that are direct deps, or + # are indirect via other resource targets. + if self.is_library(): + return self.deps().of_type('android_resources') + return self.deps().recursive_resource_deps().of_type('android_resources') + + def native_libraries(self): + if path := self.get('shared_libraries_runtime_deps_file'): + return _extract_native_libraries_from_runtime_deps(path) + return [] + + def secondary_abi_native_libraries(self): + if path := self.get('secondary_abi_shared_libraries_runtime_deps_file'): + return _extract_native_libraries_from_runtime_deps(path) + return [] diff --git a/naiveproxy/src/build/android/gyp/util/protoresources.py b/naiveproxy/src/build/android/gyp/util/protoresources.py index e07fce914d..34cf26d2eb 100644 --- a/naiveproxy/src/build/android/gyp/util/protoresources.py +++ b/naiveproxy/src/build/android/gyp/util/protoresources.py @@ -14,7 +14,6 @@ import sys import zipfile from util import build_utils -from util import resource_utils sys.path[1:1] = [ # `Resources_pb2` module imports `descriptor`, which imports `six`. @@ -30,11 +29,6 @@ from proto import Resources_pb2 # uint32: Magic ("ARSC"), version (1), num_entries (1), type (0) _FLAT_ARSC_HEADER = b'AAPT\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00' -# The package ID hardcoded for shared libraries. See -# _HardcodeSharedLibraryDynamicAttributes() for more details. If this value -# changes make sure to change REQUIRED_PACKAGE_IDENTIFIER in WebLayerImpl.java. -SHARED_LIBRARY_HARDCODED_ID = 36 - def _ProcessZip(zip_path, process_func): """Filters a .zip file via: new_bytes = process_func(filename, data).""" @@ -56,42 +50,10 @@ def _ProcessZip(zip_path, process_func): f.writestr(info, data) -def _ProcessProtoItem(item): - if not item.HasField('ref'): - return - - # If this is a dynamic attribute (type ATTRIBUTE, package ID 0), hardcode - # the package to SHARED_LIBRARY_HARDCODED_ID. - if item.ref.type == Resources_pb2.Reference.ATTRIBUTE and not (item.ref.id - & 0xff000000): - item.ref.id |= (0x01000000 * SHARED_LIBRARY_HARDCODED_ID) - item.ref.ClearField('is_dynamic') - - -def _ProcessProtoValue(value): - if value.HasField('item'): - _ProcessProtoItem(value.item) - return - - compound_value = value.compound_value - if compound_value.HasField('style'): - for entry in compound_value.style.entry: - _ProcessProtoItem(entry.item) - elif compound_value.HasField('array'): - for element in compound_value.array.element: - _ProcessProtoItem(element.item) - elif compound_value.HasField('plural'): - for entry in compound_value.plural.entry: - _ProcessProtoItem(entry.item) - - def _ProcessProtoXmlNode(xml_node): if not xml_node.HasField('element'): return - for attribute in xml_node.element.attribute: - _ProcessProtoItem(attribute.compiled_item) - for child in xml_node.element.child: _ProcessProtoXmlNode(child) @@ -141,76 +103,6 @@ def _SplitLocaleResourceType(_type, allowed_resource_names): return locale_type -def _HardcodeInTable(table, is_bundle_module, shared_resources_allowlist): - translations_package = None - allowed_resource_names = set() - if is_bundle_module: - # A separate top level package will be added to the resources, which - # contains only locale specific resources. The package ID of the locale - # resources is hardcoded to SHARED_LIBRARY_HARDCODED_ID. This causes - # resources in locale splits to all get assigned - # SHARED_LIBRARY_HARDCODED_ID as their package ID, which prevents a bug - # in shared library bundles where each split APK gets a separate dynamic - # ID, and cannot be accessed by the main APK. - translations_package = Resources_pb2.Package() - translations_package.package_id.id = SHARED_LIBRARY_HARDCODED_ID - translations_package.package_name = (table.package[0].package_name + - '_translations') - - # These resources are allowed in the base resources, since they are needed - # by WebView. - if shared_resources_allowlist: - allowed_resource_names = set( - resource_utils.GetRTxtStringResourceNames(shared_resources_allowlist)) - - for package in table.package: - for _type in package.type: - for entry in _type.entry: - for config_value in entry.config_value: - _ProcessProtoValue(config_value.value) - - if translations_package is not None: - locale_type = _SplitLocaleResourceType(_type, allowed_resource_names) - if locale_type: - translations_package.type.add().CopyFrom(locale_type) - - if translations_package is not None: - table.package.add().CopyFrom(translations_package) - - -def HardcodeSharedLibraryDynamicAttributes(zip_path, - is_bundle_module, - shared_resources_allowlist=None): - """Hardcodes the package IDs of dynamic attributes and locale resources. - - Hardcoding dynamic attribute package IDs is a workaround for b/147674078, - which affects Android versions pre-N. Hardcoding locale resource package IDs - is a workaround for b/155437035, which affects resources built with - --shared-lib on all Android versions - - Args: - zip_path: Path to proto APK file. - is_bundle_module: True for bundle modules. - shared_resources_allowlist: Set of resource names to not extract out of the - main package. - """ - - def process_func(filename, data): - if filename == 'resources.pb': - table = Resources_pb2.ResourceTable() - table.ParseFromString(data) - _HardcodeInTable(table, is_bundle_module, shared_resources_allowlist) - data = table.SerializeToString() - elif filename.endswith('.xml') and not filename.startswith('res/raw'): - xml_node = Resources_pb2.XmlNode() - xml_node.ParseFromString(data) - _ProcessProtoXmlNode(xml_node) - data = xml_node.SerializeToString() - return data - - _ProcessZip(zip_path, process_func) - - class _ResourceStripper: def __init__(self, partial_path, keep_predicate): self.partial_path = partial_path diff --git a/naiveproxy/src/build/android/gyp/util/resource_utils.py b/naiveproxy/src/build/android/gyp/util/resource_utils.py index ee00b5d783..4e32b6c997 100644 --- a/naiveproxy/src/build/android/gyp/util/resource_utils.py +++ b/naiveproxy/src/build/android/gyp/util/resource_utils.py @@ -189,36 +189,36 @@ def GenerateGlobs(pattern): return pattern.replace('!', '').split(':') -def DeduceResourceDirsFromFileList(resource_files): +def DeduceResourceDirsFromFileList(resource_files, validate=True): """Return a list of resource directories from a list of resource files.""" # Directory list order is important, cannot use set or other data structures # that change order. This is because resource files of the same name in # multiple res/ directories ellide one another (the last one passed is used). # Thus the order must be maintained to prevent non-deterministic and possibly # flakey builds. - resource_dirs = [] + resource_dirs = {} for resource_path in resource_files: # Resources are always 1 directory deep under res/. res_dir = os.path.dirname(os.path.dirname(resource_path)) - if res_dir not in resource_dirs: - resource_dirs.append(res_dir) + resource_dirs[res_dir] = 1 # Check if any resource_dirs are children of other ones. This indicates that a # file was listed that is not exactly 1 directory deep under res/. # E.g.: # sources = ["java/res/values/foo.xml", "java/res/README.md"] # ^^ This will cause "java" to be detected as resource directory. - for a, b in itertools.permutations(resource_dirs, 2): - if not os.path.relpath(a, b).startswith('..'): - bad_sources = (s for s in resource_files - if os.path.dirname(os.path.dirname(s)) == b) - msg = """\ + if validate: + for a, b in itertools.permutations(resource_dirs, 2): + if not os.path.relpath(a, b).startswith('..'): + bad_sources = (s for s in resource_files + if os.path.dirname(os.path.dirname(s)) == b) + msg = """\ Resource(s) found that are not in a proper directory structure: {} All resource files must follow a structure of "$ROOT/$SUBDIR/$FILE".""" - raise Exception(msg.format('\n '.join(bad_sources))) + raise Exception(msg.format('\n '.join(bad_sources))) - return resource_dirs + return list(resource_dirs) def IterResourceFilesInDirectories(directories, diff --git a/naiveproxy/src/build/android/gyp/util/server_utils.py b/naiveproxy/src/build/android/gyp/util/server_utils.py index f5fe04ed0f..5502defad7 100644 --- a/naiveproxy/src/build/android/gyp/util/server_utils.py +++ b/naiveproxy/src/build/android/gyp/util/server_utils.py @@ -24,6 +24,7 @@ QUERY_BUILD = 'query_build' POLL_HEARTBEAT = 'poll_heartbeat' REGISTER_BUILDER = 'register_builder' CANCEL_BUILD = 'cancel_build' +STOP_SERVER = 'stop_server' SERVER_SCRIPT = pathlib.Path( build_utils.DIR_SOURCE_ROOT diff --git a/naiveproxy/src/build/android/gyp/write_build_config.py b/naiveproxy/src/build/android/gyp/write_build_config.py index e95840a486..03358f386e 100755 --- a/naiveproxy/src/build/android/gyp/write_build_config.py +++ b/naiveproxy/src/build/android/gyp/write_build_config.py @@ -6,57 +6,54 @@ """Writes a .build_config.json file. -See //build/android/docs/build_config.md +This script collects information about a target and all of its transitive +dependencies and writes it to a .build_config.json file for use by other build +steps. It also performs a few validations. + +See //build/android/docs/build_config.md for more information. """ import argparse -import collections import itertools -import json import os -import shutil import sys import xml.dom.minidom from util import build_utils -import action_helpers # build_utils adds //build to sys.path. +from util import params_json_util +import action_helpers -# Types that should never be used as a dependency of another build config. -_ROOT_TYPES = ('android_apk', 'java_binary', 'java_annotation_processor', - 'robolectric_binary', 'android_app_bundle') -# Types that should not allow code deps to pass through. -_RESOURCE_TYPES = ('android_assets', 'android_resources', 'system_java_library') +class OrderedSet(dict): + """A simple implementation of an ordered set.""" -# Cache of path -> JSON dict. -_dep_config_cache = {} + def __init__(self, iterable=()): + super().__init__() + self.update(iterable) - -class OrderedSet(collections.OrderedDict): - @staticmethod - def fromkeys(iterable): - out = OrderedSet() - out.update(iterable) - return out + def __add__(self, other): + ret = OrderedSet(self) + ret.update(other) + return ret def add(self, key): self[key] = True def remove(self, key): - if key in self: - del self[key] + self.pop(key, None) def update(self, iterable): - for v in iterable: - self.add(v) + for k in iterable: + self[k] = True def difference_update(self, iterable): - for v in iterable: - self.remove(v) + for k in iterable: + self.pop(k, None) class AndroidManifest: + """Helper class to inspect properties of an AndroidManifest.xml file.""" def __init__(self, path): self.path = path dom = xml.dom.minidom.parse(path) @@ -86,115 +83,282 @@ class AndroidManifest: return self.manifest.getAttribute('package') -def ReadJson(path): - with open(path, encoding='utf-8') as f: - return json.load(f) +class _TransitiveValues: + """A container for the transitive dependencies of a target. - -def GetDepConfig(path): - if ret := _dep_config_cache.get(path): - return ret - config = ReadJson(path.replace('.build_config.json', '.params.json')) - config.update(ReadJson(path)) - config['path'] = path - _dep_config_cache[path] = config - return config - - -def DepsOfType(wanted_type, configs): - return [c for c in configs if c['type'] == wanted_type] - - -def DepPathsOfType(wanted_type, config_paths): - return [p for p in config_paths if GetDepConfig(p)['type'] == wanted_type] - - -def GetAllDepsConfigsInOrder(deps_config_paths, filter_func=None): - def apply_filter(paths): - if filter_func: - return [p for p in paths if filter_func(GetDepConfig(p))] - return paths - - def discover(path): - config = GetDepConfig(path) - all_deps = (config.get('deps_configs', []) + - config.get('public_deps_configs', [])) - return apply_filter(all_deps) - - deps_config_paths = apply_filter(deps_config_paths) - deps_config_paths = build_utils.GetSortedTransitiveDependencies( - deps_config_paths, discover) - return deps_config_paths - - -def GetObjectByPath(obj, key_path): - """Given an object, return its nth child based on a key path. + This class holds sets of paths for various types of dependencies, such as + jars, resources, assets, etc. """ - return GetObjectByPath(obj[key_path[0]], key_path[1:]) if key_path else obj + # Some values should not be removed when subtracting subtrees. + _NEVER_REMOVE = frozenset([ + 'all_interface_jars', + 'all_input_jars_paths', + 'direct_input_jars_paths', + 'direct_interface_jars', + 'direct_unprocessed_jars', + 'proguard_configs', + ]) + + def __init__(self): + # Direct classpath: + self.direct_unprocessed_jars = OrderedSet() + self.direct_interface_jars = OrderedSet() + self.direct_input_jars_paths = OrderedSet() + # Jar files + self.all_unprocessed_jars = OrderedSet() + self.all_interface_jars = OrderedSet() + self.all_input_jars_paths = OrderedSet() + self.all_dex_files = OrderedSet() + self.all_processed_jars = OrderedSet() + # Assets + self.assets = OrderedSet() + self.uncompressed_assets = OrderedSet() + self.locale_paks = OrderedSet() + # Resources + self.dependency_zip_overlays = OrderedSet() + self.dependency_zips = OrderedSet() + self.extra_package_names = OrderedSet() + # Other + self.android_manifests = OrderedSet() + self.java_resources_jars = OrderedSet() + self.proguard_configs = OrderedSet() + + def RemoveSubtree(self, + other, + retain_processed_jars=False, + retain_unprocessed_jars=False, + retain_resource_zips=False, + retain_extra_package_names=False, + retain_android_manifests=False): + """Removes all values from |other| from this instance.""" + for key, value in self.__dict__.items(): + if not (key in _TransitiveValues._NEVER_REMOVE or + (retain_processed_jars and key == 'all_processed_jars') or + (retain_unprocessed_jars + and key in ('all_unprocessed_jars', 'all_interface_jars')) or + (retain_resource_zips + and key in ('dependency_zips', 'dependency_zip_overlays')) or + (retain_extra_package_names and key == 'extra_package_names') or + (retain_android_manifests and key == 'android_manifests')): + value.difference_update(getattr(other, key)) -def RemoveObjDups(obj, base, *key_path): - """Remove array items from an object[*kep_path] that are also - contained in the base[*kep_path] (duplicates). +def _SortClasspath(dep_list): + """Sorts a list of dependencies for the classpath. + + Move low priority libraries to the end of the classpath. """ - base_target = set(GetObjectByPath(base, key_path)) - target = GetObjectByPath(obj, key_path) - target[:] = [x for x in target if x not in base_target] + dep_list.sort(key=lambda p: 1 if p.get('low_classpath_priority') else 0) + return dep_list -class Deps: - def __init__(self, direct_deps_config_paths): - self._all_deps_config_paths = GetAllDepsConfigsInOrder( - direct_deps_config_paths) - self._direct_deps_configs = [ - GetDepConfig(p) for p in direct_deps_config_paths - ] - self._all_deps_configs = [ - GetDepConfig(p) for p in self._all_deps_config_paths - ] - self._direct_deps_config_paths = direct_deps_config_paths +class _TransitiveValuesBuilder: - def All(self, wanted_type=None): - if wanted_type is None: - return self._all_deps_configs - return DepsOfType(wanted_type, self._all_deps_configs) + def __init__(self, params, remove_parent_module_overlap=True): + self._params = params + self._remove_parent_module_overlap = remove_parent_module_overlap + self._ret = _TransitiveValues() - def Direct(self, wanted_type=None): - if wanted_type is None: - return self._direct_deps_configs - return DepsOfType(wanted_type, self._direct_deps_configs) + def Build(self): + """Computes the transitive dependencies for a given target. - def AllConfigPaths(self): - return self._all_deps_config_paths + This is the core logic of the script, collecting all necessary paths and + metadata from the dependency graph. + """ + params = self._params - def GradlePrebuiltJarPaths(self): - ret = [] + # System .jar files go into sdk_jars / sdk_interface_jars. + direct_deps = _SortClasspath( + params.deps().not_of_type('system_java_library')) + all_deps = _SortClasspath( + direct_deps.recursive().not_of_type('system_java_library')) - def helper(cur): - for config in cur.Direct('java_library'): - if config['is_prebuilt'] or config.get('gradle_treat_as_prebuilt'): - if config['unprocessed_jar_path'] not in ret: - ret.append(config['unprocessed_jar_path']) + all_deps_without_under_test = all_deps + if apk_under_test_params := params.apk_under_test(): + # Cannot use .append() since this is the cached instance. + direct_deps = direct_deps + [apk_under_test_params] + all_deps = _SortClasspath( + direct_deps.recursive().not_of_type('system_java_library')) - helper(self) - return ret + self._CollectClasspath(direct_deps, all_deps) + if params.merges_manifests(): + self._CollectManifests(all_deps_without_under_test) + if params.collects_resources(): + self._CollectResources(all_deps_without_under_test) + self._CollectExtraPackageNames(direct_deps, all_deps) - def GradleLibraryProjectDeps(self): - ret = [] + self._ret.proguard_configs.update(params.get('proguard_configs', [])) + self._ret.proguard_configs.update( + all_deps.collect('proguard_configs', flatten=True)) - def helper(cur): - for config in cur.Direct('java_library'): - if config['is_prebuilt']: - pass - elif config.get('gradle_treat_as_prebuilt'): - all_deps = config.get('deps_configs', []) + config.get( - 'public_deps_configs', []) - helper(Deps(all_deps)) - elif config not in ret: - ret.append(config) + if params.is_bundle_module() and self._remove_parent_module_overlap: + self._RemoveParentModuleOverlap() - helper(self) - return ret + # If there are deps common between dist_jar() and non-dist_jar(), then + # subtract them off the full classpath to avoid double-deps. + for dist_jar_params in all_deps.of_type('dist_jar'): + self._RemoveJarsOwnedByDistJars(dist_jar_params) + + if apk_under_test_params := params.apk_under_test(): + self._RemoveApkUnderTestOverlap(apk_under_test_params) + + if params.is_bundle_module() and not params.is_base_module(): + self._AddBaseModuleToClasspath() + return self._ret + + def _CollectClasspath(self, direct_deps, all_deps): + params = self._params + ret = self._ret + # Bundle modules do not depend on each other because their names do not + # match the java naming scheme that identifies them as libraries. + # TODO(agrieve): Recognize bundle module names as java_library targets so + # that they contribute to classpath. + ret.direct_unprocessed_jars.update( + direct_deps.collect('unprocessed_jar_path')) + ret.direct_interface_jars.update(direct_deps.collect('interface_jar_path')) + ret.all_unprocessed_jars.update(all_deps.collect('unprocessed_jar_path')) + ret.all_interface_jars.update(all_deps.collect('interface_jar_path')) + + # Deps to add to the compile-time classpath (but not the runtime + # classpath). + ret.direct_input_jars_paths.update(params.get('input_jars_paths', [])) + ret.direct_input_jars_paths.update( + direct_deps.collect('input_jars_paths', flatten=True)) + ret.all_input_jars_paths.update(params.get('input_jars_paths', [])) + ret.all_input_jars_paths.update( + all_deps.collect('input_jars_paths', flatten=True)) + + # Add the target's .jar (except for dist_jar, where it's the output .jar). + if params.collects_processed_classpath(): + if not params.is_dist_jar(): + if path := params.get('processed_jar_path'): + ret.all_processed_jars.add(path) + ret.all_processed_jars.update(all_deps.collect('processed_jar_path')) + + if params.collects_dex_paths(): + if not params.is_dist_jar(): + if path := params.get('dex_path'): + ret.all_dex_files.add(path) + ret.all_dex_files.update(all_deps.collect('dex_path')) + + def _AddBaseModuleToClasspath(self): + base_module = self._params.base_module() + # Adding base module to classpath to compile against its R.java file + self._ret.direct_unprocessed_jars.add(base_module['unprocessed_jar_path']) + self._ret.all_unprocessed_jars.add(base_module['unprocessed_jar_path']) + self._ret.direct_interface_jars.add(base_module['interface_jar_path']) + self._ret.all_interface_jars.add(base_module['interface_jar_path']) + + def _CollectManifests(self, all_deps_without_under_test): + # Manifests are listed from highest priority to lowest priority. + # Ensure direct manifests come first, then sort the rest by name. + # https://developer.android.com/build/manage-manifests#merge_priorities + params = self._params + ret = self._ret + ret.android_manifests.update(params.get('mergeable_android_manifests', [])) + indirect_manifests = all_deps_without_under_test.collect( + 'mergeable_android_manifests', flatten=True) + indirect_manifests.sort(key=lambda p: (os.path.basename(p), p)) + ret.android_manifests.update(indirect_manifests) + # Prevent the main manifest from showing up in mergeable_android_manifests. + if path := params.get('android_manifest'): + if path in ret.android_manifests: + ret.android_manifests.remove(path) + + def _CollectResources(self, all_deps_without_under_test): + params = self._params + ret = self._ret + resource_deps = params.resource_deps() + ret.dependency_zips.update(resource_deps.collect('resources_zip')) + ret.dependency_zip_overlays.update( + resource_deps.collect('resources_overlay_zip')) + + assets, uncompressed_assets, locale_paks = _MergeAssets( + all_deps_without_under_test.of_type('android_assets')) + ret.assets.update(assets) + ret.uncompressed_assets.update(uncompressed_assets) + ret.locale_paks = locale_paks + + if params.get('java_resources_jar_path'): + ret.java_resources_jars.add(params) + ret.java_resources_jars.update( + all_deps_without_under_test.collect('java_resources_jar_path')) + + def _CollectExtraPackageNames(self, direct_deps, all_deps): + # Needed by java_library targets. + if self._params.is_library(): + # TODO(agrieve): We would ideally move away from being able to use R.java + # from package_names other than the library's own. + resource_deps = direct_deps.of_type('android_resources') + else: + resource_deps = all_deps.recursive_resource_deps() + self._ret.extra_package_names.update(resource_deps.collect('package_name')) + if name := self._params.get('package_name'): + self._ret.extra_package_names.add(name) + + def _RemoveJarsOwnedByDistJars(self, dist_jar_params): + """Removes jars from a _TransitiveValues object that are owned by a + dist_jar. + """ + if dist_jar_params.get('use_interface_jars'): + return + if dist_jar_params.get('direct_deps_only'): + deps = dist_jar_params.deps() + dist_jar_tvs = _TransitiveValues() + dist_jar_tvs.all_unprocessed_jars = deps.collect('unprocessed_jar_path') + dist_jar_tvs.all_interface_jars = deps.collect('interface_jar_path') + dist_jar_tvs.all_dex_files = deps.collect('dex_path') + dist_jar_tvs.all_processed_jars = deps.collect('processed_jar_path') + else: + dist_jar_tvs = _TransitiveValuesBuilder(dist_jar_params).Build() + + self._ret.RemoveSubtree(dist_jar_tvs, + retain_resource_zips=True, + retain_extra_package_names=True) + self._ret.direct_unprocessed_jars.difference_update( + dist_jar_tvs.direct_unprocessed_jars) + self._ret.direct_interface_jars.difference_update( + dist_jar_tvs.direct_interface_jars) + + def _RemoveParentModuleOverlap(self): + # There are two approaches to dealing with modules dependencies: + # 1) Perform steps in android_apk_or_module(), with only the knowledge of + # ancesstor splits. + # 2) Perform steps in android_app_bundle(), with knowledge of full set of + # modules. This is required for dex because it can handle the case of + # two leaf nodes having the same dep, and promoting that dep to their + # common parent. + # _PromoteToCommonAncestor() implements this approach. + # + # We do 1) unconditionally, and 2) for dex / proguard, but we really + # should do 2) for all applicable fields. + if parent_module := self._params.parent_module(): + x = _TransitiveValuesBuilder(parent_module, + remove_parent_module_overlap=False).Build() + self._ret.RemoveSubtree(x) + + def _RemoveApkUnderTestOverlap(self, apk_under_test_params): + # The java code for an instrumentation test apk is assembled differently + # for R8 vs. non-R8. + # + # Without R8: Each library's jar is dexed separately and then combined + # into a single classes.dex. A test apk will include all dex files not + # present in the apk-under-test. At runtime all test code lives in the + # test apk, and the program code lives in the apk-under-test. + # + # With R8: Each library's .jar file is fed into R8, which outputs + # a single .jar, which is then dexed into a classes.dex. A test apk + # includes all jar files from the program and the tests because having + # them separate doesn't work with R8's whole-program optimizations. + # Although the apk-under-test still has all of its code in its + # classes.dex, none of it is used at runtime because the copy within the + # test apk takes precedence. + self._ret.RemoveSubtree( + _TransitiveValuesBuilder(apk_under_test_params).Build(), + retain_processed_jars=self._params.get('proguard_enabled'), + retain_unprocessed_jars=True, + retain_resource_zips=True, + retain_android_manifests=True) def _MergeAssets(all_assets): @@ -236,133 +400,6 @@ def _MergeAssets(all_assets): return create_list(compressed), create_list(uncompressed), locale_paks -def _SuffixAssets(suffix_names, suffix, assets): - new_assets = [] - for x in assets: - src_path, apk_subpath = x.split(':', 1) - if apk_subpath in suffix_names: - apk_subpath += suffix - new_assets.append(f'{src_path}:{apk_subpath}') - return new_assets - - -def _ResolveGroupsAndPublicDeps(config_paths): - """Returns a list of configs with all groups inlined.""" - - def helper(config_path): - config = GetDepConfig(config_path) - if config['type'] == 'group': - # Groups combine public_deps with deps_configs, so no need to check - # public_config_paths separately. - return config.get('deps_configs', []) - if config['type'] == 'android_resources': - # android_resources targets do not support public_deps, but instead treat - # all resource deps as public deps. - return DepPathsOfType('android_resources', config.get('deps_configs', [])) - - return config.get('public_deps_configs', []) - - return build_utils.GetSortedTransitiveDependencies(config_paths, helper) - - -def _DepsFromPaths(dep_paths, - target_type, - filter_root_targets=True, - recursive_resource_deps=False): - """Resolves all groups and trims dependency branches that we never want. - - E.g. When a resource or asset depends on an apk target, the intent is to - include the .apk as a resource/asset, not to have the apk's classpath added. - - This method is meant to be called to get the top nodes (i.e. closest to - current target) that we could then use to get a full transitive dependants - list (eg using Deps#all). So filtering single elements out of this list, - filters whole branches of dependencies. By resolving groups (i.e. expanding - them to their constituents), depending on a group is equivalent to directly - depending on each element of that group. - """ - blocklist = [] - allowlist = [] - - # Don't allow root targets to be considered as a dep. - if filter_root_targets: - blocklist.extend(_ROOT_TYPES) - - # Don't allow java libraries to cross through assets/resources. - if target_type in _RESOURCE_TYPES: - allowlist.extend(_RESOURCE_TYPES) - # Pretend that this target directly depends on all of its transitive - # dependencies. - if recursive_resource_deps: - dep_paths = GetAllDepsConfigsInOrder(dep_paths) - # Exclude assets if recursive_resource_deps is set. The - # recursive_resource_deps arg is used to pull resources into the base - # module to workaround bugs accessing resources in isolated DFMs, but - # assets should be kept in the DFMs. - blocklist.append('android_assets') - - return _DepsFromPathsWithFilters(dep_paths, blocklist, allowlist) - - -def _FilterConfigPaths(dep_paths, blocklist=None, allowlist=None): - if not blocklist and not allowlist: - return dep_paths - configs = [GetDepConfig(p) for p in dep_paths] - if blocklist: - configs = [c for c in configs if c['type'] not in blocklist] - if allowlist: - configs = [c for c in configs if c['type'] in allowlist] - - return [c['path'] for c in configs] - - -def _DepsFromPathsWithFilters(dep_paths, blocklist=None, allowlist=None): - """Resolves all groups and trims dependency branches that we never want. - - See _DepsFromPaths. - - |blocklist| if passed, are the types of direct dependencies we do not care - about (i.e. tips of branches that we wish to prune). - - |allowlist| if passed, are the only types of direct dependencies we care - about (i.e. we wish to prune all other branches that do not start from one of - these). - """ - # Filter both before and after so that public_deps of blocked targets are not - # added. - allowlist_with_groups = None - if allowlist: - allowlist_with_groups = set(allowlist) - allowlist_with_groups.add('group') - dep_paths = _FilterConfigPaths(dep_paths, blocklist, allowlist_with_groups) - dep_paths = _ResolveGroupsAndPublicDeps(dep_paths) - dep_paths = _FilterConfigPaths(dep_paths, blocklist, allowlist) - - return Deps(dep_paths) - - -def _ExtractSharedLibsFromRuntimeDeps(runtime_deps_file): - ret = [] - with open(runtime_deps_file, encoding='utf-8') as f: - for line in f: - line = line.rstrip() - if not line.endswith('.so'): - continue - # Only unstripped .so files are listed in runtime deps. - # Convert to the stripped .so by going up one directory. - ret.append(os.path.normpath(line.replace('lib.unstripped/', ''))) - ret.reverse() - return ret - - -def _CreateJavaLibrariesList(library_paths): - """Returns a java literal array with the "base" library names: - e.g. libfoo.so -> foo - """ - names = ['"%s"' % os.path.basename(s)[3:-3] for s in library_paths] - return ('{%s}' % ','.join(sorted(set(names)))) - - def _CreateJavaLocaleListFromAssets(assets, locale_paks): """Returns a java literal array from a list of locale assets. @@ -382,39 +419,24 @@ def _CreateJavaLocaleListFromAssets(assets, locale_paks): def _AddJarMapping(jar_to_target, config): + """Adds mappings from jar path to GN target for a given config.""" if jar := config.get('unprocessed_jar_path'): jar_to_target[jar] = config['gn_target'] for jar in config.get('input_jars_paths', []): jar_to_target[jar] = config['gn_target'] -def _CompareClasspathPriority(dep): - return 1 if dep.get('low_classpath_priority') else 0 - - -def _DedupFeatureModuleSharedCode(child_to_ancestors, modules, - field_names_to_dedup): - # Strip out duplicates from ancestors. - for name, module in modules.items(): - if name == 'base': - continue - # Make sure we get all ancestors, not just direct parent. - for ancestor in child_to_ancestors[name]: - for f in field_names_to_dedup: - if f in module: - RemoveObjDups(module, modules[ancestor], f) - - # Strip out duplicates from siblings/cousins. - for f in field_names_to_dedup: - _PromoteToCommonAncestor(modules, child_to_ancestors, f) - - def _PromoteToCommonAncestor(modules, child_to_ancestors, field_name): + """Finds duplicates of a field across modules and moves them to the + nearest common ancestor module. This is used for app bundles to avoid + duplicating dependencies in multiple modules. + """ module_to_fields_set = {} for module_name, module in modules.items(): if field_name in module: module_to_fields_set[module_name] = set(module[field_name]) + # Find all items that are duplicated across at least two modules. seen = set() dupes = set() for fields in module_to_fields_set.values(): @@ -433,694 +455,358 @@ def _PromoteToCommonAncestor(modules, child_to_ancestors, field_name): # farthest, where "base" should always be the last element. # Arbitrarily using the first owning module - any would work. for ancestor in child_to_ancestors[owning_modules[0]]: - ancestor_is_shared_with_all = True for o in owning_modules[1:]: - if ancestor not in child_to_ancestors[o]: - ancestor_is_shared_with_all = False + if ancestor not in child_to_ancestors[o] and ancestor is not o: break - if ancestor_is_shared_with_all: + else: common_ancestor = ancestor break + else: + raise Exception('Should have already removed ancestor dupes. ' + + ','.join(owning_modules) + ' field=' + field_name + + ' dupes: ' + ','.join(dupes)) + # Move the duplicated item to the common ancestor. for o in owning_modules: module_to_fields_set[o].remove(d) module_to_fields_set[common_ancestor].add(d) + # Update the original modules dictionary with the de-duplicated lists. for module_name, module in modules.items(): if field_name in module: module[field_name] = sorted(list(module_to_fields_set[module_name])) -def _CopyBuildConfigsForDebugging(debug_dir): - shutil.rmtree(debug_dir, ignore_errors=True) - os.makedirs(debug_dir) - for src_path in _dep_config_cache: - dst_path = os.path.join(debug_dir, src_path) - assert dst_path.startswith(debug_dir), dst_path - os.makedirs(os.path.dirname(dst_path), exist_ok=True) - shutil.copy(src_path, dst_path) - print(f'Copied {len(_dep_config_cache)} .build_config.json into {debug_dir}') +def _DoPlatformChecks(params): + """Check for platform mismatches between a target and its dependencies.""" + # Robolectric is special in that it's an android target that runs on host. + # You are allowed to depend on both android |deps_require_android| and + # non-android |deps_not_support_android| targets. + if params.get('bypass_platform_checks') or params.get('requires_robolectric'): + return + + deps_require_android = [d for d in params.deps() if d.requires_android()] + deps_not_support_android = [ + d for d in params.deps() if not d.supports_android() + ] + + if deps_require_android and not params.requires_android(): + raise Exception('Some deps require building for the Android platform:\n' + + '\n'.join('* ' + d['gn_target'] + for d in deps_require_android)) + + if deps_not_support_android and params.supports_android(): + raise Exception('Not all deps support the Android platform:\n' + + '\n'.join('* ' + d['gn_target'] + for d in deps_not_support_android)) -def _ListFromDeps(deps, key_name): - return [config[key_name] for config in deps if key_name in config] +def _SuffixAssets(config, target_config): + """Adds a suffix to asset paths to avoid collisions.""" + + def helper(suffix_names, suffix, assets): + new_assets = [] + for x in assets: + src_path, apk_subpath = x.split(':', 1) + if apk_subpath in suffix_names: + apk_subpath += suffix + new_assets.append(f'{src_path}:{apk_subpath}') + return new_assets + + all_assets = target_config['assets'] + target_config['uncompressed_assets'] + suffix = '+' + target_config['package_name'] + '+' + suffix_names = {x.split(':', 1)[1].replace(suffix, '') for x in all_assets} + config['assets'] = helper(suffix_names, suffix, config['assets']) + config['uncompressed_assets'] = helper(suffix_names, suffix, + config['uncompressed_assets']) + config['apk_assets_suffixed_list'] = ','.join(f'"assets/{x}"' + for x in sorted(suffix_names)) + config['apk_assets_suffix'] = suffix -def _SetFromDeps(deps, key_name): - combined = set() - for config in deps: - if value := config.get(key_name): - if isinstance(value, str): - combined.add(value) +def _ToTraceEventRewrittenPath(jar_dir, path): + """Returns the path to the trace-event-rewritten version of a jar.""" + path = path.replace('../', '') + path = path.replace('obj/', '') + path = path.replace('gen/', '') + path = path.replace('.jar', '.tracing_rewritten.jar') + return os.path.join(jar_dir, path) + + +def _WriteLintJson(params, lint_json, main_config): + # Collect all sources and resources at the apk/bundle_module level. + aars = set() + srcjars = set() + sources = set() + resource_sources = set() + resource_zips = set() + + if path := params.get('target_sources_file'): + sources.add(path) + if paths := params.get('bundled_srcjars'): + srcjars.update(paths) + for c in params.deps().recursive(): + if c.get('chromium_code', True) and c.requires_android(): + if path := c.get('target_sources_file'): + sources.add(path) + if paths := c.get('bundled_srcjars'): + srcjars.update(paths) + if path := c.get('aar_path'): + aars.add(path) + + for c in params.resource_deps(): + if c.get('chromium_code', True): + # Prefer res_sources_path to resources_zips so that lint errors have + # real paths and to avoid needing to extract during lint. + if path := c.get('res_sources_path'): + resource_sources.add(path) else: - combined.update(value) - return combined + resource_zips.add( + c.get('resources_zip') or c.get('resources_overlay_zip')) + + if params.is_bundle(): + classpath = OrderedSet() + manifests = OrderedSet(p['android_manifest'] for p in params.module_deps()) + for m in params.module_deps(): + module_config = m.build_config_json() + classpath.update(module_config['javac_full_interface_classpath']) + manifests.update(module_config['extra_android_manifests']) + classpath = list(classpath) + manifests = list(manifests) + else: + classpath = main_config['javac_full_interface_classpath'] + manifests = [params['android_manifest']] + manifests += main_config['extra_android_manifests'] + + config = {} + config['aars'] = sorted(aars) + config['android_manifests'] = manifests + config['classpath'] = classpath + config['sources'] = sorted(sources) + config['srcjars'] = sorted(srcjars) + config['resource_sources'] = sorted(resource_sources) + config['resource_zips'] = sorted(resource_zips) + + build_utils.WriteJson(config, lint_json, only_if_changed=True) def main(): - parser = argparse.ArgumentParser() + parser = argparse.ArgumentParser( + description='Writes a .build_config.json file.') action_helpers.add_depfile_arg(parser) - parser.add_argument('--params', help='Path to .params.json file.') - parser.add_argument('--store-deps-for-debugging-to', - help='Path to copy all transitive build config files to.') + parser.add_argument('--output', help='.build_config.json to write.') options = parser.parse_args() + build_config_path = options.output - params = ReadJson(options.params) - output_path = options.params.replace('.params.json', '.build_config.json') + params = params_json_util.get_params( + build_config_path.replace('.build_config.json', '.params.json')) if lines := params.get('fail'): parser.error('\n'.join(lines)) - target_type = params['type'] + target_type = params.type - is_bundle_module = target_type == 'android_app_bundle_module' - is_apk = target_type == 'android_apk' + is_bundle_module = params.is_bundle_module() + is_apk = params.is_apk() is_apk_or_module = is_apk or is_bundle_module - is_bundle = target_type == 'android_app_bundle' + is_bundle = params.is_bundle() + has_classpath = params.has_classpath() + proguard_enabled = params.get('proguard_enabled', False) - is_java_target = target_type in ('java_binary', 'robolectric_binary', - 'java_annotation_processor', 'java_library', - 'android_apk', 'dist_aar', 'dist_jar', - 'system_java_library', - 'android_app_bundle_module') + if has_classpath: + _DoPlatformChecks(params) - deps_configs_paths = params.get('deps_configs', []) - public_deps_configs_paths = params.get('public_deps_configs', []) - deps_configs_paths += public_deps_configs_paths - deps = _DepsFromPaths( - deps_configs_paths, - target_type, - recursive_resource_deps=params.get('recursive_resource_deps')) - public_deps = _DepsFromPaths(public_deps_configs_paths, target_type) - processor_deps = _DepsFromPaths(params.get('processor_configs', []), - target_type, - filter_root_targets=False) + if is_bundle_module: + if parent_module_params := params.parent_module(): + # Validate uses_split matches the parent split's name. + parent_split_name = params.get('uses_split', 'base') + actual = parent_module_params['module_name'] + assert actual == parent_split_name, ( + f'uses_split={parent_split_name} but parent was {actual}') - all_inputs = deps.AllConfigPaths() + processor_deps.AllConfigPaths() + if is_bundle: + deps_proguard_enabled = [] + deps_proguard_disabled = [] + for module in params.module_deps(): + if module.get('proguard_enabled'): + deps_proguard_enabled.append(module['module_name']) + else: + deps_proguard_disabled.append(module['module_name']) + if deps_proguard_enabled and deps_proguard_disabled: + raise Exception('Deps %s have proguard enabled while deps %s have ' + 'proguard disabled' % + (deps_proguard_enabled, deps_proguard_disabled)) - if params.get('recursive_resource_deps'): - # Include java_library targets since changes to these targets can remove - # resource deps from the build, which would require rebuilding this target's - # build config file: crbug.com/1168655. - recursive_java_deps = _DepsFromPathsWithFilters( - GetAllDepsConfigsInOrder(deps_configs_paths), - allowlist=['java_library']) - all_inputs.extend(recursive_java_deps.AllConfigPaths()) + apk_under_test_params = params.apk_under_test() - system_library_deps = deps.Direct('system_java_library') - all_deps = deps.All() - all_library_deps = deps.All('java_library') + if is_apk and apk_under_test_params: + if apk_under_test_params['proguard_enabled']: + assert proguard_enabled, ( + 'proguard must be enabled for ' + 'instrumentation apks if it\'s enabled for the tested apk.') - direct_resources_deps = deps.Direct('android_resources') - if target_type == 'java_library': - # For Java libraries, restrict to resource targets that are direct deps, or - # are indirect via other resource targets. - # The indirect-through-other-targets ones are picked up because - # _ResolveGroupsAndPublicDeps() treats resource deps of resource targets as - # public_deps. - all_resources_deps = direct_resources_deps - else: - all_resources_deps = deps.All('android_resources') + if is_apk_or_module: + manifest = AndroidManifest(params['android_manifest']) + if not apk_under_test_params and manifest.GetInstrumentationElements(): + # This must then have instrumentation only for itself. + manifest.CheckInstrumentationElements(manifest.GetPackageName()) - if target_type == 'android_resources' and params.get( - 'recursive_resource_deps'): - # android_resources targets that want recursive resource deps also need to - # collect package_names from all library deps. This ensures the R.java files - # for these libraries will get pulled in along with the resources. - android_resources_library_deps = _DepsFromPathsWithFilters( - deps_configs_paths, allowlist=['java_library']).All('java_library') - else: - android_resources_library_deps = None + config = {} - base_module_build_config = None - if path := params.get('base_module_config'): - base_module_build_config = GetDepConfig(path) - parent_module_build_config = base_module_build_config - if path := params.get('parent_module_config'): - parent_module_build_config = GetDepConfig(path) - - config = collections.defaultdict(dict) - - # The paths we record as deps can differ from deps_config_paths: - # 1) Paths can be removed when blocked by _ROOT_TYPES / _RESOURCE_TYPES. - # 2) Paths can be added when promoted from group deps or public_deps of deps. - # Deps are promoted from groups/public_deps in order to make the filtering - # of 1) work through group() targets (which themselves are not resource - # targets, but should be treated as such when depended on by a resource - # target. A more involved filtering implementation could work to maintain - # the semantics of 1) without the need to promote deps, but we've avoided - # such an undertaking so far. - public_deps_set = set() - if public_deps_configs_paths: - resolved_public_deps_configs = [d['path'] for d in public_deps.Direct()] - if resolved_public_deps_configs != params.get('public_deps_configs', []): - config['public_deps_configs'] = resolved_public_deps_configs - public_deps_set.update(resolved_public_deps_configs) - - resolved_deps_configs = [ - d['path'] for d in deps.Direct() if d['path'] not in public_deps_set - ] - if resolved_deps_configs != params.get('deps_configs', []): - config['deps_configs'] = resolved_deps_configs - - apk_under_test_config = None if is_apk: config['apk_path'] = params['apk_path'] if path := params.get('incremental_install_json_path'): config['incremental_install_json_path'] = path config['incremental_apk_path'] = params['incremental_apk_path'] - if path := params.get('apk_under_test_config'): - apk_under_test_config = GetDepConfig(path) - config['gradle']['apk_under_test'] = os.path.basename( - apk_under_test_config['apk_path']) - - if is_java_target: - dependent_prebuilt_jars = deps.GradlePrebuiltJarPaths() - dependent_prebuilt_jars.sort() - if dependent_prebuilt_jars: - config['gradle']['dependent_prebuilt_jars'] = dependent_prebuilt_jars - - dependent_android_projects = [] - dependent_java_projects = [] - for c in deps.GradleLibraryProjectDeps(): - if c['requires_android']: - dependent_android_projects.append(c['path']) - else: - dependent_java_projects.append(c['path']) - - config['gradle']['dependent_android_projects'] = dependent_android_projects - config['gradle']['dependent_java_projects'] = dependent_java_projects - - if is_java_target: - # robolectric is special in that its an android target that runs on host. - # You are allowed to depend on both android |deps_require_android| and - # non-android |deps_not_support_android| targets. - if (not params.get('bypass_platform_checks') - and not params.get('requires_robolectric')): - deps_require_android = direct_resources_deps + [ - d for d in deps.Direct() if d.get('requires_android', False) - ] - deps_not_support_android = [ - d for d in deps.Direct() if not d.get('supports_android', True) - ] - - if deps_require_android and not params.get('requires_android'): - raise Exception( - 'Some deps require building for the Android platform:\n' + - '\n'.join('* ' + d['gn_target'] for d in deps_require_android)) - - if deps_not_support_android and params.get('supports_android'): - raise Exception('Not all deps support the Android platform:\n' + - '\n'.join('* ' + d['gn_target'] - for d in deps_not_support_android)) - - all_dex_files = [] - if is_apk_or_module or target_type == 'dist_jar': - all_dex_files = [c['dex_path'] for c in all_library_deps] - - # Classpath values filled in below (after applying apk_under_test_config). - if is_apk_or_module: - all_dex_files.append(params['dex_path']) if is_bundle_module: config['unprocessed_jar_path'] = params['unprocessed_jar_path'] config['res_size_info_path'] = params['res_size_info_path'] - if target_type == 'android_resources': - if not params.get('package_name'): - if path := params.get('android_manifest'): - manifest = AndroidManifest(path) - config['package_name'] = manifest.GetPackageName() + if has_classpath: + tv = _TransitiveValuesBuilder(params).Build() - if target_type in ('android_resources', 'android_apk', 'robolectric_binary', - 'dist_aar', 'android_app_bundle_module', 'java_library'): - dependency_zips = [] - dependency_zip_overlays = [] - for c in all_resources_deps: - if not c.get('resources_zip'): - continue + if apk_under_test_params: + assert is_apk + config['arsc_package_name'] = ( + apk_under_test_params.build_config_json()['package_name']) - dependency_zips.append(c['resources_zip']) - if c.get('resource_overlay'): - dependency_zip_overlays.append(c['resources_zip']) + config['classpath'] = list(tv.direct_unprocessed_jars) + list( + tv.direct_input_jars_paths) + config['interface_classpath'] = list(tv.direct_interface_jars) + list( + tv.direct_input_jars_paths) + # processor_configs will be of type 'java_annotation_processor', and so not + # included in deps().recursive().of_type('java_library'). Annotation + # processors run as part of the build, so need processed_jar_path. + processor_deps = params.processor_deps() + config['processor_classpath'] = _SortClasspath( + processor_deps.recursive()).collect('processed_jar_path') + config['processor_classes'] = sorted(processor_deps.collect('main_class')) - extra_package_names = [] + config['javac_full_classpath'] = (list(tv.all_unprocessed_jars) + + list(tv.all_input_jars_paths)) + config['javac_full_interface_classpath'] = (list(tv.all_interface_jars) + + list(tv.all_input_jars_paths)) - if target_type != 'android_resources': - extra_package_names = _ListFromDeps(all_resources_deps, 'package_name') - if name := params.get('package_name'): - extra_package_names.append(name) + if params.collects_processed_classpath(): + config['processed_classpath'] = list(tv.all_processed_jars) + if trace_events_jar_dir := params.get('trace_events_jar_dir'): + config['trace_event_rewritten_classpath'] = [ + _ToTraceEventRewrittenPath(trace_events_jar_dir, p) + for p in tv.all_processed_jars + ] - # android_resources targets which specified recursive_resource_deps may - # have extra_package_names. - for resources_dep in all_resources_deps: - extra_package_names.extend(resources_dep['extra_package_names']) - - # In final types (i.e. apks and modules) that create real R.java files, - # they must collect package names from java_libraries as well. - # https://crbug.com/1073476 - if target_type != 'java_library': - extra_package_names += _ListFromDeps(all_library_deps, 'package_name') - - elif params.get('recursive_resource_deps'): - # Pull extra_package_names from library deps if recursive resource deps - # are required. - extra_package_names = _ListFromDeps(android_resources_library_deps, - 'package_name') + if params.collects_dex_paths(): + config['all_dex_files'] = list(tv.all_dex_files) if target_type in ('dist_aar', 'java_library'): - paths = _ListFromDeps(all_resources_deps, 'rtxt_path') - config['dependency_rtxt_files'] = paths + config['dependency_rtxt_files'] = ( + params.resource_deps().collect('rtxt_path')) - if is_apk and apk_under_test_config: - config['arsc_package_name'] = apk_under_test_config['package_name'] - # We should not shadow the actual R.java files of the apk_under_test by - # creating new R.java files with the same package names in the tested apk. - extra_package_names = [ - package for package in extra_package_names - if package not in apk_under_test_config['extra_package_names'] - ] + sdk_deps = params.deps().of_type('system_java_library') + config['sdk_jars'] = sdk_deps.collect('unprocessed_jar_path') + config['sdk_interface_jars'] = sdk_deps.collect('interface_jar_path') + if proguard_enabled or target_type == 'dist_aar': + config['proguard_all_configs'] = sorted(tv.proguard_configs) + + if proguard_enabled: + config['proguard_classpath_jars'] = sorted(tv.all_input_jars_paths) + + if is_apk_or_module: + config['java_resources_jars'] = sorted(tv.java_resources_jars) + + if params.is_dist_jar(): + if params.get('direct_deps_only'): + if params.get('use_interface_jars'): + dist_jars = tv.direct_interface_jars + else: + dist_jars = params.deps().collect('processed_jar_path') + elif params.get('use_interface_jars'): + dist_jars = tv.all_interface_jars + else: + dist_jars = tv.all_processed_jars + + config['dist_jar'] = {} + config['dist_jar']['jars'] = list(dist_jars) + + if params.collects_resources(): # Safe to sort: Build checks that non-overlay resource have no overlap. - dependency_zips.sort() - config['dependency_zips'] = dependency_zips - config['dependency_zip_overlays'] = dependency_zip_overlays - # Order doesn't matter, so make stable. - extra_package_names.sort() - config['extra_package_names'] = extra_package_names + config['dependency_zips'] = sorted(tv.dependency_zips) + config['dependency_zip_overlays'] = list(tv.dependency_zip_overlays) + config['assets'] = sorted(tv.assets) + config['uncompressed_assets'] = sorted(tv.uncompressed_assets) - mergeable_android_manifests = params.get('mergeable_android_manifests', []) - mergeable_android_manifests.sort() - if mergeable_android_manifests: - config['mergeable_android_manifests'] = mergeable_android_manifests + if params.get('create_locales_java_list'): + config['locales_java_list'] = _CreateJavaLocaleListFromAssets( + tv.uncompressed_assets, tv.locale_paks) - extra_proguard_classpath_jars = [] - proguard_configs = params.get('proguard_configs', []) + if params.compiles_resources(): + config['extra_package_names'] = sorted(tv.extra_package_names) - if is_java_target: - classpath_direct_deps = deps.Direct() - classpath_direct_library_deps = deps.Direct('java_library') - - # The classpath used to compile this target when annotation processors are - # present. - javac_classpath = _SetFromDeps(classpath_direct_library_deps, - 'unprocessed_jar_path') - # The classpath used to compile this target when annotation processors are - # not present. These are also always used to know when a target needs to be - # rebuilt. - javac_interface_classpath = _SetFromDeps(classpath_direct_library_deps, - 'interface_jar_path') - - # Preserve order of |all_library_deps|. Move low priority libraries to the - # end of the classpath. - all_library_deps_sorted_for_classpath = sorted( - all_library_deps[::-1], key=_CompareClasspathPriority) - - # The classpath used for bytecode-rewritting. - javac_full_classpath = OrderedSet.fromkeys( - c['unprocessed_jar_path'] - for c in all_library_deps_sorted_for_classpath) - # The classpath used for error prone. - javac_full_interface_classpath = OrderedSet.fromkeys( - c['interface_jar_path'] for c in all_library_deps_sorted_for_classpath) - - # Adding base module to classpath to compile against its R.java file - if base_module_build_config: - javac_full_classpath.add(base_module_build_config['unprocessed_jar_path']) - javac_full_interface_classpath.add( - base_module_build_config['interface_jar_path']) - # Turbine now compiles headers against only the direct classpath, so the - # base module's interface jar must be on the direct interface classpath. - javac_interface_classpath.add( - base_module_build_config['interface_jar_path']) - - for dep in classpath_direct_deps: - if paths := dep.get('input_jars_paths'): - javac_classpath.update(paths) - javac_interface_classpath.update(paths) - for dep in all_deps: - if paths := dep.get('input_jars_paths'): - javac_full_classpath.update(paths) - javac_full_interface_classpath.update(paths) - - # TODO(agrieve): Might be less confusing to fold these into bootclasspath. - # Deps to add to the compile-time classpath (but not the runtime classpath). - # These are jars specified by input_jars_paths that almost never change. - # Just add them directly to all the classpaths. - if paths := params.get('input_jars_paths'): - javac_classpath.update(paths) - javac_interface_classpath.update(paths) - javac_full_classpath.update(paths) - javac_full_interface_classpath.update(paths) - - if is_java_target or is_bundle: - # The classpath to use to run this target (or as an input to ProGuard). - device_classpath = [] - # dist_jar configs should not list their device jar in their own classpath - # since the classpath is used to create the device jar itself. - if is_java_target and target_type != 'dist_jar': - if path := params.get('processed_jar_path'): - device_classpath.append(path) - device_classpath += _ListFromDeps(all_library_deps, 'processed_jar_path') - if is_bundle: - for d in deps.Direct('android_app_bundle_module'): - device_classpath.extend(c for c in d.get('device_classpath', []) - if c not in device_classpath) - - all_dist_jar_deps = deps.All('dist_jar') - - # We allow lint to be run on android_apk targets, so we collect lint - # artifacts for them. - # We allow lint to be run on android_app_bundle targets, so we need to - # collect lint artifacts for the android_app_bundle_module targets that the - # bundle includes. Different android_app_bundle targets may include different - # android_app_bundle_module targets, so the bundle needs to be able to - # de-duplicate these lint artifacts. - if is_apk_or_module: - # Collect all sources and resources at the apk/bundle_module level. - lint_aars = set() - lint_srcjars = set() - lint_sources = set() - lint_resource_sources = set() - lint_resource_zips = set() - - if path := params.get('target_sources_file'): - lint_sources.add(path) - if paths := params.get('bundled_srcjars'): - lint_srcjars.update(paths) - for c in all_library_deps: - if c.get('chromium_code', True) and c['requires_android']: - if path := c.get('target_sources_file'): - lint_sources.add(path) - lint_srcjars.update(c['bundled_srcjars']) - if path := c.get('aar_path'): - lint_aars.add(path) - - if path := params.get('res_sources_path'): - lint_resource_sources.add(path) - if path := params.get('resources_zip'): - lint_resource_zips.add(path) - for c in all_resources_deps: - if c.get('chromium_code', True): - # Prefer res_sources_path to resources_zips so that lint errors have - # real paths and to avoid needing to extract during lint. - if path := c.get('res_sources_path'): - lint_resource_sources.add(path) - else: - lint_resource_zips.add(c['resources_zip']) - - config['lint_aars'] = sorted(lint_aars) - config['lint_srcjars'] = sorted(lint_srcjars) - config['lint_sources'] = sorted(lint_sources) - config['lint_resource_sources'] = sorted(lint_resource_sources) - config['lint_resource_zips'] = sorted(lint_resource_zips) - config['lint_extra_android_manifests'] = [] + if params.merges_manifests(): + config['extra_android_manifests'] = list(tv.android_manifests) if is_bundle: - modules_by_name = {m['name']: m for m in params['modules']} + module_deps = params.module_deps() + module_params_by_name = {m['module_name']: m for m in module_deps} module_configs_by_name = { - m['name']: GetDepConfig(m['build_config']) - for m in params['modules'] + m['module_name']: m.build_config_json() + for m in module_deps } - modules = {name: {} for name in modules_by_name} + modules = {m: {} for m in module_params_by_name} - child_to_ancestors = {n: ['base'] for n in modules_by_name} - for name, module in modules_by_name.items(): - while parent := module.get('uses_split'): - child_to_ancestors[name].append(parent) - module = modules_by_name[parent] + child_to_ancestors = {n: [] for n in module_params_by_name} + for name, module in module_params_by_name.items(): + while module := module.parent_module(): + child_to_ancestors[name].append(module['module_name']) per_module_fields = [ - 'device_classpath', 'trace_event_rewritten_device_classpath', - 'all_dex_files', 'assets', 'uncompressed_assets' + 'processed_classpath', + 'trace_event_rewritten_classpath', + 'all_dex_files', + 'assets', + 'uncompressed_assets', ] - lint_aars = set() - lint_srcjars = set() - lint_sources = set() - lint_resource_sources = set() - lint_resource_zips = set() - lint_extra_android_manifests = set() + union_fields = {} + if params.get('trace_events_jar_dir'): + union_fields['processed_classpath'] = 'processed_classpath' + union_fields['trace_event_rewritten_classpath'] = ( + 'trace_event_rewritten_classpath') + if proguard_enabled: + union_fields['proguard_classpath_jars'] = 'proguard_classpath_jars' + union_fields['proguard_all_configs'] = 'proguard_all_configs' + union_fields['sdk_jars'] = 'sdk_jars' + + unioned_values = {k: OrderedSet() for k in union_fields} for n, c in module_configs_by_name.items(): + module_params = module_params_by_name[n] if n == 'base': assert 'base_module_config' not in config, ( 'Must have exactly 1 base module!') config['package_name'] = c['package_name'] - config['version_code'] = c['version_code'] - config['version_name'] = c['version_name'] - config['base_module_config'] = c['path'] - config['android_manifest'] = c['android_manifest'] - else: - # All manifests nodes are merged into the main manfiest by lint.py. - lint_extra_android_manifests.add(c['android_manifest']) + config['version_code'] = module_params['version_code'] + config['version_name'] = module_params['version_name'] + config['base_module_config'] = module_params.path + config['android_manifest'] = module_params['android_manifest'] + + for dst_key, src_key in union_fields.items(): + unioned_values[dst_key].update(c[src_key]) - lint_extra_android_manifests.update(c['extra_android_manifests']) - lint_aars.update(c['lint_aars']) - lint_srcjars.update(c['lint_srcjars']) - lint_sources.update(c['lint_sources']) - lint_resource_sources.update(c['lint_resource_sources']) - lint_resource_zips.update(c['lint_resource_zips']) module = modules[n] - module['final_dex_path'] = c['final_dex_path'] + module['final_dex_path'] = module_params['final_dex_path'] for f in per_module_fields: if f in c: module[f] = c[f] - config['lint_aars'] = sorted(lint_aars) - config['lint_srcjars'] = sorted(lint_srcjars) - config['lint_sources'] = sorted(lint_sources) - config['lint_resource_sources'] = sorted(lint_resource_sources) - config['lint_resource_zips'] = sorted(lint_resource_zips) - config['lint_extra_android_manifests'] = sorted( - lint_extra_android_manifests) - _DedupFeatureModuleSharedCode(child_to_ancestors, modules, - per_module_fields) + for dst_key in union_fields: + config[dst_key] = list(unioned_values[dst_key]) + + # Promote duplicates from siblings/cousins. + for f in per_module_fields: + _PromoteToCommonAncestor(modules, child_to_ancestors, f) config['modules'] = modules - if is_java_target or (is_bundle and params.get('proguard_enabled')): - config['sdk_jars'] = [ - c['unprocessed_jar_path'] for c in system_library_deps - ] - config['sdk_interface_jars'] = [ - c['interface_jar_path'] for c in system_library_deps - ] - - if target_type in ('android_apk', 'dist_aar', 'dist_jar', - 'android_app_bundle_module', 'android_app_bundle'): - for c in all_deps: - proguard_configs.extend(c.get('proguard_configs', [])) - extra_proguard_classpath_jars.extend(c.get('input_jars_paths', [])) - if is_bundle: - for c in deps.Direct('android_app_bundle_module'): - proguard_configs.extend(c.get('proguard_configs', [])) - extra_proguard_classpath_jars.extend( - j for j in c.get('proguard_classpath_jars', []) - if j not in extra_proguard_classpath_jars) - - deps_proguard_enabled = [] - deps_proguard_disabled = [] - for d in deps.Direct('android_app_bundle_module'): - if not d['device_classpath']: - # We don't care about modules that have no Java code for proguarding. - continue - if d.get('proguard_enabled'): - deps_proguard_enabled.append(d['module_name']) - else: - deps_proguard_disabled.append(d['module_name']) - if deps_proguard_enabled and deps_proguard_disabled: - raise Exception('Deps %s have proguard enabled while deps %s have ' - 'proguard disabled' % (deps_proguard_enabled, - deps_proguard_disabled)) - - # The java code for an instrumentation test apk is assembled differently for - # R8 vs. non-R8. - # - # Without R8: Each library's jar is dexed separately and then combined - # into a single classes.dex. A test apk will include all dex files not already - # present in the apk-under-test. At runtime all test code lives in the test - # apk, and the program code lives in the apk-under-test. - # - # With R8: Each library's .jar file is fed into R8, which outputs - # a single .jar, which is then dexed into a classes.dex. A test apk includes - # all jar files from the program and the tests because having them separate - # doesn't work with R8's whole-program optimizations. Although the - # apk-under-test still has all of its code in its classes.dex, none of it is - # used at runtime because the copy of it within the test apk takes precidence. - - if is_apk and apk_under_test_config: - if apk_under_test_config['proguard_enabled']: - assert params.get('proguard_enabled'), ( - 'proguard must be enabled for ' - 'instrumentation apks if it\'s enabled for the tested apk.') - # Mutating lists, so no need to explicitly re-assign to dict. - proguard_configs.extend(apk_under_test_config['proguard_all_configs']) - extra_proguard_classpath_jars.extend( - apk_under_test_config['proguard_classpath_jars']) - - # Add all tested classes to the test's classpath to ensure that the test's - # java code is a superset of the tested apk's java code - device_classpath_extended = list(device_classpath) - device_classpath_extended.extend( - p for p in apk_under_test_config['device_classpath'] - if p not in device_classpath) - # Include in the classpath classes that are added directly to the apk under - # test (those that are not a part of a java_library). - javac_classpath.add(apk_under_test_config['unprocessed_jar_path']) - javac_interface_classpath.add(apk_under_test_config['interface_jar_path']) - javac_full_classpath.add(apk_under_test_config['unprocessed_jar_path']) - javac_full_interface_classpath.add( - apk_under_test_config['interface_jar_path']) - javac_full_classpath.update(apk_under_test_config['javac_full_classpath']) - javac_full_interface_classpath.update( - apk_under_test_config['javac_full_interface_classpath']) - - # Exclude .jar files from the test apk that exist within the apk under test. - apk_under_test_deps = Deps([apk_under_test_config['path']]) - apk_under_test_library_deps = apk_under_test_deps.All('java_library') - apk_under_test_dex_files = { - c['dex_path'] - for c in apk_under_test_library_deps - } - all_dex_files = [ - p for p in all_dex_files if p not in apk_under_test_dex_files - ] - apk_under_test_jar_files = set(apk_under_test_config['device_classpath']) - device_classpath = [ - p for p in device_classpath if p not in apk_under_test_jar_files - ] - - if target_type in ('android_apk', 'dist_aar', 'dist_jar', - 'android_app_bundle_module', 'android_app_bundle'): - config['proguard_all_configs'] = sorted(set(proguard_configs)) - config['proguard_classpath_jars'] = sorted( - set(extra_proguard_classpath_jars)) - - if target_type in ('dist_jar', 'java_binary', 'robolectric_binary'): - # The classpath to use to run this target. - host_classpath = [] - if path := params.get('processed_jar_path'): - host_classpath.append(path) - host_classpath.extend(c['processed_jar_path'] for c in all_library_deps) - # Collect all the dist_jar host jars. - dist_jar_host_jars = _ListFromDeps(all_dist_jar_deps, 'processed_jar_path') - # Collect all the jars that went into the dist_jar host jars. - dist_jar_host_classpath = _SetFromDeps(all_dist_jar_deps, 'host_classpath') - # Remove the jars that went into the dist_jar host jars. - host_classpath = [ - p for p in host_classpath if p not in dist_jar_host_classpath - ] - # Add the dist_jar host jars themselves instead. - host_classpath += dist_jar_host_jars - config['host_classpath'] = host_classpath - - if is_java_target: - dist_jar_device_classpath = _SetFromDeps(all_dist_jar_deps, - 'device_classpath') - dist_jar_javac_full_classpath = _SetFromDeps(all_dist_jar_deps, - 'javac_full_classpath') - dist_jar_javac_full_interface_classpath = _SetFromDeps( - all_dist_jar_deps, 'javac_full_interface_classpath') - dist_jar_child_dex_files = _SetFromDeps(all_dist_jar_deps, 'all_dex_files') - - dist_jar_device_jars = _ListFromDeps(all_dist_jar_deps, - 'processed_jar_path') - dist_jar_combined_dex_files = _ListFromDeps(all_dist_jar_deps, 'dex_path') - dist_jar_interface_jars = _ListFromDeps(all_dist_jar_deps, - 'interface_jar_path') - dist_jar_unprocessed_jars = _ListFromDeps(all_dist_jar_deps, - 'unprocessed_jar_path') - - device_classpath = [ - p for p in device_classpath if p not in dist_jar_device_classpath - ] - device_classpath += dist_jar_device_jars - - javac_full_classpath.difference_update(dist_jar_javac_full_classpath) - javac_full_classpath.update(dist_jar_unprocessed_jars) - - javac_full_interface_classpath.difference_update( - dist_jar_javac_full_interface_classpath) - javac_full_interface_classpath.update(dist_jar_interface_jars) - - javac_interface_classpath.update(dist_jar_interface_jars) - javac_classpath.update(dist_jar_unprocessed_jars) - - if is_apk_or_module or target_type == 'dist_jar': - all_dex_files = [ - p for p in all_dex_files if p not in dist_jar_child_dex_files - ] - all_dex_files += dist_jar_combined_dex_files - - if is_apk_or_module or target_type == 'dist_jar': - # Dependencies for the final dex file of an apk. - config['all_dex_files'] = all_dex_files - - if is_java_target: - config['classpath'] = sorted(javac_classpath) - config['interface_classpath'] = sorted(javac_interface_classpath) - # Direct() will be of type 'java_annotation_processor', and so not included - # in All('java_library'). - # Annotation processors run as part of the build, so need processed_jar_path. - config['processor_classpath'] = _ListFromDeps( - processor_deps.Direct() + processor_deps.All('java_library'), - 'processed_jar_path') - config['processor_classes'] = sorted(c['main_class'] - for c in processor_deps.Direct()) - config['javac_full_classpath'] = list(javac_full_classpath) - config['javac_full_interface_classpath'] = list( - javac_full_interface_classpath) - elif is_bundle: - # bundles require javac_full_classpath to create .aab.jar.info and require - # javac_full_interface_classpath for lint. - javac_full_classpath = OrderedSet() - javac_full_interface_classpath = OrderedSet() - for d in deps.Direct('android_app_bundle_module'): - javac_full_classpath.update(d['javac_full_classpath']) - javac_full_interface_classpath.update(d['javac_full_interface_classpath']) - javac_full_classpath.add(d['unprocessed_jar_path']) - javac_full_interface_classpath.add(d['interface_jar_path']) - config['javac_full_classpath'] = list(javac_full_classpath) - config['javac_full_interface_classpath'] = list( - javac_full_interface_classpath) - - if target_type in ('android_apk', 'android_app_bundle', - 'android_app_bundle_module', 'dist_aar', 'dist_jar'): - config['device_classpath'] = device_classpath - if trace_events_jar_dir := params.get('trace_events_jar_dir'): - trace_event_rewritten_device_classpath = [] - for jar_path in device_classpath: - jar_path = jar_path.replace('../', '') - jar_path = jar_path.replace('obj/', '') - jar_path = jar_path.replace('gen/', '') - jar_path = jar_path.replace('.jar', '.tracing_rewritten.jar') - rewritten_jar_path = os.path.join(trace_events_jar_dir, jar_path) - trace_event_rewritten_device_classpath.append(rewritten_jar_path) - - config['trace_event_rewritten_device_classpath'] = ( - trace_event_rewritten_device_classpath) - - if apk_under_test_config: - config['device_classpath_extended'] = device_classpath_extended - - if target_type == 'dist_jar': - if params.get('direct_deps_only'): - if params.get('use_interface_jars'): - dist_jars = config['interface_classpath'] - else: - dist_jars = sorted(c['processed_jar_path'] - for c in classpath_direct_library_deps) - else: - if params.get('use_interface_jars'): - dist_jars = [c['interface_jar_path'] for c in all_library_deps] - else: - dist_jars = config['device_classpath'] - - config['dist_jar']['jars'] = dist_jars - if is_apk_or_module: - manifest = AndroidManifest(params['android_manifest']) - if not apk_under_test_config and manifest.GetInstrumentationElements(): - # This must then have instrumentation only for itself. - manifest.CheckInstrumentationElements(manifest.GetPackageName()) - config['package_name'] = manifest.GetPackageName() config['android_manifest'] = params['android_manifest'] config['merged_android_manifest'] = params['merged_android_manifest'] @@ -1133,34 +819,23 @@ def main(): if final_dex_path := params.get('final_dex_path'): config['final_dex_path'] = final_dex_path - library_paths = [] - java_libraries_list = None - if path := params.get('shared_libraries_runtime_deps_file'): - # GN does not add this input to avoid depending on the generated_file() target. - all_inputs.append(path) - library_paths = _ExtractSharedLibsFromRuntimeDeps(path) - java_libraries_list = _CreateJavaLibrariesList(library_paths) - - secondary_abi_library_paths = [] - if path := params.get('secondary_abi_shared_libraries_runtime_deps_file'): - all_inputs.append(path) - secondary_abi_library_paths = _ExtractSharedLibsFromRuntimeDeps(path) - secondary_abi_library_paths.sort() - paths_without_parent_dirs = [ - p for p in secondary_abi_library_paths if os.path.sep not in p - ] - if paths_without_parent_dirs: - sys.stderr.write('Found secondary native libraries from primary ' - 'toolchain directory. This is a bug!\n') - sys.stderr.write('\n'.join(paths_without_parent_dirs)) - sys.stderr.write('\n\nIt may be helpful to run: \n') - sys.stderr.write(' gn path out/Default //chrome/android:' - 'monochrome_secondary_abi_lib //base:base\n') - sys.exit(1) + library_paths = params.native_libraries() + secondary_abi_libraries = params.secondary_abi_native_libraries() + paths_without_parent_dirs = [ + p for p in secondary_abi_libraries if os.path.sep not in p + ] + if paths_without_parent_dirs: + sys.stderr.write('Found secondary native libraries from primary ' + 'toolchain directory. This is a bug!\n') + sys.stderr.write('\n'.join(paths_without_parent_dirs)) + sys.stderr.write('\n\nIt may be helpful to run: \n') + sys.stderr.write(' gn path out/Default //chrome/android:' + 'monochrome_secondary_abi_lib //base:base\n') + sys.exit(1) + config['native'] = {} config['native']['libraries'] = library_paths - config['native']['secondary_abi_libraries'] = secondary_abi_library_paths - config['native']['java_libraries_list'] = java_libraries_list + config['native']['secondary_abi_libraries'] = secondary_abi_libraries if is_bundle_module: loadable_modules = params.get('loadable_modules', []) @@ -1187,103 +862,21 @@ def main(): config['rtxt_path'] = params['rtxt_path'] config['module_pathmap_path'] = params['module_pathmap_path'] - # Collect java resources - java_resources_jars = _ListFromDeps(all_library_deps, - 'java_resources_jar_path') - if apk_under_test_config: - apk_under_test_resource_jars = _SetFromDeps(apk_under_test_library_deps, - 'java_resources_jar_path') - java_resources_jars = [ - jar for jar in java_resources_jars - if jar not in apk_under_test_resource_jars - ] - java_resources_jars.sort() - config['java_resources_jars'] = java_resources_jars - if is_apk_or_module or target_type == 'robolectric_binary': - # android_resources deps which had recursive_resource_deps set should not - # have the manifests from the recursively collected deps added to this - # module. This keeps the manifest declarations in the child DFMs, since they - # will have the Java implementations. - def ExcludeRecursiveResourcesDeps(config): - return not config.get('recursive_resource_deps', False) - - extra_manifest_deps = [ - GetDepConfig(p) for p in GetAllDepsConfigsInOrder( - deps_configs_paths, filter_func=ExcludeRecursiveResourcesDeps) - ] - # Manifests are listed from highest priority to lowest priority. - # Ensure directly manfifests come first, and then sort the rest by name. - # https://developer.android.com/build/manage-manifests#merge_priorities - config['extra_android_manifests'] = list(mergeable_android_manifests) - manifests_from_deps = [] - for c in extra_manifest_deps: - manifests_from_deps += c.get('mergeable_android_manifests', []) - manifests_from_deps.sort(key=lambda p: (os.path.basename(p), p)) - config['extra_android_manifests'] += manifests_from_deps - - assets, uncompressed_assets, locale_paks = _MergeAssets( - deps.All('android_assets')) - config['assets'] = assets - config['uncompressed_assets'] = uncompressed_assets - config['locales_java_list'] = _CreateJavaLocaleListFromAssets( - uncompressed_assets, locale_paks) if path := params.get('suffix_apk_assets_used_by_config'): - if path == output_path: + if path == build_config_path: target_config = config else: - target_config = GetDepConfig(path) - all_assets = (target_config['assets'] + - target_config['uncompressed_assets']) - suffix = '+' + target_config['package_name'] + '+' - suffix_names = { - x.split(':', 1)[1].replace(suffix, '') - for x in all_assets - } - config['assets'] = _SuffixAssets(suffix_names, suffix, assets) - config['uncompressed_assets'] = _SuffixAssets(suffix_names, suffix, - uncompressed_assets) - config['apk_assets_suffixed_list'] = ','.join( - f'"assets/{x}"' for x in sorted(suffix_names)) - config['apk_assets_suffix'] = suffix + target_config = params_json_util.get_build_config(path) + _SuffixAssets(config, target_config) - # DYNAMIC FEATURE MODULES: - # There are two approaches to dealing with modules dependencies: - # 1) Perform steps in android_apk_or_module(), with only the knowledge of - # ancesstor splits. Our implementation currently allows only for 2 levels: - # base -> parent -> leaf - # Bundletool normally fails if two leaf nodes merge the same manifest or - # resources. The fix is to add the common dep to the chrome or base module - # so that our deduplication logic will work. - # RemoveObjDups() implements this approach. - # 2) Perform steps in android_app_bundle(), with knowledge of full set of - # modules. This is required for dex because it can handle the case of two - # leaf nodes having the same dep, and promoting that dep to their common - # parent. - # _DedupFeatureModuleSharedCode() implements this approach. - if base_module_build_config: - ancestor_configs = [base_module_build_config] - if parent_module_build_config is not base_module_build_config: - ancestor_configs += [parent_module_build_config] - for c in ancestor_configs: - RemoveObjDups(config, c, 'dependency_zips') - RemoveObjDups(config, c, 'dependency_zip_overlays') - RemoveObjDups(config, c, 'extra_android_manifests') - RemoveObjDups(config, c, 'extra_package_names') - - if is_java_target: + if has_classpath: jar_to_target = {} - _AddJarMapping(jar_to_target, params) - for d in all_deps: + all_params = params.deps() + [params] + if apk_under_test_params: + all_params.append(apk_under_test_params) + for d in all_params.recursive(): _AddJarMapping(jar_to_target, d) - if base_module_build_config: - for c in ancestor_configs: - _AddJarMapping(jar_to_target, c) - if apk_under_test_config: - _AddJarMapping(jar_to_target, apk_under_test_config) - jar_to_target.update( - zip(apk_under_test_config['javac_full_classpath'], - apk_under_test_config['javac_full_classpath_targets'])) # Used by check_for_missing_direct_deps.py to give better error message # when missing deps are found. Both javac_full_classpath_targets and @@ -1293,17 +886,20 @@ def main(): jar_to_target[x] for x in config['javac_full_classpath'] ] - build_utils.WriteJson(config, output_path, only_if_changed=True) + if path := params.get('lint_json'): + _WriteLintJson(params, path, config) + + build_utils.WriteJson(config, build_config_path, only_if_changed=True) if options.depfile: - all_inputs += [ - p.replace('.build_config.json', '.params.json') for p in all_inputs - ] - action_helpers.write_depfile(options.depfile, output_path, all_inputs) - - if options.store_deps_for_debugging_to: - GetDepConfig(output_path) # Add it to cache. - _CopyBuildConfigsForDebugging(options.store_deps_for_debugging_to) + all_inputs = params_json_util.all_read_file_paths() + if path := params.get('shared_libraries_runtime_deps_file'): + # Path must be added to depfile because the GN template does not add this + # input to avoid having to depend on the generated_file() target. + all_inputs.append(path) + if path := params.get('secondary_abi_shared_libraries_runtime_deps_file'): + all_inputs.append(path) + action_helpers.write_depfile(options.depfile, build_config_path, all_inputs) if __name__ == '__main__': diff --git a/naiveproxy/src/build/android/gyp/write_build_config.pydeps b/naiveproxy/src/build/android/gyp/write_build_config.pydeps index ac0c355d3f..74c4ceebc0 100644 --- a/naiveproxy/src/build/android/gyp/write_build_config.pydeps +++ b/naiveproxy/src/build/android/gyp/write_build_config.pydeps @@ -4,4 +4,5 @@ ../../gn_helpers.py util/__init__.py util/build_utils.py +util/params_json_util.py write_build_config.py diff --git a/naiveproxy/src/build/android/java/templates/BuildConfig.template b/naiveproxy/src/build/android/java/templates/BuildConfig.template index c1465a6627..09bfe4779c 100644 --- a/naiveproxy/src/build/android/java/templates/BuildConfig.template +++ b/naiveproxy/src/build/android/java/templates/BuildConfig.template @@ -103,13 +103,26 @@ public class BuildConfig { public static String APK_ASSETS_SUFFIX = null; #endif - // Enable features that are more typically available on desktop. + // Use in conjunction with FEATURE_PC check to limit desktop-only + // features to devices with build flag. Should only be used in + // DeviceInfo.java since this is the source of truth for isDesktop check. + // (TODO: crbug.com/430983585) Clean up this flag once the desktop + // build is fully functional. #if defined(_IS_DESKTOP_ANDROID) public static boolean IS_DESKTOP_ANDROID = true; #else public static boolean IS_DESKTOP_ANDROID; #endif + // Controls whether or not native-only renderers are available. Note that this check isn't + // sufficient to determine whether they are enabled, but just whether they have been included + // in the build. +#if defined(_JAVALESS_RENDERERS_AVAILABLE) + public static boolean JAVALESS_RENDERERS_AVAILABLE = true; +#else + public static boolean JAVALESS_RENDERERS_AVAILABLE; +#endif + // Controls whether or not StrictModeContext is a no-op. #if defined(_DISABLE_STRICT_MODE_CONTEXT) public static boolean DISABLE_STRICT_MODE_CONTEXT = true; diff --git a/naiveproxy/src/build/android/list_java_targets.py b/naiveproxy/src/build/android/list_java_targets.py index 5f1a106a88..d83718d4f7 100755 --- a/naiveproxy/src/build/android/list_java_targets.py +++ b/naiveproxy/src/build/android/list_java_targets.py @@ -250,6 +250,10 @@ def main(): _compile(output_dir, ['build.ninja']) # Query ninja for all __build_config_crbug_908819 targets. + # TODO(agrieve): java_group, android_assets, and android_resources do not + # write .build_config.json files, and so will not show up by this query. + # If we ever need them to, use "gn gen" into a temp dir, and set an extra + # gn arg that causes all write_build_config() template to print all targets. targets = _query_for_build_config_targets(output_dir) entries = [_TargetEntry(t) for t in targets] @@ -263,6 +267,9 @@ def main(): quiet=args.quiet) if args.type: + if set(args.type) & {'android_resources', 'android_assets', 'group'}: + logging.warning('Cannot filter by this type. See TODO.') + sys.exit(1) entries = [e for e in entries if e.get_type() in args.type] if args.proguard_enabled: diff --git a/naiveproxy/src/build/android/pylib/constants/__init__.py b/naiveproxy/src/build/android/pylib/constants/__init__.py index cfde2d8526..ae2a6aacf8 100644 --- a/naiveproxy/src/build/android/pylib/constants/__init__.py +++ b/naiveproxy/src/build/android/pylib/constants/__init__.py @@ -79,11 +79,6 @@ PACKAGE_INFO.update({ chrome.PackageInfo('org.chromium.webview_ui_test', 'org.chromium.webview_ui_test.WebViewUiTestActivity', 'webview-command-line', None), - 'weblayer_browsertests': - chrome.PackageInfo( - 'org.chromium.weblayer_browsertests_apk', - 'org.chromium.weblayer_browsertests_apk.WebLayerBrowserTestsActivity', - 'chrome-native-tests-command-line', None), }) @@ -160,7 +155,6 @@ PYTHON_UNIT_TEST_SUITES = { 'java_cpp_enum_tests', 'java_cpp_strings_tests', 'java_google_api_keys_tests', - 'extract_unwind_tables_tests', ] }, } 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 c70205ddce..c90ea50f28 100644 --- a/naiveproxy/src/build/android/pylib/gtest/gtest_test_instance.py +++ b/naiveproxy/src/build/android/pylib/gtest/gtest_test_instance.py @@ -29,7 +29,6 @@ BROWSER_TEST_SUITES = [ 'android_sync_integration_tests', 'components_browsertests', 'content_browsertests', - 'weblayer_browsertests', ] # The max number of tests to run on a batch during the test run. @@ -689,8 +688,6 @@ class GtestTestInstance(test_instance.TestInstance): disabled_prefixes += ['MANUAL_'] if not self._run_disabled: disabled_prefixes += ['DISABLED_', 'FLAKY_'] - if not self._run_pre_tests: - disabled_prefixes += ['PRE_'] disabled_filter_items += ['%s*' % dp for dp in disabled_prefixes] disabled_filter_items += ['*.%s*' % dp for dp in disabled_prefixes] diff --git a/naiveproxy/src/build/android/pylib/local/device/local_device_environment.py b/naiveproxy/src/build/android/pylib/local/device/local_device_environment.py index 4b43c75c54..0083400132 100644 --- a/naiveproxy/src/build/android/pylib/local/device/local_device_environment.py +++ b/naiveproxy/src/build/android/pylib/local/device/local_device_environment.py @@ -120,7 +120,6 @@ class LocalDeviceEnvironment(environment.Environment): if hasattr(args, 'force_main_user'): self._force_main_user = args.force_main_user self._use_persistent_shell = args.use_persistent_shell - self._disable_test_server = args.disable_test_server use_local_devil_tools = False if hasattr(args, 'use_local_devil_tools'): @@ -258,10 +257,6 @@ class LocalDeviceEnvironment(environment.Environment): def trace_output(self): return self._trace_output - @property - def disable_test_server(self): - return self._disable_test_server - @property def force_main_user(self): return self._force_main_user diff --git a/naiveproxy/src/build/android/pylib/local/device/local_device_gtest_run.py b/naiveproxy/src/build/android/pylib/local/device/local_device_gtest_run.py index 1e85197813..0fcbb23d57 100644 --- a/naiveproxy/src/build/android/pylib/local/device/local_device_gtest_run.py +++ b/naiveproxy/src/build/android/pylib/local/device/local_device_gtest_run.py @@ -4,14 +4,12 @@ import contextlib -import collections import fnmatch import itertools import logging import math import os import posixpath -import subprocess import shutil import sys import time @@ -21,7 +19,6 @@ from devil.android import crash_handler from devil.android import device_errors from devil.android import device_temp_file from devil.android import logcat_monitor -from devil.android import ports from devil.android.ndk import abis from devil.android.tools import system_app from devil.android.sdk import version_codes @@ -34,7 +31,6 @@ from pylib import constants from pylib.base import base_test_result from pylib.base import test_exception from pylib.gtest import gtest_test_instance -from pylib.local import local_test_server_spawner from pylib.local.device import local_device_environment from pylib.local.device import local_device_test_run from pylib.symbols import stack_symbolizer @@ -75,15 +71,6 @@ _GTEST_PRETEST_PREFIX = 'PRE_' _SECONDS_TO_NANOS = int(1e9) -# Tests that use SpawnedTestServer must run the LocalTestServerSpawner on the -# host machine. -# TODO(jbudorick): Move this up to the test instance if the net test server is -# handled outside of the APK for the remote_device environment. -_SUITE_REQUIRES_TEST_SERVER_SPAWNER = [ - 'components_browsertests', 'content_unittests', 'content_browsertests', - 'net_unittests', 'services_unittests', 'unit_tests' -] - # No-op context manager. If we used Python 3, we could change this to # contextlib.ExitStack() class _NullContextManager: @@ -342,7 +329,7 @@ class _ApkDelegate: except device_errors.DeviceUnreachableError as e: exception_recorder.register(e) logging.exception('gtest shard device unreachable.') - except Exception: + except Exception as e: exception_recorder.register( test_exception.StartInstrumentationError(e)) device.ForceStop(self._package) @@ -491,7 +478,6 @@ class LocalDeviceGtestRun(local_device_test_run.LocalDeviceTestRun): else: self._test_perf_output_filenames = itertools.repeat(None) self._crashes = set() - self._servers = collections.defaultdict(list) #override def TestPackage(self): @@ -544,42 +530,12 @@ class LocalDeviceGtestRun(local_device_test_run.LocalDeviceTestRun): check_return=True, as_root=self._env.force_main_user) - @measures.timed_func('device_setup', 'start_servers') - def start_servers(dev): - try: - # See https://crbug.com/1030827. - # This is a hack that may break in the future. We're relying on the - # fact that adb doesn't use ipv6 for it's server, and so doesn't - # listen on ipv6, but ssh remote forwarding does. 5037 is the port - # number adb uses for its server. - if b"[::1]:5037" in subprocess.check_output( - "ss -o state listening 'sport = 5037'", shell=True): - logging.error( - 'Test Server cannot be started with a remote-forwarded adb ' - 'server. Continuing anyways, but some tests may fail.') - return - except subprocess.CalledProcessError: - pass - - self._servers[str(dev)] = [] - if self.TestPackage() in _SUITE_REQUIRES_TEST_SERVER_SPAWNER: - self._servers[str(dev)].append( - local_test_server_spawner.LocalTestServerSpawner( - ports.AllocateTestServerPort(), dev)) - - for s in self._servers[str(dev)]: - s.SetUp() - def bind_crash_handler(step, dev): return lambda: crash_handler.RetryOnSystemCrash(step, dev) steps = [install_apk] if not self._test_instance.use_existing_test_data: steps.append(push_test_data) - if self._env.disable_test_server: - logging.warning('Not starting test server. Some tests may fail.') - else: - steps.append(start_servers) steps = [bind_crash_handler(s, device) for s in steps] if self._env.concurrent_adb: @@ -766,7 +722,11 @@ class LocalDeviceGtestRun(local_device_test_run.LocalDeviceTestRun): #override def _GroupTests(self, tests): pre_tests, other_tests = _GroupPreTests(tests) - all_tests = pre_tests + other_tests + + all_tests = other_tests + if self._test_instance.run_pre_tests: + all_tests = pre_tests + other_tests + return self._SortTests(all_tests) def _UploadTestArtifacts(self, device, test_artifacts_device_dir): @@ -980,8 +940,6 @@ class LocalDeviceGtestRun(local_device_test_run.LocalDeviceTestRun): if render_test_output_dir: self._PullRenderTestOutput(device, render_test_output_dir.name) - for s in self._servers[str(device)]: - s.Reset() if self._test_instance.app_files: self._delegate.PullAppFiles(device, self._test_instance.app_files, self._test_instance.app_file_dir) @@ -1049,18 +1007,4 @@ class LocalDeviceGtestRun(local_device_test_run.LocalDeviceTestRun): #override def TearDown(self): - # By default, teardown will invoke ADB. When receiving SIGTERM due to a - # timeout, there's a high probability that ADB is non-responsive. In these - # cases, sending an ADB command will potentially take a long time to time - # out. Before this happens, the process will be hard-killed for not - # responding to SIGTERM fast enough. - if self._received_sigterm: - return - - @local_device_environment.handle_shard_failures - @trace_event.traced - def individual_device_tear_down(dev): - for s in self._servers.get(str(dev), []): - s.TearDown() - - self._env.parallel_devices.pMap(individual_device_tear_down) + pass 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 0e4f84d0c7..5529b5d8f0 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 @@ -133,7 +133,7 @@ _DEVICE_GOLD_DIR = 'skia_gold' # A map of Android product models to SDK ints. RENDER_TEST_MODEL_SDK_CONFIGS = { # Android x86 emulator. - 'Android SDK built for x86': [26, 29], + 'Android SDK built for x86': [29], # We would like this to be supported, but it is currently too prone to # introducing flakiness due to a combination of Gold and Chromium issues. # See crbug.com/1233700 and skbug.com/12149 for more information. 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 deleted file mode 100644 index 5c277b3ec3..0000000000 --- a/naiveproxy/src/build/android/pylib/local/local_test_server_spawner.py +++ /dev/null @@ -1,97 +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. - - -import json -import time - -from devil.android import forwarder -from devil.android import ports -from pylib.base import test_server -from pylib.constants import host_paths - -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 - - -def _WaitUntil(predicate, max_attempts=5): - """Blocks until the provided predicate (function) is true. - - Returns: - Whether the provided predicate was satisfied once (before the timeout). - """ - sleep_time_sec = 0.025 - for _ in range(1, max_attempts): - if predicate(): - return True - time.sleep(sleep_time_sec) - sleep_time_sec = min(1, sleep_time_sec * 2) # Don't wait more than 1 sec. - return False - - -class PortForwarderAndroid(chrome_test_server_spawner.PortForwarder): - - def __init__(self, device): - self.device = device - - def Map(self, port_pairs): - forwarder.Forwarder.Map(port_pairs, self.device) - - def GetDevicePortForHostPort(self, host_port): - return forwarder.Forwarder.DevicePortForHostPort(host_port) - - def WaitHostPortAvailable(self, port): - return _WaitUntil(lambda: ports.IsHostPortAvailable(port)) - - def WaitPortNotAvailable(self, port): - return _WaitUntil(lambda: not ports.IsHostPortAvailable(port)) - - def WaitDevicePortReady(self, port): - return _WaitUntil(lambda: ports.IsDevicePortUsed(self.device, port)) - - def Unmap(self, device_port): - forwarder.Forwarder.UnmapDevicePort(device_port, self.device) - - -class LocalTestServerSpawner(test_server.TestServer): - - def __init__(self, port, device): - super().__init__() - self._device = device - self._spawning_server = chrome_test_server_spawner.SpawningServer( - port, PortForwarderAndroid(device), MAX_TEST_SERVER_INSTANCES) - - @property - def server_address(self): - return self._spawning_server.server.server_address - - @property - def port(self): - return self.server_address[1] - - #override - def SetUp(self): - # See net/test/spawned_test_server/remote_test_server.h for description of - # the fields in the config file. - test_server_config = json.dumps({ - 'spawner_url_base': 'http://localhost:%d' % self.port - }) - self._device.WriteFile( - '%s/net-test-server-config' % self._device.GetExternalStoragePath(), - test_server_config) - forwarder.Forwarder.Map([(self.port, self.port)], self._device) - self._spawning_server.Start() - - #override - def Reset(self): - self._spawning_server.CleanupState() - - #override - def TearDown(self): - self.Reset() - self._spawning_server.Stop() - forwarder.Forwarder.UnmapDevicePort(self.port, self._device) diff --git a/naiveproxy/src/build/android/pylib/symbols/deobfuscator.py b/naiveproxy/src/build/android/pylib/symbols/deobfuscator.py index 710609854f..6544f5f98b 100644 --- a/naiveproxy/src/build/android/pylib/symbols/deobfuscator.py +++ b/naiveproxy/src/build/android/pylib/symbols/deobfuscator.py @@ -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 logging import os from pylib import constants @@ -18,8 +19,17 @@ _PASSTHROUH_ON_FAILURE = False class Deobfuscator(ExpensiveLineTransformer): def __init__(self, mapping_path): - super().__init__(_PROCESS_START_TIMEOUT, _MINIMUM_TIMEOUT, - _PER_LINE_TIMEOUT) + min_timeout = _MINIMUM_TIMEOUT + for k in os.environ: + if k.startswith('DRONE') or k.startswith('SKYLAB'): + logging.warning( + 'Likely running in a CPU-limited context due to the presence of ' + 'the %s env var. Setting min timeout for Deobfuscator to 10x.', k) + # TODO(crbug.com/421235960): Remove this if the CPU constraints are + # removed. + min_timeout = 10 * _MINIMUM_TIMEOUT + break + super().__init__(_PROCESS_START_TIMEOUT, min_timeout, _PER_LINE_TIMEOUT) script_path = os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'android', 'stacktrace', 'java_deobfuscate.py') self._command = [script_path, mapping_path] diff --git a/naiveproxy/src/build/android/pylintrc b/naiveproxy/src/build/android/pylintrc index abb27fe114..c5b3c2b566 100644 --- a/naiveproxy/src/build/android/pylintrc +++ b/naiveproxy/src/build/android/pylintrc @@ -1,6 +1,6 @@ [MESSAGES CONTROL] -disable=abstract-class-not-used,bad-continuation,bad-indentation,duplicate-code,fixme,invalid-name,line-too-long,locally-disabled,locally-enabled,missing-docstring,star-args,too-few-public-methods,too-many-arguments,too-many-branches,too-many-instance-attributes,too-many-lines,too-many-locals,too-many-public-methods,too-many-statements,wrong-import-order,wrong-import-position +disable=abstract-class-not-used,bad-continuation,bad-indentation,duplicate-code,fixme,invalid-name,line-too-long,locally-disabled,locally-enabled,missing-docstring,star-args,too-few-public-methods,too-many-arguments,too-many-branches,too-many-instance-attributes,too-many-lines,too-many-locals,too-many-public-methods,too-many-statements,wrong-import-order,wrong-import-position,too-many-return-statements [REPORTS] diff --git a/naiveproxy/src/build/android/resource_sizes.py b/naiveproxy/src/build/android/resource_sizes.py index 5d7bc6ac00..44efc7a966 100755 --- a/naiveproxy/src/build/android/resource_sizes.py +++ b/naiveproxy/src/build/android/resource_sizes.py @@ -67,7 +67,8 @@ _RC_HEADER_RE = re.compile(r'^#define (?P\w+).* (?P\d+)\)?$') _RE_NON_LANGUAGE_PAK = re.compile(r'^assets/.*(resources|percent)\.pak$') _READELF_SIZES_METRICS = { 'text': ['.text'], - 'data': ['.data', '.rodata', '.data.rel.ro', '.data.rel.ro.local'], + 'data': + ['.data', '.rodata', '.data.rel.ro', '.data.rel.ro.local', '.tdata'], 'relocations': ['.rel.dyn', '.rel.plt', '.rela.dyn', '.rela.plt', '.relr.dyn'], 'unwind': [ @@ -266,7 +267,7 @@ def _NormalizeResourcesArsc(apk_path, num_arsc_files, num_translations, size = 0 for res_id, string_val in en_strings.items(): - if string_val == fr_strings[res_id]: + if string_val == fr_strings.get(res_id): string_size = len(string_val) # 7 bytes is the per-entry overhead (not specific to any string). See # https://android.googlesource.com/platform/frameworks/base.git/+/android-4.2.2_r1/tools/aapt/StringPool.cpp#414. @@ -560,7 +561,7 @@ def _AnalyzeInternal(apk_path, continue section_sizes = _ExtractLibSectionSizesFromApk(apk_path, lib_info.filename) native_code_unaligned_size += sum(v for k, v in section_sizes.items() - if k != 'bss') + if k not in ('bss', 'tbss')) # Size of main .so vs remaining. if lib_info == main_lib_info: main_lib_size = lib_info.file_size diff --git a/naiveproxy/src/build/android/test/BUILD.gn b/naiveproxy/src/build/android/test/BUILD.gn index e9bbbce1b4..5094d1a04b 100644 --- a/naiveproxy/src/build/android/test/BUILD.gn +++ b/naiveproxy/src/build/android/test/BUILD.gn @@ -13,32 +13,35 @@ group("android_nocompile_tests") { # All test suites use targets in nocompile_gn/BUILD.gn in order to share the # same target output directory and avoid running 'gn gen' for each # android_nocompile_test_suite(). - deps = [ - ":android_lint_tests", - ":android_lookup_dep_tests", - ] + deps = [ ":android_lookup_dep_tests" ] + + if (!disable_android_lint) { + deps += [ ":android_lint_tests" ] + } } -android_nocompile_test_suite("android_lint_tests") { - # Depend on lint script so that the action is re-run whenever the script is modified. - pydeps = [ "//build/android/gyp/lint.pydeps" ] +if (!disable_android_lint) { + android_nocompile_test_suite("android_lint_tests") { + # Depend on lint script so that the action is re-run whenever the script is modified. + pydeps = [ "//build/android/gyp/lint.pydeps" ] - tests = [ - { - target = "nocompile_gn:default_locale_lint_test" - nocompile_sources = - rebase_path(default_locale_lint_test_nocompile_sources, - "", - "nocompile_gn") - expected_compile_output_regex = "Warning:.*DefaultLocale" - }, - { - target = "nocompile_gn:new_api_lint_test" - nocompile_sources = - rebase_path(new_api_lint_test_nocompile_sources, "", "nocompile_gn") - expected_compile_output_regex = "Error:.*NewApi" - }, - ] + tests = [ + { + target = "nocompile_gn:default_locale_lint_test" + nocompile_sources = + rebase_path(default_locale_lint_test_nocompile_sources, + "", + "nocompile_gn") + expected_compile_output_regex = "Warning:.*DefaultLocale" + }, + { + target = "nocompile_gn:new_api_lint_test" + nocompile_sources = + rebase_path(new_api_lint_test_nocompile_sources, "", "nocompile_gn") + expected_compile_output_regex = "Error:.*NewApi" + }, + ] + } } android_nocompile_test_suite("android_lookup_dep_tests") { diff --git a/naiveproxy/src/build/android/test/nocompile_gn/BUILD.gn b/naiveproxy/src/build/android/test/nocompile_gn/BUILD.gn index 406bd8c485..4ee30b7834 100644 --- a/naiveproxy/src/build/android/test/nocompile_gn/BUILD.gn +++ b/naiveproxy/src/build/android/test/nocompile_gn/BUILD.gn @@ -7,46 +7,38 @@ import("//build/config/android/android_nocompile.gni") import("//build/config/android/rules.gni") import("nocompile_sources.gni") -template("lint_test") { - _library_target_name = "${target_name}_test_java" - _apk_target_name = "${target_name}_apk" +if (!disable_android_lint) { + # LINT tests only make sense if the args.gn keeps LINT enabled. + template("lint_test") { + _library_target_name = "${target_name}_test_java" - android_library(_library_target_name) { - sources = [ "//tools/android/errorprone_plugin/test/src/org/chromium/tools/errorprone/plugin/Empty.java" ] - not_needed(invoker, [ "sources" ]) - if (enable_android_nocompile_tests) { - sources += invoker.sources + android_library(_library_target_name) { + sources = [ "//tools/android/errorprone_plugin/test/src/org/chromium/tools/errorprone/plugin/Empty.java" ] + not_needed(invoker, [ "sources" ]) + if (enable_android_nocompile_tests) { + sources += invoker.sources + } + } + + android_apk(target_name) { + # This cannot be marked testonly since lint has special ignores for testonly + # targets. We need to test linting a normal apk target. + apk_name = target_name + deps = [ ":$_library_target_name" ] + android_manifest = "//build/android/AndroidManifest.xml" + enable_lint = true } } - android_apk(_apk_target_name) { - # This cannot be marked testonly since lint has special ignores for testonly - # targets. We need to test linting a normal apk target. - apk_name = _apk_target_name - deps = [ ":$_library_target_name" ] - android_manifest = "//build/android/AndroidManifest.xml" + lint_test("default_locale_lint_test") { + sources = default_locale_lint_test_nocompile_sources } - android_lint(target_name) { - _apk_target = ":${_apk_target_name}" - deps = [ "${_apk_target}__java" ] - build_config_dep = "$_apk_target$build_config_target_suffix" - build_config = get_label_info(_apk_target, "target_gen_dir") + "/" + - get_label_info(_apk_target, "name") + ".build_config.json" - if (enable_android_nocompile_tests) { - skip_build_server = true - } + lint_test("new_api_lint_test") { + sources = new_api_lint_test_nocompile_sources } } -lint_test("default_locale_lint_test") { - sources = default_locale_lint_test_nocompile_sources -} - -lint_test("new_api_lint_test") { - sources = new_api_lint_test_nocompile_sources -} - missing_symbol_generated_importer_test( "import_parent_missing_symbol_test_java") { importer_package = "test.missing_symbol.child_missing" diff --git a/naiveproxy/src/build/android/test_runner.py b/naiveproxy/src/build/android/test_runner.py index b435ef2d82..7791a5ee23 100755 --- a/naiveproxy/src/build/android/test_runner.py +++ b/naiveproxy/src/build/android/test_runner.py @@ -254,12 +254,6 @@ def AddCommonOptions(parser): action='store_true', help='Uses a persistent shell connection for the adb connection.') - parser.add_argument('--disable-test-server', - action='store_true', - help='Disables SpawnedTestServer which doesn' - 't work with remote adb. ' - 'WARNING: Will break tests which require the server.') - # This is currently only implemented for gtests and instrumentation tests. parser.add_argument( '--gtest_also_run_disabled_tests', '--gtest-also-run-disabled-tests', @@ -488,14 +482,12 @@ def AddGTestOptions(parser): help='Do not push new files to the device, instead using existing APK ' 'and test data. Only use when running the same test for multiple ' 'iterations.') - # This is currently only implemented for gtests tests. - # TODO(crbug.com/40200835): Remove this flag when PRE tests run properly. - parser.add_argument('--gtest_also_run_pre_tests', - '--gtest-also-run-pre-tests', + parser.add_argument('--gtest_skip_pre_tests', + '--gtest-skip-pre-tests', dest='run_pre_tests', - action='store_true', + action='store_false', default=True, - help='Also run PRE_ tests if applicable.') + help='Do not run PRE_ tests if applicable.') def AddInstrumentationTestOptions(parser): diff --git a/naiveproxy/src/build/android/test_runner.pydeps b/naiveproxy/src/build/android/test_runner.pydeps index 7452c6bddd..852361077a 100644 --- a/naiveproxy/src/build/android/test_runner.pydeps +++ b/naiveproxy/src/build/android/test_runner.pydeps @@ -53,7 +53,6 @@ ../../third_party/catapult/devil/devil/android/logcat_monitor.py ../../third_party/catapult/devil/devil/android/ndk/__init__.py ../../third_party/catapult/devil/devil/android/ndk/abis.py -../../third_party/catapult/devil/devil/android/ports.py ../../third_party/catapult/devil/devil/android/sdk/__init__.py ../../third_party/catapult/devil/devil/android/sdk/aapt.py ../../third_party/catapult/devil/devil/android/sdk/adb_wrapper.py @@ -133,7 +132,6 @@ ../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/decorators.py ../util/lib/common/google_storage_helper.py ../util/lib/common/unittest_util.py @@ -172,7 +170,6 @@ pylib/base/test_instance.py pylib/base/test_instance_factory.py pylib/base/test_run.py pylib/base/test_run_factory.py -pylib/base/test_server.py pylib/constants/__init__.py pylib/constants/host_paths.py pylib/gtest/__init__.py @@ -199,7 +196,6 @@ pylib/local/emulator/ini.py pylib/local/emulator/local_emulator_environment.py pylib/local/emulator/proto/__init__.py pylib/local/emulator/proto/avd_pb2.py -pylib/local/local_test_server_spawner.py pylib/local/machine/__init__.py pylib/local/machine/local_machine_environment.py pylib/local/machine/local_machine_hostside_test_run.py diff --git a/naiveproxy/src/build/build_config.h b/naiveproxy/src/build/build_config.h index e31bc768f5..9b404797ab 100644 --- a/naiveproxy/src/build/build_config.h +++ b/naiveproxy/src/build/build_config.h @@ -16,13 +16,13 @@ // // Operating System: // IS_AIX / IS_ANDROID / IS_ASMJS / IS_CHROMEOS / IS_FREEBSD / IS_FUCHSIA / -// IS_IOS / IS_IOS_MACCATALYST / IS_IOS_TVOS / IS_LINUX / IS_MAC / IS_NACL / +// IS_IOS / IS_IOS_MACCATALYST / IS_IOS_TVOS / IS_LINUX / IS_MAC / // IS_NETBSD / IS_OPENBSD / IS_QNX / IS_SOLARIS / IS_WATCHOS / IS_WIN // Operating System family: // IS_APPLE: IOS or MAC or IOS_MACCATALYST or IOS_TVOS or WATCHOS // IS_BSD: FREEBSD or NETBSD or OPENBSD // IS_POSIX: AIX or ANDROID or ASMJS or CHROMEOS or FREEBSD or IOS or LINUX -// or MAC or NACL or NETBSD or OPENBSD or QNX or SOLARIS +// or MAC or NETBSD or OPENBSD or QNX or SOLARIS // This file also adds defines specific to the platform, architecture etc. // @@ -49,6 +49,10 @@ // ARCH_CPU_31_BITS / ARCH_CPU_32_BITS / ARCH_CPU_64_BITS // ARCH_CPU_BIG_ENDIAN / ARCH_CPU_LITTLE_ENDIAN +// Mapping to some Rust conditionals: +// +// * `#[cfg(unix)]` ~= `BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)` + #ifndef BUILD_BUILD_CONFIG_H_ #define BUILD_BUILD_CONFIG_H_ @@ -60,10 +64,7 @@ // IWYU pragma: always_keep // A set of macros to use for platform detection. -#if defined(__native_client__) -// __native_client__ must be first, so that other OS_ defines are not set. -#define OS_NACL 1 -#elif defined(ANDROID) +#if defined(ANDROID) #define OS_ANDROID 1 #elif defined(__APPLE__) // Only include TargetConditionals after testing ANDROID as some Android builds @@ -136,11 +137,11 @@ // For access to standard POSIXish features, use OS_POSIX instead of a // more specific macro. -#if defined(OS_AIX) || defined(OS_ANDROID) || defined(OS_ASMJS) || \ - defined(OS_FREEBSD) || defined(OS_IOS) || defined(OS_LINUX) || \ - defined(OS_CHROMEOS) || defined(OS_MAC) || defined(OS_NACL) || \ - defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_QNX) || \ - defined(OS_SOLARIS) || defined(OS_ZOS) +#if defined(OS_AIX) || defined(OS_ANDROID) || defined(OS_ASMJS) || \ + defined(OS_FREEBSD) || defined(OS_IOS) || defined(OS_LINUX) || \ + defined(OS_CHROMEOS) || defined(OS_MAC) || defined(OS_NETBSD) || \ + defined(OS_OPENBSD) || defined(OS_QNX) || defined(OS_SOLARIS) || \ + defined(OS_ZOS) #define OS_POSIX 1 #endif @@ -223,12 +224,6 @@ #define BUILDFLAG_INTERNAL_IS_MAC() (0) #endif -#if defined(OS_NACL) -#define BUILDFLAG_INTERNAL_IS_NACL() (1) -#else -#define BUILDFLAG_INTERNAL_IS_NACL() (0) -#endif - #if defined(OS_NETBSD) #define BUILDFLAG_INTERNAL_IS_NETBSD() (1) #else @@ -331,7 +326,7 @@ #define ARCH_CPU_ARM64 1 #define ARCH_CPU_64_BITS 1 #define ARCH_CPU_LITTLE_ENDIAN 1 -#elif defined(__pnacl__) || defined(__asmjs__) || defined(__wasm__) +#elif defined(__asmjs__) || defined(__wasm__) #define ARCH_CPU_32_BITS 1 #define ARCH_CPU_LITTLE_ENDIAN 1 #elif defined(__MIPSEL__) diff --git a/naiveproxy/src/build/check_gn_headers_allowlist.txt b/naiveproxy/src/build/check_gn_headers_allowlist.txt index d99cab8345..8943891aaa 100644 --- a/naiveproxy/src/build/check_gn_headers_allowlist.txt +++ b/naiveproxy/src/build/check_gn_headers_allowlist.txt @@ -137,12 +137,6 @@ ppapi/lib/gl/include/GLES2/gl2.h ppapi/lib/gl/include/GLES2/gl2ext.h ppapi/lib/gl/include/GLES2/gl2platform.h ppapi/lib/gl/include/KHR/khrplatform.h -ppapi/nacl_irt/irt_manifest.h -ppapi/nacl_irt/public/irt_ppapi.h -ppapi/native_client/src/shared/ppapi_proxy/ppruntime.h -ppapi/native_client/src/untrusted/pnacl_irt_shim/irt_shim_ppapi.h -ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.h -ppapi/native_client/src/untrusted/pnacl_irt_shim/shim_ppapi.h ppapi/proxy/dispatch_reply_message.h ppapi/proxy/plugin_proxy_delegate.h ppapi/proxy/plugin_resource_callback.h @@ -206,7 +200,6 @@ third_party/woff2/src/port.h third_party/yasm/source/config/linux/config.h third_party/yasm/source/config/linux/libyasm-stdint.h third_party/zlib/contrib/minizip/crypt.h -tools/ipc_fuzzer/message_lib/all_message_null_macros.h ui/base/clipboard/clipboard_test_template.h ui/events/keycodes/keyboard_codes_posix.h ui/gfx/overlay_transform.h diff --git a/naiveproxy/src/build/chromeos/test_runner.py b/naiveproxy/src/build/chromeos/test_runner.py index dd27ab2d2a..500e9f9199 100755 --- a/naiveproxy/src/build/chromeos/test_runner.py +++ b/naiveproxy/src/build/chromeos/test_runner.py @@ -840,8 +840,6 @@ def setup_env(): # of args. # TODO(crbug.com/40567963): Make the GN-dependent deps controllable via cmd # line args. - if not env.get('GN_ARGS'): - env['GN_ARGS'] = 'enable_nacl = true' if not env.get('USE'): env['USE'] = 'highdpi' return env diff --git a/naiveproxy/src/build/config/BUILD.gn b/naiveproxy/src/build/config/BUILD.gn index 009d68745f..56ca3ca739 100644 --- a/naiveproxy/src/build/config/BUILD.gn +++ b/naiveproxy/src/build/config/BUILD.gn @@ -113,10 +113,6 @@ config("debug") { "DYNAMIC_ANNOTATIONS_ENABLED=1", ] - if (is_nacl) { - defines += [ "DYNAMIC_ANNOTATIONS_PREFIX=NACL_" ] - } - if (is_win) { if (!enable_iterator_debugging && !use_custom_libcxx) { # Iterator debugging is enabled by default by the compiler on debug @@ -139,12 +135,10 @@ config("release") { if (is_tsan) { defines += [ "DYNAMIC_ANNOTATIONS_ENABLED=1" ] } else { - defines += [ "NVALGRIND" ] - if (!is_nacl) { - # NaCl always enables dynamic annotations. Currently this value is set to - # 1 for all .nexes. - defines += [ "DYNAMIC_ANNOTATIONS_ENABLED=0" ] - } + defines += [ + "NVALGRIND", + "DYNAMIC_ANNOTATIONS_ENABLED=0", + ] } if (is_ios) { diff --git a/naiveproxy/src/build/config/BUILDCONFIG.gn b/naiveproxy/src/build/config/BUILDCONFIG.gn index 844cac5eb0..934e15c267 100644 --- a/naiveproxy/src/build/config/BUILDCONFIG.gn +++ b/naiveproxy/src/build/config/BUILDCONFIG.gn @@ -28,7 +28,7 @@ # represents the computer doing the compile and never changes. The "target" # represents the main thing we're trying to build. The "current" represents # which configuration is currently being defined, which can be either the -# host, the target, or something completely different (like nacl). GN will +# host, the target, or something completely different. GN will # run the same build file multiple times for the different required # configuration in the same build. # @@ -160,7 +160,7 @@ declare_args() { # For details on the current state of modules in Chromium see # https://chromium.googlesource.com/chromium/src/+/main/docs/modules.md # We explicitly need this flag in this file because it's read by this file. - use_libcxx_modules = false + use_clang_modules = false # DON'T ADD MORE FLAGS HERE. Read the comment above. } @@ -329,7 +329,12 @@ is_fuchsia = current_os == "fuchsia" is_ios = current_os == "ios" is_linux = current_os == "linux" || current_os == "openwrt" is_mac = current_os == "mac" -is_nacl = current_os == "nacl" + +# TODO(crbug.com/40511454): Remove is_nacl from all build files, then +# remove the is_nacl variable. +assert(current_os != "nacl") +is_nacl = false + is_wasm = current_os == "emscripten" is_watchos = current_os == "watchos" is_win = current_os == "win" || current_os == "winuwp" @@ -356,7 +361,7 @@ is_posix = !is_win && !is_fuchsia # Holds all configs used for running the compiler. default_compiler_configs = [ - "//build/config:feature_flags", + "//build/config/compiler/pgo:default_pgo_flags", "//build/config/compiler:afdo", "//build/config/compiler:afdo_optimize_size", "//build/config/compiler:cet_shadow_stack", @@ -379,9 +384,9 @@ default_compiler_configs = [ "//build/config/compiler:thin_archive", "//build/config/compiler:thinlto_optimize_max", "//build/config/compiler:tot_warnings", - "//build/config/compiler/pgo:default_pgo_flags", "//build/config/coverage:default_coverage", "//build/config/sanitizers:default_sanitizer_flags", + "//build/config:feature_flags", ] if (is_win) { @@ -458,7 +463,10 @@ if (is_win) { } else if (is_android) { # Warn whenever linking code that could unintentionally switch off # branch target identification (BTI) on Arm systems. - _linker_configs = [ "//build/config/android:lld_branch_target_hardening" ] + _linker_configs = [ + "//build/config/android:lld_branch_target_hardening", + "//build/config/android:default_relr_relocations", + ] } else { _linker_configs = [] } @@ -541,19 +549,6 @@ set_defaults("rust_proc_macro") { configs = default_rust_proc_macro_configs } -DEFAULT_MODULE_DEPS = [ - "//buildtools/third_party/libc++:_Builtin_intrinsics", - "//buildtools/third_party/libc++:_Builtin_limits", - "//buildtools/third_party/libc++:_Builtin_stdarg", - "//buildtools/third_party/libc++:_Builtin_stdbool", - "//buildtools/third_party/libc++:_Builtin_stdint", - "//buildtools/third_party/libc++:_Builtin_unwind", - "//buildtools/third_party/libc++:std", - "//buildtools/third_party/libc++:std_stdatomic_h", - "//buildtools/third_party/libc++:sysroot_features", - "//buildtools/third_party/libc++:sysroot_types", -] - # A helper for forwarding testonly and visibility. # Forwarding "*" does not include variables from outer scopes (to avoid copying # all globals into each template invocation), so it will not pick up @@ -580,7 +575,7 @@ foreach(_target_type, target(_target_type, target_name) { forward_variables_from(invoker, "*", - TESTONLY_AND_VISIBILITY + [ "use_libcxx_modules" ]) + TESTONLY_AND_VISIBILITY + [ "use_clang_modules" ]) forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) if (!defined(inputs)) { inputs = [] @@ -589,24 +584,44 @@ foreach(_target_type, deps = [] } - _use_libcxx_modules = use_libcxx_modules - if (defined(invoker.use_libcxx_modules)) { - _use_libcxx_modules = invoker.use_libcxx_modules + if (!defined(public_deps)) { + public_deps = [] } - if (filter_include(configs, - [ - "//build/config/compiler:exceptions", - "//build/config/compiler:rtti", - ]) != []) { - # Exceptions and RTTI flags are incompatible with libc++ modules build. - # So disable modules build for such targets. - _use_libcxx_modules = false + if (use_clang_modules) { + # When Clang modules are used, libc++ headers must be copied (to the gen + # directory) regardless of whether the libc++ module is used in this + # target. + public_deps += [ + "//buildtools/third_party/libc++:copy_custom_headers", + "//buildtools/third_party/libc++:copy_libcxx_headers", + ] } - if (is_clang && _use_libcxx_modules) { + if (!defined(use_libcxx_modules)) { + use_libcxx_modules = use_clang_modules + } + + if (filter_include( + configs, + [ + # TODO(https://github.com/llvm/llvm-project/pull/145654): + # Remove mac_no_default_new_delete_symbols after clang roll. + ":mac_no_default_new_delete_symbols", + "//build/config/compiler:exceptions", + "//build/config/compiler:rtti", + ]) != [] || + filter_include(configs, + [ "//build/config/compiler:no_exceptions" ]) == []) { + # Exceptions (i.e. if the 'no_exceptions' config is not used) and RTTI + # flags are incompatible with libc++ modules build. So disable modules + # build for such targets. + use_libcxx_modules = false + } + + if (use_libcxx_modules) { # This is necessary for Clang modules builds. - deps += DEFAULT_MODULE_DEPS + deps += [ "//buildtools/third_party/libc++:all_modules" ] if (!defined(defines)) { defines = [] } @@ -617,10 +632,6 @@ foreach(_target_type, configs -= [ "//build/config/compiler:libcxx_module" ] } - # _use_libcxx_modules is considered unused, if is_clang = false in the - # above conditional. - not_needed([ "_use_libcxx_modules" ]) - # Consumed by the unsafe-buffers plugin during compile. # # TODO(crbug.com/326584510): Reclient doesn't respect this variable, see @@ -666,7 +677,7 @@ foreach(_target_type, "*", TESTONLY_AND_VISIBILITY + [ "no_default_deps", - "use_libcxx_modules", + "use_clang_modules", ]) forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) if (!defined(inputs)) { @@ -705,24 +716,44 @@ foreach(_target_type, deps += [ "//build/config:${_target_type}_deps" ] } - _use_libcxx_modules = use_libcxx_modules - if (defined(invoker.use_libcxx_modules)) { - _use_libcxx_modules = invoker.use_libcxx_modules + if (!defined(public_deps)) { + public_deps = [] } - if (filter_include(configs, - [ - "//build/config/compiler:exceptions", - "//build/config/compiler:rtti", - ]) != []) { - # Exceptions and RTTI flags are incompatible with libc++ modules build. - # So disable modules build for such targets. - _use_libcxx_modules = false + if (use_clang_modules) { + # When Clang modules are used, libc++ headers must be copied (to the gen + # directory) regardless of whether the libc++ module is used in this + # target. + public_deps += [ + "//buildtools/third_party/libc++:copy_custom_headers", + "//buildtools/third_party/libc++:copy_libcxx_headers", + ] } - if (is_clang && _use_libcxx_modules) { + if (!defined(use_libcxx_modules)) { + use_libcxx_modules = use_clang_modules + } + + if (filter_include( + configs, + [ + # TODO(https://github.com/llvm/llvm-project/pull/145654): + # Remove mac_no_default_new_delete_symbols after clang roll. + ":mac_no_default_new_delete_symbols", + "//build/config/compiler:exceptions", + "//build/config/compiler:rtti", + ]) != [] || + filter_include(configs, + [ "//build/config/compiler:no_exceptions" ]) == []) { + # Exceptions (i.e. if the 'no_exceptions' config is not used) and RTTI + # flags are incompatible with libc++ modules build. So disable modules + # build for such targets. + use_libcxx_modules = false + } + + if (use_libcxx_modules) { # These are necessary for Clang modules builds. - deps += DEFAULT_MODULE_DEPS + deps += [ "//buildtools/third_party/libc++:all_modules" ] if (!defined(defines)) { defines = [] } @@ -733,10 +764,6 @@ foreach(_target_type, configs -= [ "//build/config/compiler:libcxx_module" ] } - # _use_libcxx_modules is considered unused, if is_clang = false in the - # above conditional. - not_needed([ "_use_libcxx_modules" ]) - # On Android, write shared library output file to metadata. We will use # this information to, for instance, collect all shared libraries that # should be packaged into an APK. diff --git a/naiveproxy/src/build/config/android/BUILD.gn b/naiveproxy/src/build/config/android/BUILD.gn index 183ac8569f..db40252627 100644 --- a/naiveproxy/src/build/config/android/BUILD.gn +++ b/naiveproxy/src/build/config/android/BUILD.gn @@ -100,16 +100,18 @@ config("hide_all_but_jni") { [ "-Wl,--version-script=" + rebase_path(_version_script, root_build_dir) ] } -config("lld_pack_relocations") { - ldflags = [ "-Wl,--pack-dyn-relocs=android" ] -} - -config("lld_relr_relocations") { +config("relr_relocations") { # RELR supported API 30+, but supported 28+ with --use-android-relr-tags. # https://android.googlesource.com/platform/bionic/+/master/android-changes-for-ndk-developers.md#relative-relocations-relr ldflags = [ "-Wl,--pack-dyn-relocs=relr,--use-android-relr-tags" ] } +config("default_relr_relocations") { + if (default_min_sdk_version >= 28) { + configs = [ ":relr_relocations" ] + } +} + config("lld_branch_target_hardening") { # Config opts a shared library into BTI linker hardening. This # is an opt-in config (rather than default-enabled) to avoid diff --git a/naiveproxy/src/build/config/android/config.gni b/naiveproxy/src/build/config/android/config.gni index e11e7d5434..8a1e384ac5 100644 --- a/naiveproxy/src/build/config/android/config.gni +++ b/naiveproxy/src/build/config/android/config.gni @@ -26,6 +26,9 @@ 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") +assert(!(enable_javaless_renderers && is_component_build), + "Javaless renderers do not support component build, see " + + "go/javaless-renderers-component-build.") # Toolchain used to create native libraries for robolectric_binary() targets. robolectric_toolchain = "//build/toolchain/android:robolectric_$host_cpu" @@ -316,7 +319,7 @@ if (is_android) { # value of the arguments set above. declare_args() { # Default value for targetSdkVersion for APK and bundle targets. - default_target_sdk_version = "35" + default_target_sdk_version = "36" # Whether java assertions and Preconditions checks are enabled. enable_java_asserts = dcheck_always_on || !is_official_build diff --git a/naiveproxy/src/build/config/android/extract_unwind_tables.gni b/naiveproxy/src/build/config/android/extract_unwind_tables.gni deleted file mode 100644 index 6518a2d3a0..0000000000 --- a/naiveproxy/src/build/config/android/extract_unwind_tables.gni +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright 2018 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/android/rules.gni") - -unwind_table_asset_v1_filename = "unwind_cfi_32" - -_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") { - action(target_name) { - forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) - _output_path = - "$target_out_dir/$target_name/$unwind_table_asset_v1_filename" - - # Strip the "lib" prefix, if present. Add and then remove a space because - # our ownly tool is "replace all". - _library_name = get_label_info(invoker.library_target, "name") - _library_name = - string_replace(string_replace(" $_library_name", " $shlib_prefix", ""), - " ", - "") - _library_path = "$root_out_dir/lib.unstripped/$shlib_prefix$_library_name$shlib_extension" - - script = "//build/android/gyp/extract_unwind_tables.py" - outputs = [ _output_path ] - inputs = [ - _dump_syms, - _library_path, - ] - deps = [ - _dump_syms_target, - invoker.library_target, - ] - - args = [ - "--input_path", - rebase_path(_library_path, root_build_dir), - "--output_path", - rebase_path(_output_path, root_build_dir), - "--dump_syms_path", - rebase_path(_dump_syms, root_build_dir), - ] - } -} diff --git a/naiveproxy/src/build/config/android/internal_rules.gni b/naiveproxy/src/build/config/android/internal_rules.gni index 2d1d775a4c..82668c13e6 100644 --- a/naiveproxy/src/build/config/android/internal_rules.gni +++ b/naiveproxy/src/build/config/android/internal_rules.gni @@ -126,11 +126,11 @@ template("write_build_config") { _params_file = string_replace(invoker.build_config, ".build_config.json", ".params.json") _inputs = [ _params_file ] + _outputs = [ invoker.build_config ] _deps = [] + _type = invoker.type if (current_toolchain == default_toolchain) { - _type = invoker.type - # Ensure targets match naming patterns so that __assetres, __header, __host, # and __validate targets work properly. if (filter_exclude([ _type ], _java_resource_types) == []) { @@ -157,6 +157,8 @@ template("write_build_config") { if (current_toolchain != default_toolchain) { not_needed(invoker, "*") _params = { + type = "" + # This has to be a build-time error rather than a GN assert because many # packages have a mix of java and non-java targets. For example, the # following would fail even though nothing depends on :bar(//baz): @@ -176,21 +178,34 @@ template("write_build_config") { ] } } else { + _deps_configs = [] + if (defined(invoker.config_deps)) { + foreach(_dep, invoker.config_deps) { + _dep_label = get_label_info(_dep, "label_no_toolchain") + _dep_gen_dir = get_label_info(_dep, "target_gen_dir") + _dep_name = get_label_info(_dep, "name") + _dep_config = "$_dep_gen_dir/$_dep_name.params.json" + _deps_configs += [ _dep_config ] + } + } if (defined(invoker.possible_config_deps)) { - _deps_configs = [] + _is_bundle = _type == "android_app_bundle" + not_needed([ "_is_bundle" ]) foreach(_possible_dep, invoker.possible_config_deps) { _dep_label = get_label_info(_possible_dep, "label_no_toolchain") if (filter_exclude([ _dep_label ], java_target_patterns) == []) { - _deps += [ "$_dep_label$build_config_target_suffix" ] _dep_gen_dir = get_label_info(_possible_dep, "target_gen_dir") _dep_name = get_label_info(_possible_dep, "name") - _dep_config = "$_dep_gen_dir/$_dep_name.build_config.json" - + _dep_config = "$_dep_gen_dir/$_dep_name.params.json" _deps_configs += [ _dep_config ] + if (_is_bundle) { + _inputs += [ "$_dep_gen_dir/$_dep_name.build_config.json" ] + _deps += [ "$_dep_label$build_config_target_suffix" ] + } } } - _inputs += _deps_configs } + _inputs += _deps_configs if (defined(invoker.possible_config_public_deps)) { _public_deps_configs = [] foreach(_possible_dep, invoker.possible_config_public_deps) { @@ -207,11 +222,9 @@ template("write_build_config") { # Put the bug number in the target name so that false-positives # have a hint in the error message about non-existent dependencies. - _deps += [ "$_dep_label$build_config_target_suffix" ] _dep_gen_dir = get_label_info(_possible_dep, "target_gen_dir") _dep_name = get_label_info(_possible_dep, "name") - _dep_config = "$_dep_gen_dir/$_dep_name.build_config.json" - + _dep_config = "$_dep_gen_dir/$_dep_name.params.json" _public_deps_configs += [ _dep_config ] } _inputs += _public_deps_configs @@ -220,10 +233,9 @@ template("write_build_config") { invoker.annotation_processor_deps != []) { _processor_configs = [] foreach(_dep_label, invoker.annotation_processor_deps) { - _deps += [ "$_dep_label$build_config_target_suffix" ] _dep_gen_dir = get_label_info(_dep_label, "target_gen_dir") _dep_name = get_label_info(_dep_label, "name") - _dep_config = "$_dep_gen_dir/$_dep_name.build_config.json" + _dep_config = "$_dep_gen_dir/$_dep_name.params.json" _processor_configs += [ _dep_config ] } _inputs += _processor_configs @@ -232,28 +244,32 @@ template("write_build_config") { _dep_label = invoker.apk_under_test _dep_gen_dir = get_label_info(_dep_label, "target_gen_dir") _dep_name = get_label_info(_dep_label, "name") - _apk_under_test_config = "$_dep_gen_dir/$_dep_name.build_config.json" - _inputs += [ _apk_under_test_config ] - _deps += [ "$_dep_label$build_config_target_suffix" ] - } - if (defined(invoker.base_module_target)) { - _dep_label = invoker.base_module_target - _dep_gen_dir = get_label_info(_dep_label, "target_gen_dir") - _dep_name = get_label_info(_dep_label, "name") - _base_module_config = "$_dep_gen_dir/$_dep_name.build_config.json" - _inputs += [ _base_module_config ] + _apk_under_test_config = "$_dep_gen_dir/$_dep_name.params.json" + _inputs += [ + _apk_under_test_config, + "$_dep_gen_dir/$_dep_name.build_config.json", + ] + + # .build_config.json needed only for AndroidManifest.xml. _deps += [ "$_dep_label$build_config_target_suffix" ] } if (defined(invoker.parent_module_target)) { _dep_label = invoker.parent_module_target _dep_gen_dir = get_label_info(_dep_label, "target_gen_dir") _dep_name = get_label_info(_dep_label, "name") - _parent_module_config = "$_dep_gen_dir/$_dep_name.build_config.json" + _parent_module_config = "$_dep_gen_dir/$_dep_name.params.json" _inputs += [ _parent_module_config ] - _deps += [ "$_dep_label$build_config_target_suffix" ] + _deps_configs += [ _parent_module_config ] } - if (defined(invoker.module_build_configs)) { - _inputs += invoker.module_build_configs + if (defined(invoker.base_module_target)) { + _dep_label = invoker.base_module_target + _dep_gen_dir = get_label_info(_dep_label, "target_gen_dir") + _dep_name = get_label_info(_dep_label, "name") + _base_module_config = "$_dep_gen_dir/$_dep_name.params.json" + _inputs += [ _base_module_config ] + if (!defined(invoker.parent_module_target)) { + _deps_configs += [ _base_module_config ] + } } if (defined(invoker.android_manifest)) { _inputs += [ invoker.android_manifest ] @@ -297,12 +313,21 @@ template("write_build_config") { _rebased_asset_sources = rebase_path(_assets.sources, root_build_dir) } + if (defined(invoker.enable_lint) && invoker.enable_lint) { + _lint_json = string_replace(invoker.build_config, ".json", ".lint.json") + _outputs += [ _lint_json ] + } + _params = { type = _type gn_target = _target_label - if (defined(_deps_configs)) { - deps_configs = rebase_path(_deps_configs, root_build_dir) + if (_deps_configs != []) { + if (_type == "group" || _type == "android_resources") { + public_deps_configs = rebase_path(_deps_configs, root_build_dir) + } else { + deps_configs = rebase_path(_deps_configs, root_build_dir) + } } if (defined(_public_deps_configs)) { public_deps_configs = rebase_path(_public_deps_configs, root_build_dir) @@ -321,10 +346,6 @@ template("write_build_config") { parent_module_config = rebase_path(_parent_module_config, root_build_dir) } - if (defined(invoker.module_build_configs)) { - module_configs = - rebase_path(invoker.module_build_configs, root_build_dir) - } if (defined(_suffix_apk_assets_used_by_config)) { suffix_apk_assets_used_by_config = rebase_path(_suffix_apk_assets_used_by_config, root_build_dir) @@ -335,6 +356,8 @@ template("write_build_config") { "assets", "bypass_platform_checks", "chromium_code", + "create_locales_java_list", + "dex_needs_classpath", "direct_deps_only", "disable_asset_compression", "gradle_treat_as_prebuilt", @@ -349,10 +372,10 @@ template("write_build_config") { "recursive_resource_deps", "requires_android", "requires_robolectric", - "resource_overlay", "secondary_native_lib_placeholders", "supports_android", "use_interface_jars", + "uses_split", "version_code", "version_name", ]) @@ -412,7 +435,12 @@ template("write_build_config") { android_manifest = rebase_path(invoker.android_manifest, root_build_dir) } if (defined(invoker.resources_zip)) { - resources_zip = rebase_path(invoker.resources_zip, root_build_dir) + if (defined(invoker.resource_overlay) && invoker.resource_overlay) { + resources_overlay_zip = + rebase_path(invoker.resources_zip, root_build_dir) + } else { + resources_zip = rebase_path(invoker.resources_zip, root_build_dir) + } } if (defined(invoker.rtxt_path)) { rtxt_path = rebase_path(invoker.rtxt_path, root_build_dir) @@ -500,46 +528,46 @@ template("write_build_config") { rebase_path("$target_out_dir/$_trace_events_target_name", root_build_dir) } - if (defined(invoker.modules)) { - modules = [] - foreach(_module, invoker.modules) { - modules += [ - { - name = _module.name - build_config = rebase_path(_module.build_config, root_build_dir) - if (defined(_module.uses_split)) { - uses_split = _module.uses_split - } - }, - ] - } + if (defined(_lint_json)) { + lint_json = rebase_path(_lint_json, root_build_dir) } } } write_file(_params_file, _params, "json") - action_with_pydeps(target_name) { - forward_variables_from(invoker, [ "testonly" ]) - script = "//build/android/gyp/write_build_config.py" - depfile = "$target_gen_dir/$target_name.d" - inputs = _inputs - outputs = [ invoker.build_config ] + # These build steps require no computed values. + if (_type == "android_assets" || _type == "android_resources" || + _type == "group") { + not_needed([ + "_deps", + "_inputs", + "_outputs", + "target_name", + ]) + } else { + action_with_pydeps(target_name) { + forward_variables_from(invoker, [ "testonly" ]) + script = "//build/android/gyp/write_build_config.py" + depfile = "$target_gen_dir/$target_name.d" + inputs = _inputs + outputs = _outputs - args = [ - "--depfile", - rebase_path(depfile, root_build_dir), - "--params", - rebase_path(_params_file, root_build_dir), - ] + args = [ + "--output", + rebase_path(invoker.build_config, root_build_dir), + "--depfile", + rebase_path(depfile, root_build_dir), + ] - deps = [] - if (defined(invoker.deps)) { - deps += invoker.deps + deps = [] + if (defined(invoker.deps)) { + deps += invoker.deps + } + if (defined(invoker.android_manifest_dep)) { + deps += [ invoker.android_manifest_dep ] + } + deps += _deps } - if (defined(invoker.android_manifest_dep)) { - deps += [ invoker.android_manifest_dep ] - } - deps += _deps } } @@ -1030,10 +1058,7 @@ if (enable_java_templates) { ] } - if (defined(invoker.skip_build_server) && invoker.skip_build_server) { - # Nocompile tests need lint to fail through ninja. - args += [ "--skip-build-server" ] - } else if (android_static_analysis == "build_server") { + if (android_static_analysis == "build_server") { args += [ "--use-build-server" ] } @@ -1082,24 +1107,23 @@ if (enable_java_templates) { deps += [ "//build/android:prepare_android_lint_cache" ] inputs += [ _create_cache_stamp_path ] } - inputs += [ invoker.build_config ] - _rebased_build_config = - rebase_path(invoker.build_config, root_build_dir) + _lint_json = string_replace(invoker.build_config, ".json", ".lint.json") + inputs += [ _lint_json ] + _rebased_lint_json = rebase_path(_lint_json, root_build_dir) args += [ - "--manifest-path=@FileArg($_rebased_build_config:android_manifest)", - "--extra-manifest-paths=@FileArg($_rebased_build_config:lint_extra_android_manifests)", + "--manifest-paths=@FileArg($_rebased_lint_json:android_manifests)", # Lint requires all source and all resource files to be passed in the # same invocation for checks like UnusedResources. - "--sources=@FileArg($_rebased_build_config:lint_sources)", - "--aars=@FileArg($_rebased_build_config:lint_aars)", - "--srcjars=@FileArg($_rebased_build_config:lint_srcjars)", - "--resource-sources=@FileArg($_rebased_build_config:lint_resource_sources)", - "--resource-zips=@FileArg($_rebased_build_config:lint_resource_zips)", + "--sources=@FileArg($_rebased_lint_json:sources)", + "--aars=@FileArg($_rebased_lint_json:aars)", + "--srcjars=@FileArg($_rebased_lint_json:srcjars)", + "--resource-sources=@FileArg($_rebased_lint_json:resource_sources)", + "--resource-zips=@FileArg($_rebased_lint_json:resource_zips)", - # The full classpath is required for annotation checks like @IntDef. - "--classpath=@FileArg($_rebased_build_config:javac_full_interface_classpath)", + # The required for annotation checks like @IntDef. + "--classpath=@FileArg($_rebased_lint_json:classpath)", ] } @@ -1230,9 +1254,9 @@ if (enable_java_templates) { # modules' build configs may double-use some jars. if (defined(invoker.add_view_trace_events) && invoker.add_view_trace_events) { - _args += [ "--feature-jars=@FileArg($_rebased_build_config:modules:${_feature_module.name}:trace_event_rewritten_device_classpath)" ] + _args += [ "--feature-jars=@FileArg($_rebased_build_config:modules:${_feature_module.name}:trace_event_rewritten_classpath)" ] } else { - _args += [ "--feature-jars=@FileArg($_rebased_build_config:modules:${_feature_module.name}:device_classpath)" ] + _args += [ "--feature-jars=@FileArg($_rebased_build_config:modules:${_feature_module.name}:processed_classpath)" ] } if (defined(_feature_module.uses_split)) { @@ -1247,13 +1271,9 @@ if (enable_java_templates) { rebase_path(_stamp, root_build_dir), ] } else { - if (defined(invoker.has_apk_under_test) && invoker.has_apk_under_test) { - _args += [ "--input-paths=@FileArg($_rebased_build_config:device_classpath_extended)" ] - } else { - _args += [ - "--input-paths=@FileArg($_rebased_build_config:device_classpath)", - ] - } + _args += [ + "--input-paths=@FileArg($_rebased_build_config:processed_classpath)", + ] # We don't directly set the output arg on the _args variable since it is # shared with the expectation target that uses its own stamp file and @@ -1266,8 +1286,9 @@ if (enable_java_templates) { } _outputs += [ _mapping_path ] - _enable_checks = !defined(invoker.enable_proguard_checks) || - invoker.enable_proguard_checks + _enable_checks = + (!defined(invoker.enable_proguard_checks) || + invoker.enable_proguard_checks) && android_static_analysis != "off" if (!_enable_checks) { _args += [ "--disable-checks" ] } @@ -1419,7 +1440,7 @@ if (enable_java_templates) { rebase_path(_java_script, root_build_dir), "--main-class", _main_class, - "--classpath=@FileArg($_rebased_build_config:host_classpath)", + "--classpath=@FileArg($_rebased_build_config:processed_classpath)", "--max-heap-size=$_max_heap_size", ] data = [] @@ -2122,13 +2143,26 @@ if (enable_java_templates) { "--include-resources=$_rebased_android_sdk_jar", "--aapt2-path", rebase_path(android_sdk_tools_bundle_aapt2, root_build_dir), - "--dependencies-res-zips=@FileArg($_rebased_build_config:dependency_zips)", "--extra-res-packages=@FileArg($_rebased_build_config:extra_package_names)", "--min-sdk-version=${invoker.min_sdk_version}", "--target-sdk-version=${_target_sdk_version}", "--webp-cache-dir=obj/android-webp-cache", ] + if (!defined(testonly) || !testonly || + (defined(invoker.enforce_resource_overlays_in_tests) && + invoker.enforce_resource_overlays_in_tests)) { + _args += [ + "--dependencies-res-zips=@FileArg($_rebased_build_config:dependency_zips)", + "--dependencies-res-zip-overlays=@FileArg($_rebased_build_config:dependency_zip_overlays)", + ] + } else { + _args += [ + "--dependencies-res-zip-overlays=@FileArg($_rebased_build_config:dependency_zips)", + "--dependencies-res-zip-overlays=@FileArg($_rebased_build_config:dependency_zip_overlays)", + ] + } + _inputs += [ invoker.android_manifest ] _outputs = [ _final_srcjar_path ] _args += [ @@ -2239,14 +2273,6 @@ if (enable_java_templates) { "${invoker.shared_resources_allowlist_locales}" ] } - if (!defined(testonly) || !testonly || - (defined(invoker.enforce_resource_overlays_in_tests) && - invoker.enforce_resource_overlays_in_tests)) { - _args += [ "--dependencies-res-zip-overlays=@FileArg($_rebased_build_config:dependency_zip_overlays)" ] - } else { - _args += [ "--dependencies-res-zip-overlays=@FileArg($_rebased_build_config:dependency_zips)" ] - } - if (defined(invoker.proguard_file)) { _outputs += [ invoker.proguard_file ] _args += [ @@ -2493,7 +2519,7 @@ if (enable_java_templates) { if (!defined(deps)) { deps = [] } - deps += [ "//build/android/unused_resources:unused_resources" ] + deps += [ "//build/android/unused_resources" ] _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) args = [ "--script", @@ -2502,6 +2528,7 @@ if (enable_java_templates) { rebase_path(invoker.output_config, root_build_dir), "--r-text-in=@FileArg($_rebased_build_config:rtxt_path)", "--dependencies-res-zips=@FileArg($_rebased_build_config:dependency_zips)", + "--dependencies-res-zips=@FileArg($_rebased_build_config:dependency_zip_overlays)", "--depfile", rebase_path(depfile, root_build_dir), ] @@ -3074,7 +3101,7 @@ if (enable_java_templates) { args += [ "--processorpath=$_rebased_nullaway_jar", "--enable-nullaway", - "--processorpath=@FileArg($_rebased_errorprone_buildconfig:host_classpath)", + "--processorpath=@FileArg($_rebased_errorprone_buildconfig:processed_classpath)", ] inputs += [ _nullaway_jar, @@ -3086,10 +3113,7 @@ if (enable_java_templates) { if (defined(testonly) && testonly) { args += [ "--testonly" ] } - if (defined(invoker.skip_build_server) && invoker.skip_build_server) { - # Nocompile tests need lint to fail through ninja. - args += [ "--skip-build-server" ] - } else if (android_static_analysis == "build_server") { + if (android_static_analysis == "build_server") { args += [ "--use-build-server" ] } } @@ -3545,6 +3569,15 @@ if (enable_java_templates) { _dex_path = "$target_out_dir/$_main_target_name.dex.jar" _enable_desugar = !defined(invoker.enable_desugar) || invoker.enable_desugar + if (defined(invoker.min_sdk_version)) { + _min_sdk_version = invoker.min_sdk_version + } else { + _min_sdk_version = default_min_sdk_version + } + if (_min_sdk_version < default_min_sdk_version || + _min_sdk_version < 24) { + _dex_needs_classpath = true + } } # For static libraries, the javac jar output is created at the intermediate @@ -3608,6 +3641,17 @@ if (enable_java_templates) { _java_header_deps += [ "${invoker.base_module_target}__java__header" ] _java_validate_deps += [ "${invoker.base_module_target}__java__validate" ] _java_host_deps += [ "${invoker.base_module_target}__compile_java" ] + if (defined(invoker.parent_module_target)) { + assert( + invoker.parent_module_target != invoker.base_module_target, + "Use parent_module_target only when parent_module_target != base_module_target") + _java_assetres_deps += + [ "${invoker.parent_module_target}__java__assetres" ] + _java_header_deps += [ "${invoker.parent_module_target}__java__header" ] + _java_validate_deps += + [ "${invoker.parent_module_target}__java__validate" ] + _java_host_deps += [ "${invoker.parent_module_target}__compile_java" ] + } } if (_is_prebuilt || _has_sources) { @@ -3620,7 +3664,7 @@ if (enable_java_templates) { _javac_classpath_deps = _java_host_deps + _non_java_deps + [ ":$_build_config_target_name" ] - _include_android_sdk = _build_device_jar + _include_android_sdk = _requires_android if (defined(invoker.include_android_sdk)) { _include_android_sdk = invoker.include_android_sdk } @@ -3656,7 +3700,9 @@ if (enable_java_templates) { "aar_path", "annotation_processor_deps", "base_allowlist_rtxt_path", + "create_locales_java_list", "direct_deps_only", + "enable_lint", "gradle_treat_as_prebuilt", "input_jars_paths", "preferred_dep", @@ -3664,7 +3710,6 @@ if (enable_java_templates) { "main_class", "mergeable_android_manifests", "module_name", - "parent_module_target", "proguard_configs", "proguard_enabled", "proguard_mapping_path", @@ -3684,6 +3729,7 @@ if (enable_java_templates) { "android_manifest_dep", "merged_android_manifest", "final_dex_path", + "library_always_compress", "loadable_modules", "native_lib_placeholders", "res_size_info_path", @@ -3691,7 +3737,7 @@ if (enable_java_templates) { "secondary_abi_shared_libraries_runtime_deps_file", "secondary_native_lib_placeholders", "shared_libraries_runtime_deps_file", - "library_always_compress", + "uses_split", ]) } if (_type == "android_apk") { @@ -3709,12 +3755,16 @@ if (enable_java_templates) { "add_view_trace_events", "base_module_target", "module_pathmap_path", + "parent_module_target", "proto_resources_path", ]) } chromium_code = _chromium_code build_config = _build_config is_prebuilt = _is_prebuilt + if (defined(_dex_needs_classpath)) { + dex_needs_classpath = _dex_needs_classpath + } # Specifically avoid passing in invoker.base_module_target as one of the # possible_config_deps. @@ -3966,7 +4016,6 @@ if (enable_java_templates) { _compile_java_errorprone_target = "${_main_target_name}__errorprone" compile_java_helper(_compile_java_errorprone_target) { forward_variables_from(invoker, _compile_java_forward_variables) - forward_variables_from(invoker, [ "skip_build_server" ]) enable_errorprone = true if (defined(invoker.errorprone_args)) { if (!defined(javac_args)) { @@ -4279,7 +4328,7 @@ if (enable_java_templates) { if (defined(invoker.public_deps)) { public_deps += invoker.public_deps } - if (is_cronet_for_aosp_build) { + if (is_cronet_build) { # See crbug/1449896 for more details about the metadata fields # and why they are added. _java_library_deps = _default_deps @@ -4319,7 +4368,12 @@ if (enable_java_templates) { if (defined(invoker.jar_included_patterns)) { java_library_jar_included_patterns = invoker.jar_included_patterns } - java_library_android_sdk_dep = [ _android_sdk_dep ] + if (defined(invoker.alternative_android_sdk_dep)) { + java_library_android_sdk_dep = + [ invoker.alternative_android_sdk_dep ] + } else { + java_library_android_sdk_dep = [ default_android_sdk_dep ] + } } } } else { diff --git a/naiveproxy/src/build/config/android/rules.gni b/naiveproxy/src/build/config/android/rules.gni index 6b0c5f325b..d176f828ca 100644 --- a/naiveproxy/src/build/config/android/rules.gni +++ b/naiveproxy/src/build/config/android/rules.gni @@ -535,7 +535,9 @@ if (!is_robolectric && enable_java_templates) { forward_variables_from(invoker, [ "testonly" ]) _build_config = "$target_gen_dir/${target_name}.build_config.json" _rtxt_out_path = "$target_gen_dir/${target_name}.R.txt" - write_build_config("$target_name$build_config_target_suffix") { + + # Writes a .params.json via write_file(), but does not define a target. + write_build_config("unused") { forward_variables_from(invoker, [ "resource_overlay" ]) build_config = _build_config @@ -548,10 +550,7 @@ if (!is_robolectric && enable_java_templates) { } action_with_pydeps(target_name) { forward_variables_from(invoker, [ "visibility" ]) - public_deps = [ - ":$target_name$build_config_target_suffix", - invoker.generating_target, - ] + public_deps = [ invoker.generating_target ] inputs = [ invoker.generated_resources_zip ] outputs = [ _rtxt_out_path ] script = "//build/android/gyp/create_r_txt.py" @@ -748,7 +747,6 @@ if (!is_robolectric && enable_java_templates) { _resources_zip = "$target_out_dir/$target_name.resources.zip" _rtxt_out_path = _base_path + "_R.txt" _build_config = _base_path + ".build_config.json" - _build_config_target_name = "$target_name$build_config_target_suffix" _deps = [] if (defined(invoker.deps)) { @@ -779,7 +777,8 @@ if (!is_robolectric && enable_java_templates) { [ "*\bthird_party\b*" ]) != [] } - write_build_config(_build_config_target_name) { + # Writes a .params.json via write_file(), but does not define a target. + write_build_config("unused") { type = "android_resources" build_config = _build_config resources_zip = _resources_zip @@ -888,7 +887,6 @@ if (!is_robolectric && enable_java_templates) { forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) _build_config = "$target_gen_dir/$target_name.build_config.json" - _build_config_target_name = "$target_name$build_config_target_suffix" _sources = [] if (defined(invoker.sources)) { @@ -913,7 +911,8 @@ if (!is_robolectric && enable_java_templates) { "android_assets() renaming_sources.length != renaming_destinations.length") } - write_build_config(_build_config_target_name) { + # Writes a .params.json via write_file(), but does not define a target. + write_build_config("unused") { type = "android_assets" build_config = _build_config @@ -936,15 +935,11 @@ if (!is_robolectric && enable_java_templates) { # Use an action in order to mark sources as "inputs" to a GN target so that # GN will fail if the appropriate deps do not exist, and so that "gn refs" - # will know about the sources. We do not add these inputs & deps to the - # __build_config target because we want building .build_config.json files - # to be fast (and because write_build_config.py does not need the files to - # exist). + # will know about the sources. _all_sources = _sources + _renaming_sources if (_all_sources != []) { action(target_name) { forward_variables_from(invoker, [ "deps" ]) - public_deps = [ ":$_build_config_target_name" ] script = "//build/android/gyp/validate_inputs.py" inputs = _all_sources @@ -957,7 +952,6 @@ if (!is_robolectric && enable_java_templates) { } else { group(target_name) { forward_variables_from(invoker, [ "deps" ]) - public_deps = [ ":$_build_config_target_name" ] } } } @@ -986,7 +980,9 @@ if (!is_robolectric && enable_java_templates) { if (defined(invoker.public_deps)) { _invoker_deps += invoker.public_deps } - write_build_config("$target_name$build_config_target_suffix") { + + # Writes a .params.json via write_file(), but does not define a target. + write_build_config("unused") { forward_variables_from(invoker, _build_config_vars) type = "group" build_config = "$target_gen_dir/${invoker.target_name}.build_config.json" @@ -1029,10 +1025,6 @@ if (!is_robolectric && enable_java_templates) { forward_variables_from(invoker, "*", _build_config_vars + TESTONLY_AND_VISIBILITY) - if (!defined(deps)) { - deps = [] - } - deps += [ ":$target_name$build_config_target_suffix" ] if (is_cronet_for_aosp_build) { metadata = { java_library_deps = [] @@ -1354,7 +1346,6 @@ if (!is_robolectric && enable_java_templates) { # # chromium_code: If true, extra analysis warning/errors will be enabled. # enable_errorprone: If true, enables the errorprone compiler. - # skip_build_server: If true, avoids sending tasks to the build server. # # jar_excluded_patterns: List of patterns of .class files to exclude. # jar_included_patterns: List of patterns of .class files to include. @@ -1752,13 +1743,15 @@ if (!is_robolectric && enable_java_templates) { "--output", rebase_path(invoker.output, root_build_dir), "--dependencies-res-zips=@FileArg($_rebased_build_config:dependency_zips)", + "--dependencies-res-zips=@FileArg($_rebased_build_config:dependency_zip_overlays)", "--r-text-files=@FileArg($_rebased_build_config:dependency_rtxt_files)", "--proguard-configs=@FileArg($_rebased_build_config:proguard_all_configs)", ] if (_direct_deps_only) { args += [ "--jars=@FileArg($_rebased_build_config:classpath)" ] } else { - args += [ "--jars=@FileArg($_rebased_build_config:device_classpath)" ] + args += + [ "--jars=@FileArg($_rebased_build_config:processed_classpath)" ] } if (defined(invoker.android_manifest)) { @@ -2014,6 +2007,10 @@ if (!is_robolectric && enable_java_templates) { defines += [ "_IS_DESKTOP_ANDROID" ] } + if (enable_javaless_renderers) { + defines += [ "_JAVALESS_RENDERERS_AVAILABLE" ] + } + if (defined(invoker.write_clang_profiling_data) && invoker.write_clang_profiling_data) { defines += [ "_WRITE_CLANG_PROFILING_DATA" ] @@ -2767,6 +2764,9 @@ if (!is_robolectric && enable_java_templates) { invoker.add_view_trace_events && enable_trace_event_bytecode_rewriting } + _enable_lint = defined(invoker.enable_lint) && invoker.enable_lint && + !disable_android_lint + # We cannot skip this target when omit_dex = true because it writes the # build_config.json. java_library_impl(_java_target_name) { @@ -2784,18 +2784,25 @@ if (!is_robolectric && enable_java_templates) { "jacoco_never_instrument", "jar_excluded_patterns", "javac_args", + "library_always_compress", "mergeable_android_manifests", + "min_sdk_version", "native_lib_placeholders", "parent_module_target", "processor_args_javac", + "skip_build_server", "secondary_abi_loadable_modules", "secondary_native_lib_placeholders", "sources", "suffix_apk_assets_used_by", - "library_always_compress", + "uses_split", ]) + if (_generate_productconfig_java) { + create_locales_java_list = true + } version_code = _version_code version_name = _version_name + enable_lint = _enable_lint if (_is_bundle_module) { type = "android_app_bundle_module" res_size_info_path = _res_size_info_path @@ -2903,7 +2910,6 @@ if (!is_robolectric && enable_java_templates) { # Generates proguard configs deps += [ ":$_compile_resources_target" ] proguard_mapping_path = _proguard_mapping_path - has_apk_under_test = defined(invoker.apk_under_test) # Must not be set via write_build_config, because that will cause it # to be picked up by test apks that use apk_under_test. @@ -2927,7 +2933,7 @@ if (!is_robolectric && enable_java_templates) { enable_desugar = false } else { input_classes_filearg = - "@FileArg($_rebased_build_config:device_classpath)" + "@FileArg($_rebased_build_config:processed_classpath)" } } @@ -3211,8 +3217,6 @@ if (!is_robolectric && enable_java_templates) { _final_deps += [ ":$_apk_operations_target_name" ] } - _enable_lint = defined(invoker.enable_lint) && invoker.enable_lint && - !disable_android_lint if (_enable_lint) { android_lint("${target_name}__lint") { forward_variables_from(invoker, @@ -3553,10 +3557,6 @@ if (!is_robolectric && enable_java_templates) { ]) is_bundle_module = true generate_buildconfig_java = _is_base_module - if (defined(uses_split)) { - assert(defined(parent_module_target), - "Must set parent_module_target when uses_split is set") - } } } @@ -3980,6 +3980,7 @@ if (!is_robolectric && enable_java_templates) { [ "cpp_root_names", "cpp_package_name", + "deps", ]) } action_with_pydeps(_aidl_target) { @@ -4041,13 +4042,18 @@ if (!is_robolectric && enable_java_templates) { args += rebase_path(sources, root_build_dir) } if (_do_cpp_gen) { - _aidl_config = "${_aidl_target}_include_config" + _aidl_config = "${_aidl_target}__config" config(_aidl_config) { include_dirs = [ "$target_gen_dir" ] } source_set("${_aidl_target}_native") { sources = _cpp_outputs + _header_outputs deps = [ ":$_aidl_target" ] + if (defined(invoker.deps)) { + foreach(_dep, invoker.deps) { + deps += [ "${_dep}_native" ] + } + } libs = [ "binder_ndk" ] public_configs = [ "//third_party/android_sdk:libbinder_include", @@ -4526,7 +4532,7 @@ if (!is_robolectric && enable_java_templates) { if (!defined(requires_android)) { requires_android = true } - include_java_resources = !defined(invoker.include_java_resources) || + include_java_resources = defined(invoker.include_java_resources) && invoker.include_java_resources supports_android = true jar_path = "$_output_path/classes.jar" @@ -4785,6 +4791,9 @@ if (!is_robolectric && enable_java_templates) { not_needed(invoker, [ "add_view_trace_events" ]) } + _enable_lint = defined(invoker.enable_lint) && invoker.enable_lint && + !disable_android_lint + _build_config_target_name = "$_target_name$build_config_target_suffix" _build_config_target = ":$_build_config_target_name" write_build_config(_build_config_target_name) { @@ -4792,7 +4801,7 @@ if (!is_robolectric && enable_java_templates) { possible_config_deps = _module_targets + [ _android_sdk_dep ] build_config = _build_config proguard_enabled = _proguard_enabled - modules = _modules + enable_lint = _enable_lint if (_proguard_enabled) { add_view_trace_events = _add_view_trace_events @@ -4825,9 +4834,9 @@ if (!is_robolectric && enable_java_templates) { "--classpath", "@FileArg($_rebased_build_config:sdk_jars)", "--input-jars", - "@FileArg($_rebased_build_config:device_classpath)", + "@FileArg($_rebased_build_config:processed_classpath)", "--output-jars", - "@FileArg($_rebased_build_config:trace_event_rewritten_device_classpath)", + "@FileArg($_rebased_build_config:trace_event_rewritten_classpath)", ] deps = [ _build_config_target, @@ -5199,8 +5208,6 @@ if (!is_robolectric && enable_java_templates) { } } - _enable_lint = defined(invoker.enable_lint) && invoker.enable_lint && - !disable_android_lint if (_enable_lint) { android_lint("${target_name}__lint") { forward_variables_from(invoker, diff --git a/naiveproxy/src/build/config/apple/codesign.py b/naiveproxy/src/build/config/apple/codesign.py index 62db2573e5..84a1a57543 100644 --- a/naiveproxy/src/build/config/apple/codesign.py +++ b/naiveproxy/src/build/config/apple/codesign.py @@ -34,6 +34,22 @@ else: basestring_compat = str +class FileListAction(argparse.Action): + """Action that load a file and interpret it as a list of file names.""" + + def __init__(self, option_strings, dest, nargs=None, **kwds): + if nargs is not None: + raise ValueError("nargs not allowed") + super().__init__(option_strings, dest, nargs, **kwds) + + def __call__(self, parser, namespace, values, option_strings): + dest = getattr(namespace, self.dest) + with open(values, 'r', encoding='utf-8') as stream: + for line in stream: + path = line[:-1] + dest.append(path) + + def GetProvisioningProfilesDirs(): """Returns the location of the installed mobile provisioning profiles. @@ -494,6 +510,14 @@ class CodeSignBundleAction(Action): dest='mobileprovision_files', help='list of mobileprovision files to use. If empty, uses the files ' + 'in $HOME/Library/MobileDevice/Provisioning Profiles') + parser.add_argument( + '--mobileprovision-list', + '-M', + action=FileListAction, + dest='mobileprovision_files', + help='path to a file containing a list of mobileprovision files to ' + + 'use (this will behave as each "-m $line" was passsed for each line ' + + 'in that file)') parser.set_defaults(no_signature=False) @staticmethod @@ -673,6 +697,14 @@ class GenerateEntitlementsAction(Action): dest='mobileprovision_files', help='set of mobileprovision files to use. If empty, uses the files ' + 'in $HOME/Library/MobileDevice/Provisioning Profiles') + parser.add_argument( + '--mobileprovision-list', + '-M', + action=FileListAction, + dest='mobileprovision_files', + help='path to a file containing a list of mobileprovision files to ' + + 'use (this will behave as each "-m $line" was passsed for each line ' + + 'in that file)') @staticmethod def _Execute(args): @@ -705,6 +737,14 @@ class FindProvisioningProfileAction(Action): dest='mobileprovision_files', help='set of mobileprovision files to use. If empty, uses the files ' + 'in $HOME/Library/MobileDevice/Provisioning Profiles') + parser.add_argument( + '--mobileprovision-list', + '-M', + action=FileListAction, + dest='mobileprovision_files', + help='path to a file containing a list of mobileprovision files to ' + + 'use (this will behave as each "-m $line" was passsed for each line ' + + 'in that file)') @staticmethod def _Execute(args): diff --git a/naiveproxy/src/build/config/apple/compile_ib_files.py b/naiveproxy/src/build/config/apple/compile_ib_files.py index ca535ca307..3bc8ce79a2 100644 --- a/naiveproxy/src/build/config/apple/compile_ib_files.py +++ b/naiveproxy/src/build/config/apple/compile_ib_files.py @@ -38,7 +38,7 @@ def main(): ibtool_section_re = re.compile(r'/\*.*\*/') ibtool_re = re.compile(r'.*note:.*is clipping its content') try: - stdout = subprocess.check_output(ibtool_args) + stdout = subprocess.check_output(ibtool_args, encoding='utf-8') except subprocess.CalledProcessError as e: print(e.output) raise diff --git a/naiveproxy/src/build/config/apple/create_signed_bundle.gni b/naiveproxy/src/build/config/apple/create_signed_bundle.gni index 989ab96bdd..c2325afa8c 100644 --- a/naiveproxy/src/build/config/apple/create_signed_bundle.gni +++ b/naiveproxy/src/build/config/apple/create_signed_bundle.gni @@ -318,12 +318,10 @@ template("apple_mobile_create_signed_bundle") { "-t=" + invoker.platform_sdk_name, "-i=" + ios_code_signing_identity, "-b=" + rebase_path(_bundle_binary_path, root_build_dir), + "-M=" + rebase_path(ios_mobileprovision_files_filelist, root_build_dir), ] - foreach(mobileprovision, ios_mobileprovision_files) { - post_processing_args += - [ "-m=" + rebase_path(mobileprovision, root_build_dir) ] - } post_processing_sources += ios_mobileprovision_files + post_processing_sources += [ ios_mobileprovision_files_filelist ] if (_enable_entitlements) { post_processing_args += [ "-e=" + rebase_path(_entitlements_path, root_build_dir) ] diff --git a/naiveproxy/src/build/config/apple/mobile_config.gni b/naiveproxy/src/build/config/apple/mobile_config.gni index 48e80f2165..28bba9fd1f 100644 --- a/naiveproxy/src/build/config/apple/mobile_config.gni +++ b/naiveproxy/src/build/config/apple/mobile_config.gni @@ -51,6 +51,14 @@ declare_args() { ios_mobileprovision_files = [] } +# Generates ios_mobileprovision_files_filelist that will contain one file +# name per line. This is used to reduce the length of the commande line +# to codesign.py script. There is a different file per toolchain. +ios_mobileprovision_files_filelist = "$root_out_dir/mobileprovisions.filelist" +write_file(ios_mobileprovision_files_filelist, + rebase_path(ios_mobileprovision_files, root_build_dir), + "list lines") + # As entitlements are tied to a specific bundle identifier, all the # test applications share the same identifier. This simplifies adding # new test application (since there is no need to investigate which diff --git a/naiveproxy/src/build/config/c++/c++.gni b/naiveproxy/src/build/config/c++/c++.gni index 24a58a9466..d559d2adee 100644 --- a/naiveproxy/src/build/config/c++/c++.gni +++ b/naiveproxy/src/build/config/c++/c++.gni @@ -2,7 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/config/nacl/config.gni") import("//build/config/sanitizers/sanitizers.gni") import("//build/toolchain/rbe.gni") import("//build_overrides/build.gni") @@ -48,12 +47,11 @@ declare_args() { # Apple platforms provide the intrinsics from a different library, and the # implementations in compiler-rt are outdated, so avoid building them in this # case. - use_llvm_libatomic = !is_apple && !is_nacl + use_llvm_libatomic = !is_apple } use_custom_libcxx = use_custom_libcxx || (use_custom_libcxx_for_host && !is_a_target_toolchain) -use_custom_libcxx = use_custom_libcxx && !is_nacl declare_args() { # WARNING: Setting this to a non-default value is highly discouraged. @@ -76,7 +74,7 @@ declare_args() { # The saigo libc++ is distinct from the custom hermetic libc++. However, since # the Chrome team controls the saigo toolchain, it is safe to unconditionally # enable libc++ hardening there as well. -use_safe_libcxx = (use_custom_libcxx && enable_safe_libcxx) || is_nacl_saigo +use_safe_libcxx = use_custom_libcxx && enable_safe_libcxx # libc++abi needs to be exported from executables to be picked up by shared # libraries on certain instrumented builds. @@ -100,7 +98,7 @@ if (is_android && export_libcxxabi_from_executables) { libcxx_is_shared = true } -if (use_libcxx_modules) { +if (use_clang_modules) { libcxx_prefix = "${root_gen_dir}/third_party/libc++/src" libcxx_modulemap_in = read_file("//third_party/libc++/src/include/module.modulemap.in", diff --git a/naiveproxy/src/build/config/c++/modules.gni b/naiveproxy/src/build/config/c++/modules.gni new file mode 100644 index 0000000000..0350c5ec60 --- /dev/null +++ b/naiveproxy/src/build/config/c++/modules.gni @@ -0,0 +1,52 @@ +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/clang/clang.gni") + +if (is_ios) { + import("//build/config/ios/ios_sdk.gni") + sdk_path = ios_sdk_path +} + +if (is_mac) { + import("//build/config/mac/mac_sdk.gni") + sdk_path = mac_sdk_path +} + +if (use_clang_modules) { + if (is_linux || is_chromeos) { + sysroot_modulemap = "//build/linux/amd64/module.modulemap" + } else if (is_apple) { + sysroot_modulemaps = [ + "$sdk_path/usr/include/DarwinBasic.modulemap", + "$sdk_path/usr/include/DarwinFoundation.modulemap", + "$sdk_path/usr/include/c_standard_library.modulemap", + ] + } else if (is_android) { + sysroot_modulemap = "//build/android/amd64/module.modulemap" + } + + if (defined(sysroot_modulemap)) { + sysroot_modulemaps = [ sysroot_modulemap ] + } + + module_map_flags = + [ "-fmodule-map-file=" + rebase_path( + "${root_gen_dir}/third_party/libc++/src/include/module.modulemap", + root_build_dir) ] + module_map_flags += [ clang_arg_prefix + "-fbuiltin-module-map" ] + foreach(modulemap, sysroot_modulemaps) { + module_map_flags += + [ "-fmodule-map-file=" + rebase_path(modulemap, root_build_dir) ] + } + + # Textual modules do not need to be precompiled. + # However, like regular modules, they do need to include things. + template("textual_module") { + source_set(target_name) { + forward_variables_from(invoker, [ "public_deps" ]) + use_libcxx_modules = false + } + } +} diff --git a/naiveproxy/src/build/config/chrome_build.gni b/naiveproxy/src/build/config/chrome_build.gni index 6d192b8a00..e7f18493d5 100644 --- a/naiveproxy/src/build/config/chrome_build.gni +++ b/naiveproxy/src/build/config/chrome_build.gni @@ -88,4 +88,4 @@ declare_args() { # Whether to enable built-in branding assets (logos & marketing snippets) for # search providers in choice UIs. -enable_builtin_search_provider_assets = is_chrome_branded && !is_android +enable_builtin_search_provider_assets = is_chrome_branded diff --git a/naiveproxy/src/build/config/clang/BUILD.gn b/naiveproxy/src/build/config/clang/BUILD.gn index 1a663091eb..20a2ec81a1 100644 --- a/naiveproxy/src/build/config/clang/BUILD.gn +++ b/naiveproxy/src/build/config/clang/BUILD.gn @@ -97,7 +97,6 @@ clang_plugin("find_bad_constructs") { # dynamically. plugin = "find-bad-constructs" plugin_arguments = [ - "span-ctor-from-string-literal", "raw-ref-template-as-trivial-member", "raw-span-template-as-trivial-member", "check-stack-allocated", @@ -220,6 +219,10 @@ template("clang_lib") { _dir = "loongarch64-unknown-linux-gnu" } else if (current_cpu == "riscv64") { _dir = "riscv64-unknown-linux-gnu" + } else if (current_cpu == "ppc64") { + _dir = "ppc64le-unknown-linux-gnu" + } else if (current_cpu == "s390x") { + _dir = "s390x-unknown-linux-gnu" } else { assert(false) # Unhandled cpu type } @@ -292,7 +295,7 @@ clang_lib("compiler_builtins") { } else { assert(false, "unsupported target_platform=$target_platform") } - } else { + } else if (current_cpu != "ppc64" && current_cpu != "s390x") { libname = "builtins" } } diff --git a/naiveproxy/src/build/config/clang/clang.gni b/naiveproxy/src/build/config/clang/clang.gni index 01493db516..95812df016 100644 --- a/naiveproxy/src/build/config/clang/clang.gni +++ b/naiveproxy/src/build/config/clang/clang.gni @@ -14,11 +14,8 @@ declare_args() { # coding guidelines, etc. Only used when compiling with Chrome's Clang, not # Chrome OS's. clang_use_chrome_plugins = - is_clang && !is_nacl && current_os != "zos" && - default_toolchain != "//build/toolchain/cros:target" && - # TODO(https://crbug.com/351909443): Remove this after fixing performance - # of Clang modules build. - !use_libcxx_modules + is_clang && 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 @@ -68,3 +65,9 @@ if (defined(clang_warning_suppression_file) && # The leading space is important, if the string is non-empty. rbe_bug_326584510_missing_inputs = " -inputs=" + string_join(",", rbe_bug_326584510_missing_input_list) + +if (is_win) { + clang_arg_prefix = "/clang:" +} else { + clang_arg_prefix = "" +} diff --git a/naiveproxy/src/build/config/compiler/BUILD.gn b/naiveproxy/src/build/config/compiler/BUILD.gn index 220e4dd1ae..8864110fc9 100644 --- a/naiveproxy/src/build/config/compiler/BUILD.gn +++ b/naiveproxy/src/build/config/compiler/BUILD.gn @@ -5,6 +5,7 @@ import("//build/buildflag_header.gni") import("//build/config/android/config.gni") import("//build/config/c++/c++.gni") +import("//build/config/c++/modules.gni") import("//build/config/chrome_build.gni") import("//build/config/chromeos/args.gni") import("//build/config/clang/clang.gni") @@ -35,12 +36,6 @@ if (is_mac) { if (is_ios) { import("//build/config/ios/ios_sdk.gni") } -if (is_nacl) { - # To keep NaCl variables out of builds that don't include NaCl, all - # variables defined in nacl/config.gni referenced here should be protected by - # is_nacl conditions. - import("//build/config/nacl/config.gni") -} # Normally, clang will find the correct LLD binary to invoke without needing # -B to be passed. For cases where this does not give the correct result, @@ -199,14 +194,23 @@ declare_args() { # This greatly reduces the size of debug builds, at the cost of # debugging information which is required by some specialized # debugging tools. - simple_template_names = is_clang && !is_nacl && !is_win && !is_apple + simple_template_names = is_clang && !is_win && !is_apple + + # This switch is used to enable -Wexit-time-destructors by default. This + # warning serves as a flip switch to allow a gradual migration of targets + # away from the opt-in wexit_time_destructors config, and into the default + # compiler config. + # TODO(crbug.com/40031409): This argument will eventually default to true, + # but ultimately the goal is for it to eventually be removed, once this mode + # is stable enough. + is_wexit_time_destructors_default = false } declare_args() { # Set to true to use icf, Identical Code Folding. use_icf = (is_posix || is_fuchsia) && !is_debug && !using_sanitizer && - !use_clang_coverage && current_os != "zos" && - !(is_android && use_order_profiling) && use_lld && !is_wasm + !use_clang_coverage && !(is_android && use_order_profiling) && + use_lld && !is_wasm } if (is_android) { @@ -218,12 +222,32 @@ if (is_android) { # The orderfile is trained on PGO builds (for arm64) and AFDO builds (for # arm32), so apply them only in these cases. - if (defined(default_chrome_orderfile)) { - if (((current_cpu == "arm64" || current_cpu == "x64") && - chrome_pgo_phase == 2) || - ((current_cpu == "arm" || current_cpu == "x86") && - clang_use_default_sample_profile)) { + if (((current_cpu == "arm64" || current_cpu == "x64") && + chrome_pgo_phase == 2) || + ((current_cpu == "arm" || current_cpu == "x86") && + clang_use_default_sample_profile)) { + if (defined(default_chrome_orderfile)) { chrome_orderfile_path = default_chrome_orderfile + } else if (enable_chrome_android_internal) { + # We generate separate orderfiles for 32-bit and 64-bit architectures + # to improve performance and reduce memory usage. + # - WebView and Chrome ARM64, see https://crbug.com/41490637. + # - WebView and Chrome x86, see https://crbug.com/967343. + # *IMPORTANT*: The x86 and x64 architectures are used to test orderfile + # logic more easily on an emulator, so the decision to use the arm64 + # orderfile for x64 (instead of arm32) is somewhat arbitrary. We just + # needed to use some real orderfile. + if (is_desktop_android && current_cpu == "x64") { + # For Android Desktop x64, orderfile is disabled, see + # https://crbug.com/422005929. + chrome_orderfile_path = "" + } else if (current_cpu == "arm64" || current_cpu == "x64") { + chrome_orderfile_path = + "//chrome/android/orderfiles/arm64/orderfile.arm64.out" + } else if (current_cpu == "arm" || current_cpu == "x86") { + chrome_orderfile_path = + "//chrome/android/orderfiles/arm/orderfile.arm.out" + } } } } @@ -248,7 +272,7 @@ assert(!(llvm_force_head_revision && use_remoteexec && host_os != "linux"), # Since this is referenced both when passing the file and when deciding which # warnings to enable, store it in a separate variable here. use_clang_warning_suppression_file = - !is_nacl && default_toolchain != "//build/toolchain/cros:target" && + default_toolchain != "//build/toolchain/cros:target" && !llvm_android_mainline && is_clang && clang_warning_suppression_file != "" # default_include_dirs --------------------------------------------------------- @@ -307,8 +331,6 @@ config("compiler") { if (current_os == "openwrt") { configs += [ "//build/config/openwrt:compiler" ] } - } else if (is_nacl) { - configs += [ "//build/config/nacl:compiler" ] } else if (is_mac) { configs += [ "//build/config/mac:compiler" ] } else if (is_ios) { @@ -344,13 +366,12 @@ config("compiler") { # Here we enable -fno-delete-null-pointer-checks, which makes various nullptr # operations (e.g. dereferencing) into defined behavior. This avoids deletion # of some security-critical code: see https://crbug.com/1139129. - # The older NaCl toolchain does not support the flag. And, we still want UBSan - # to catch undefined behavior related to nullptrs, so do not add this flag if - # UBSan is enabled. GCC seems to have some bugs compiling constexpr code when - # this is defined, so only enable it if using_clang. - # See: https://gcc.gnu.org/PR97913 + # We still want UBSan to catch undefined behavior related to nullptrs, so do + # not add this flag if UBSan is enabled. GCC seems to have some bugs + # compiling constexpr code when this is defined, so only enable it if + # using_clang. See: https://gcc.gnu.org/PR97913 # TODO(mpdenton): remove is_clang once GCC bug is fixed. - if ((!is_nacl || is_nacl_saigo) && !is_ubsan && is_clang) { + if (!is_ubsan && is_clang) { cflags += [ "-fno-delete-null-pointer-checks" ] } @@ -372,6 +393,20 @@ config("compiler") { cflags += [ "-fno-ident" ] } + # We cannot rely on errno being set after math functions, + # especially since glibc does not set it. Thus, use -fno-math-errno + # so that the compiler knows it can inline math functions. + # Note that this is different from -ffast-math (even though -ffast-math + # implies -fno-math-errno), which also allows a number of unsafe + # optimizations. This flag must be consistently set for both module + # precompilation and normal source compilation, which means it's enabled for + # some targets even in debug builds. + if (is_win && is_clang) { + cflags += [ "/clang:-fno-math-errno" ] + } else if (!is_win) { + cflags += [ "-fno-math-errno" ] + } + # In general, Windows is totally different, but all the other builds share # some common compiler and linker configuration. if (!is_win) { @@ -405,7 +440,7 @@ config("compiler") { } } else if (is_chromeos) { cflags += [ "-fstack-protector-strong" ] - } else if ((is_posix && !is_nacl) || is_fuchsia) { + } else if (is_posix || is_fuchsia) { if (current_os != "aix") { # Not available on aix. cflags += [ "-fstack-protector" ] @@ -455,7 +490,7 @@ config("compiler") { # links. ldflags += [ "-Wl,--build-id=sha1" ] } else if (current_os != "aix" && current_os != "zos") { - if (use_lld && !is_nacl) { + if (use_lld) { ldflags += [ "-Wl,--build-id=fast" ] } else { ldflags += [ "-Wl,--build-id" ] @@ -473,18 +508,16 @@ config("compiler") { ] } - if (!is_nacl) { - if (exclude_unwind_tables) { - cflags += [ - "-fno-unwind-tables", - "-fno-asynchronous-unwind-tables", - ] - rustflags += [ "-Cforce-unwind-tables=no" ] - defines += [ "NO_UNWIND_TABLES" ] - } else { - cflags += [ "-funwind-tables" ] - rustflags += [ "-Cforce-unwind-tables=yes" ] - } + if (exclude_unwind_tables) { + cflags += [ + "-fno-unwind-tables", + "-fno-asynchronous-unwind-tables", + ] + rustflags += [ "-Cforce-unwind-tables=no" ] + defines += [ "NO_UNWIND_TABLES" ] + } else { + cflags += [ "-funwind-tables" ] + rustflags += [ "-Cforce-unwind-tables=yes" ] } } @@ -592,6 +625,10 @@ config("compiler") { cflags += [ "-fno-sized-deallocation" ] } } + + if (diagnostics_print_source_range_info && !is_win) { + cflags += [ "-fdiagnostics-print-source-range-info" ] + } } if (use_lld) { @@ -613,7 +650,7 @@ config("compiler") { ldflags += [ "-Wl,-z,keep-text-section-prefix" ] } - if (is_clang && !is_nacl) { + if (is_clang) { cflags += [ "-fcrash-diagnostics-dir=" + clang_diagnostic_dir ] if (save_reproducers_on_lld_crash && use_lld) { ldflags += [ @@ -664,7 +701,10 @@ config("compiler") { # Enable ELF CREL (see crbug.com/357878242) for all platforms that use ELF # (excluding toolchains that use an older version of LLVM). # TODO(crbug.com/376278218): This causes segfault on Linux ARM builds. + # It also causes segfault on Linux s390x: + # https://github.com/llvm/llvm-project/issues/149511 if (is_linux && use_lld && !llvm_android_mainline && current_cpu != "arm" && + current_cpu != "s390x" && current_cpu != "mipsel" && current_cpu != "mips64el" && default_toolchain != "//build/toolchain/cros:target") { cflags += [ "-Wa,--crel,--allow-experimental-crel" ] @@ -673,8 +713,7 @@ config("compiler") { # C11/C++11 compiler flags setup. # --------------------------- - if (is_linux || is_chromeos || is_android || (is_nacl && is_clang) || - current_os == "aix") { + if (is_linux || is_chromeos || is_android || current_os == "aix") { if (is_clang) { standard_prefix = "c" @@ -682,12 +721,6 @@ config("compiler") { # defined by the compiler. However, lots of code relies on the # non-standard features that _GNU_SOURCE enables, so define it manually. defines += [ "_GNU_SOURCE" ] - - if (is_nacl) { - # Undefine __STRICT_ANSI__ to get non-standard features which would - # otherwise not be enabled by NaCl's sysroots. - cflags += [ "-U__STRICT_ANSI__" ] - } } else { # Gcc does not support ##__VA_ARGS__ when in standards-conforming mode, # but we use this feature in several places in Chromium. @@ -698,17 +731,12 @@ config("compiler") { } cflags_c += [ "-std=${standard_prefix}11" ] - if (is_nacl && !is_nacl_saigo) { - # This is for the pnacl_newlib toolchain. It's only used to build - # a few independent ppapi test files that don't pull in any other - # dependencies. - cflags_cc += [ "-std=${standard_prefix}++14" ] - if (is_clang) { - cflags_cc += [ "-fno-trigraphs" ] - } - } else if (is_clang) { + if (is_clang) { if (defined(use_cxx17) && use_cxx17) { + assert(!use_cxx23) cflags_cc += [ "-std=${standard_prefix}++17" ] + } else if (use_cxx23) { + cflags_cc += [ "-std=${standard_prefix}++23" ] } else { cflags_cc += [ "-std=${standard_prefix}++20" ] } @@ -720,7 +748,10 @@ config("compiler") { } else if (is_win) { cflags_c += [ "/std:c11" ] if (defined(use_cxx17) && use_cxx17) { + assert(!use_cxx23) cflags_cc += [ "/std:c++17" ] + } else if (use_cxx23) { + cflags_cc += [ "/std:c++23" ] } else { cflags_cc += [ "/std:c++20" ] } @@ -730,16 +761,14 @@ config("compiler") { # See: https://learn.microsoft.com/en-us/cpp/build/reference/zc-cplusplus cflags_cc += [ "/Zc:__cplusplus" ] } - } else if (!is_nacl) { - # TODO(mcgrathr) - the NaCl GCC toolchain doesn't support either - # gnu11/gnu++11 or c11/c++11; we technically don't need this toolchain any - # more, but there are still a few buildbots using it, so until those are - # turned off we need the !is_nacl clause and the (is_nacl && is_clang) - # clause, above. + } else { cflags_c += [ "-std=c11" ] if (defined(use_cxx17) && use_cxx17) { + assert(!use_cxx23) cflags_cc += [ "-std=c++17" ] + } else if (use_cxx23) { + cflags_cc += [ "-std=c++23" ] } else { cflags_cc += [ "-std=c++20" ] } @@ -930,7 +959,7 @@ config("compiler") { } if (compiler_timing) { - if (is_clang && !is_nacl) { + if (is_clang) { cflags += [ "-ftime-trace" ] if (use_lld && is_mac) { ldflags += [ "-Wl,--time-trace" ] @@ -973,7 +1002,7 @@ config("compiler") { } } - if (is_clang && !is_nacl && show_includes) { + if (is_clang && show_includes) { if (is_win) { cflags += [ "/clang:-H", @@ -990,8 +1019,7 @@ config("compiler") { # This flag enforces that member pointer base types are complete. It helps # prevent us from running into problems in the Microsoft C++ ABI (see # https://crbug.com/847724). - if (is_clang && !is_nacl && target_os != "chromeos" && - (is_win || use_custom_libcxx)) { + if (is_clang && target_os != "chromeos" && (is_win || use_custom_libcxx)) { cflags += [ "-fcomplete-member-pointers" ] } @@ -1061,7 +1089,7 @@ config("compiler") { asmflags += cflags_c } - if (is_chromeos_device && !is_nacl) { + if (is_chromeos_device) { # On ChromeOS devices, we want to ensure we're using Chrome's allocator # symbols for all C++ new/delete operator overloads. PartitionAlloc # and other local allocators should always take precedence over system or @@ -1269,8 +1297,7 @@ config("compiler_cpu_abi") { # CPU architecture. We may or may not be doing a cross compile now, so for # simplicity we always explicitly set the architecture. if (current_cpu == "x64") { - if (is_clang && !is_android && !is_nacl && !is_fuchsia && - !is_chromeos_device && current_os != "openwrt") { + if (is_clang && !is_android && !is_fuchsia && !is_chromeos_device && current_os != "openwrt") { cflags += [ "--target=x86_64-unknown-linux-gnu" ] ldflags += [ "--target=x86_64-unknown-linux-gnu" ] } else { @@ -1279,50 +1306,43 @@ config("compiler_cpu_abi") { } cflags += [ "-msse3" ] } else if (current_cpu == "x86") { - if (is_clang && !is_android && !is_nacl && !is_chromeos_device && - current_os != "openwrt") { + if (is_clang && !is_android && !is_chromeos_device && current_os != "openwrt") { cflags += [ "--target=i386-unknown-linux-gnu" ] ldflags += [ "--target=i386-unknown-linux-gnu" ] } else { cflags += [ "-m32" ] ldflags += [ "-m32" ] } - if (!is_nacl) { - cflags += [ - "-mfpmath=sse", - "-msse3", - ] - } + cflags += [ + "-mfpmath=sse", + "-msse3", + ] } else if (current_cpu == "arm") { - if (is_clang && !is_android && !is_nacl && !is_chromeos_device && - current_os != "openwrt") { + if (is_clang && !is_android && !is_chromeos_device && current_os != "openwrt") { cflags += [ "--target=arm-linux-gnueabihf" ] ldflags += [ "--target=arm-linux-gnueabihf" ] } - if (!is_nacl) { - cflags += [ - "-mfloat-abi=$arm_float_abi", - ] - if (arm_cpu != "") { - cflags += [ "-mcpu=$arm_cpu" ] - } else { - cflags += [ "-march=$arm_arch" ] - } - ldflags += [ "-mfloat-abi=$arm_float_abi" ] + cflags += [ + "-march=$arm_arch", + "-mfloat-abi=$arm_float_abi", + ] + if (arm_cpu != "") { + cflags -= [ "-march=$arm_arch" ] + cflags += [ "-mcpu=$arm_cpu" ] } + ldflags += [ "-mfloat-abi=$arm_float_abi" ] if (arm_tune != "") { cflags += [ "-mtune=$arm_tune" ] } } else if (current_cpu == "arm64") { - if (is_clang && !is_android && !is_nacl && !is_fuchsia && - !is_chromeos_device && current_os != "openwrt") { + if (is_clang && !is_android && !is_fuchsia && !is_chromeos_device && current_os != "openwrt") { cflags += [ "--target=aarch64-linux-gnu" ] ldflags += [ "--target=aarch64-linux-gnu" ] } if (arm_cpu != "") { cflags += [ "-mcpu=$arm_cpu" ] } - } else if (current_cpu == "mipsel" && !is_nacl) { + } else if (current_cpu == "mipsel") { ldflags += [ "-Wl,--hash-style=sysv" ] if (custom_toolchain == "" && current_os != "openwrt") { if (is_clang) { @@ -1415,7 +1435,7 @@ config("compiler_cpu_abi") { if (!is_debug && use_thin_lto && is_a_target_toolchain && mips_float_abi == "soft") { ldflags += [ "-Wl,-mllvm,-mattr=+soft-float" ] } - } else if (current_cpu == "mips" && !is_nacl) { + } else if (current_cpu == "mips") { ldflags += [ "-Wl,--hash-style=sysv" ] if (custom_toolchain == "") { if (is_clang) { @@ -1622,10 +1642,6 @@ config("compiler_codegen") { cflags = [] ldflags = [] - if (is_nacl) { - configs += [ "//build/config/nacl:compiler_codegen" ] - } - if (current_cpu == "arm64" && !is_win && is_clang) { # Disable outlining everywhere on arm64 except Win. For more information see # crbug.com/931297 for Android and crbug.com/1410297 for iOS. @@ -1680,26 +1696,17 @@ config("compiler_deterministic") { # different build directory like "out/feature_a" and "out/feature_b" if # we build same files with same compile flag. # Other paths are already given in relative, no need to normalize them. - if (is_nacl) { - # TODO(https://crbug.com/1231236): Use -ffile-compilation-dir= here. - cflags += [ - "-Xclang", - "-fdebug-compilation-dir", - "-Xclang", - ".", - ] - } else { - # -ffile-compilation-dir is an alias for both -fdebug-compilation-dir= - # and -fcoverage-compilation-dir=. - cflags += [ "-ffile-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), - ] - } + # -ffile-compilation-dir is an alias for both -fdebug-compilation-dir= + # and -fcoverage-compilation-dir=. + cflags += [ "-ffile-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) asmflags = [ "-Wa,-fdebug-compilation-dir,." ] @@ -1722,7 +1729,7 @@ config("compiler_deterministic") { # Tells the compiler not to use absolute paths when passing the default # paths to the tools it invokes. We don't want this because we don't # really need it and it can mess up the RBE cache entries. - if (is_clang && (!is_nacl || is_nacl_saigo)) { + if (is_clang) { cflags += [ "-no-canonical-prefixes" ] # Same for links: Let the compiler driver invoke the linker @@ -1736,7 +1743,7 @@ config("compiler_deterministic") { } } - if (use_libcxx_modules) { + if (use_clang_modules) { cflags += [ # This removes absolute paths from .pcm files. "-Xclang", @@ -1846,6 +1853,29 @@ config("clang_warning_suppression") { } } +# Enable bounds checks when indexing directly (i.e. not via a pointer) +# into C arrays. This aligns with libc++ hardening for +# `std::array::operator[]`. +# +# UBSan already includes these checks and more. +# GCC does not appear to support these flags. +# +# This config appears to tip "ASan Debug (32-bit x86 with V8-ARM)" just +# over the brink and prevent ASan from grabbing its necessary 512 MB of +# address space. (N.B. the issue is not seen on its release counterpart, +# and it might have been possible to mitigate with +# `is_component_build = false`.) +# +# See also: https://crbug.com/40891132#comment10 +config("sanitize_c_array_bounds") { + if (!is_ubsan && is_clang && !(is_asan && target_cpu == "x86")) { + cflags = [ + "-fsanitize=array-bounds", + "-fsanitize-trap=array-bounds", + ] + } +} + config("rustc_revision") { if (rustc_revision != "") { # Similar to the above config, this is here so that all files get recompiled @@ -1859,7 +1889,7 @@ config("rustc_revision") { } config("compiler_arm_fpu") { - if (current_cpu == "arm" && !is_ios && !is_nacl && arm_fpu != "") { + if (current_cpu == "arm" && !is_ios && arm_fpu != "") { cflags = [ "-mfpu=$arm_fpu" ] if (!arm_use_thumb) { cflags += [ "-marm" ] @@ -1869,8 +1899,7 @@ config("compiler_arm_fpu") { } config("compiler_arm_thumb") { - if (current_cpu == "arm" && arm_use_thumb && is_posix && - !(is_apple || is_nacl)) { + if (current_cpu == "arm" && arm_use_thumb && is_posix && !is_apple) { cflags = [ "-mthumb" ] } } @@ -1884,34 +1913,26 @@ config("compiler_arm") { } config("libcxx_module") { - if (use_libcxx_modules) { - modulemap = rebase_path( - "${root_gen_dir}/third_party/libc++/src/include/module.modulemap", - root_build_dir) - sysroot_modulemap = - rebase_path("//build/linux/amd64/module.modulemap", root_build_dir) + if (use_clang_modules) { + cflags_cc = + [ + "-fmodules", + clang_arg_prefix + "-fno-implicit-module-maps", + "-fno-implicit-modules", - cflags_cc = [ - "-fmodules", - "-fmodule-map-file=" + modulemap, - "-fbuiltin-module-map", - "-fmodule-map-file=" + sysroot_modulemap, - "-fno-implicit-module-maps", - "-fno-implicit-modules", + "-Xclang", + "-fmodules-local-submodule-visibility", # required for builtins - "-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/1456385): Figure out if this can be removed. - "-Wno-modules-ambiguous-internal-linkage", + # TODO(crbug.com/40440396): Clean up. + "-Wno-modules-import-nested-redundant", - # 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", - ] + # Needed to allow using builtin modules when the headers are + # unnecessarily using extern "C". + "-Wno-module-import-in-extern-c", + ] + module_map_flags } } @@ -1942,7 +1963,7 @@ config("runtime_library") { # the C++ symbols. This config ensures the C++ symbols exist and are strong in # order to cause that replacement to occur by explicitly linking in clang's # compiler-rt library. - if (is_clang && !is_nacl && !is_cronet_build) { + if (is_clang && !is_cronet_build) { configs += [ "//build/config/clang:compiler_builtins" ] } @@ -2024,15 +2045,9 @@ config("tot_warnings") { # Entries should generally require both is_clang and llvm_force_head_revision, # but may have additional constraints as well (e.g. only some OSes) - if (is_clang && llvm_force_head_revision && !is_nacl) { - cflags_cc += [ - # TODO(crbug.com/417996267): Fix and re-enable - "-Wno-character-conversion", - ] - cflags_objcc += [ - # TODO(crbug.com/417996267): Fix and re-enable - "-Wno-character-conversion", - ] + if (is_clang && llvm_force_head_revision) { + # TODO(crbug.com/432275627): Fix and re-enable. + cflags += [ "-Wno-uninitialized-const-pointer" ] } } @@ -2070,7 +2085,7 @@ config("default_warnings") { cflags += [ "/wd4244" ] } } else { - if ((is_apple || is_android) && !is_nacl) { + if (is_apple || is_android) { # Warns if a method is used whose availability is newer than the # deployment target. cflags += [ "-Wunguarded-availability" ] @@ -2098,13 +2113,11 @@ config("default_warnings") { cflags_cc += [ # See comment for -Wno-c++11-narrowing. "-Wno-narrowing", - ] - # -Wno-class-memaccess warns about hash table and vector in blink. - # But the violation is intentional. - if (!is_nacl) { - cflags_cc += [ "-Wno-class-memaccess" ] - } + # -Wno-class-memaccess warns about hash table and vector in blink. + # But the violation is intentional. + "-Wno-class-memaccess", + ] # -Wunused-local-typedefs is broken in gcc, # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63872 @@ -2133,6 +2146,11 @@ config("default_warnings") { # Disables. "-Wno-missing-field-initializers", # "struct foo f = {0};" "-Wno-unused-parameter", # Unused function parameters. + + # An ABI compat warning we don't care about, https://crbug.com/1102157 + # TODO(thakis): Push this to the (few) targets that need it, + # instead of having a global flag. + "-Wno-psabi", ] cflags_cc += [ @@ -2140,15 +2158,6 @@ config("default_warnings") { "-Wno-invalid-offsetof", # offsetof on non-standard-layout type # (crbug.com/40285259) ] - - if (!is_nacl || is_nacl_saigo) { - cflags += [ - # An ABI compat warning we don't care about, https://crbug.com/1102157 - # TODO(thakis): Push this to the (few) targets that need it, - # instead of having a global flag. - "-Wno-psabi", - ] - } } if (is_clang) { @@ -2159,47 +2168,43 @@ config("default_warnings") { # which we no longer use. Check if it makes sense to remove # this as well. http://crbug.com/316352 "-Wno-unneeded-internal-declaration", + + # TODO(crbug.com/330524456): -Wcast-function-type is under -Wextra now. + "-Wno-cast-function-type", + + # TODO(crbug.com/40284799): Fix and re-enable. + "-Wno-thread-safety-reference-return", + + # TODO(crbug.com/376641662): Fix and re-enable. + "-Wno-nontrivial-memcall", ] - if (!is_nacl || is_nacl_saigo) { - if (is_win) { - # TODO(thakis): https://crbug.com/617318 - # Currently RBE can not handle case sensitiveness for windows well. - cflags += [ "-Wno-nonportable-include-path" ] - } + cflags_cc += [ + # TODO(crbug.com/328490295): Fix and re-enable for C flags. + "-Wenum-compare-conditional", - if (is_fuchsia) { - cflags_cc += [ - # TODO(crbug.com/42050603): fix and reenable - "-Wno-missing-field-initializers", - ] - } + # nullability-completeness is an on-by-default diagnostic in Clang, + # but we don't want it in chromium. + # These trigger build errors during transitional patches that will + # progressively roll out nullability annotations across third-party + # code. Once there is a widly used file-level pragma that + # nullability-completeness check can detect or an alternate check for + # annotation completeness, this warning exception can be removed. + "-Wno-nullability-completeness", - cflags += [ - # TODO(crbug.com/330524456): -Wcast-function-type is under -Wextra now. - "-Wno-cast-function-type", + # New clang warnings usually go here during a roll + ] - # TODO(crbug.com/40284799): Fix and re-enable. - "-Wno-thread-safety-reference-return", - - # TODO(crbug.com/376641662): Fix and re-enable. - "-Wno-nontrivial-memcall", - ] + if (is_win) { + # TODO(thakis): https://crbug.com/617318 + # Currently RBE can not handle case sensitiveness for windows well. + cflags += [ "-Wno-nonportable-include-path" ] + } + if (is_fuchsia) { cflags_cc += [ - # TODO(crbug.com/328490295): Fix and re-enable for C flags. - "-Wenum-compare-conditional", - - # nullability-completeness is an on-by-default diagnostic in Clang, - # but we don't want it in chromium. - # These trigger build errors during transitional patches that will - # progressively roll out nullability annotations across third-party - # code. Once there is a widly used file-level pragma that - # nullability-completeness check can detect or an alternate check for - # annotation completeness, this warning exception can be removed. - "-Wno-nullability-completeness", - - # New clang warnings usually go here during a roll + # TODO(crbug.com/42050603): fix and reenable + "-Wno-missing-field-initializers", ] } @@ -2246,6 +2251,13 @@ config("default_warnings") { if (cc_wrapper == "ccache" || cc_wrapper == "icecc") { cflags += [ "-Wno-gnu-line-marker" ] } + + if (is_wexit_time_destructors_default) { + # TODO(crbug.com/40031409): We are migrating towards making this warning + # enabled by default, and once that is completed, the warning + # should always be added for clang builds. + cflags += [ "-Wexit-time-destructors" ] + } } # TODO(crbug.com/354162568): Clean up and enable. @@ -2296,14 +2308,11 @@ config("prevent_unsafe_narrowing") { "-Wshorten-64-to-32", "-Wsign-compare", "-Wsign-conversion", + + # Avoid bugs of the form `if (size_t i = size; i >= 0; --i)` while + # fixing types to be sign-correct. + "-Wtautological-unsigned-zero-compare", ] - if (!is_nacl) { - cflags += [ - # Avoid bugs of the form `if (size_t i = size; i >= 0; --i)` while - # fixing types to be sign-correct. - "-Wtautological-unsigned-zero-compare", - ] - } } } @@ -2380,35 +2389,30 @@ config("chromium_code") { # Warn on unreachable code, including unreachable breaks and returns. # See https://crbug.com/346399#c148 for suppression strategies. "-Wunreachable-code-aggressive", + + # Warn on GNU extensions. + "-Wgnu", + + # TODO(crbug.com/357081796): Try to enable these. + "-Wno-gnu-anonymous-struct", + "-Wno-gnu-conditional-omitted-operand", + "-Wno-gnu-include-next", + "-Wno-gnu-label-as-value", + "-Wno-gnu-redeclared-enum", + "-Wno-gnu-statement-expression", + "-Wno-gnu-zero-variadic-macro-arguments", + "-Wno-zero-length-array", + + # Thread safety analysis. See base/thread_annotations.h and + # https://clang.llvm.org/docs/ThreadSafetyAnalysis.html + "-Wthread-safety", ] - # Thread safety analysis is broken under nacl: https://crbug.com/982423. - if (!is_nacl || is_nacl_saigo) { - cflags += [ - # Thread safety analysis. See base/thread_annotations.h and - # https://clang.llvm.org/docs/ThreadSafetyAnalysis.html - "-Wthread-safety", - - # Warn on GNU extensions. - "-Wgnu", - - # TODO(crbug.com/357081796): Try to enable these. - "-Wno-gnu-anonymous-struct", - "-Wno-gnu-conditional-omitted-operand", - "-Wno-gnu-include-next", - "-Wno-gnu-label-as-value", - "-Wno-gnu-redeclared-enum", - "-Wno-gnu-statement-expression", - "-Wno-gnu-zero-variadic-macro-arguments", - "-Wno-zero-length-array", - ] - - if (is_chromeos) { - cflags += [ "-Wno-gnu-offsetof-extensions" ] - } - if (is_ios) { - cflags += [ "-Wno-gnu-case-range" ] - } + if (is_chromeos) { + cflags += [ "-Wno-gnu-offsetof-extensions" ] + } + if (is_ios) { + cflags += [ "-Wno-gnu-case-range" ] } } @@ -2447,13 +2451,10 @@ config("no_chromium_code") { # Similarly, we're not going to fix all the C++11 narrowing issues in # third-party libraries. "-Wno-c++11-narrowing", + + # Disabled for similar reasons as -Wunused-variable. + "-Wno-unused-but-set-variable", ] - if (!is_nacl) { - cflags += [ - # Disabled for similar reasons as -Wunused-variable. - "-Wno-unused-but-set-variable", - ] - } } configs = [ ":default_warnings" ] @@ -2463,6 +2464,10 @@ config("no_chromium_code") { if (treat_warnings_as_errors && is_clang) { configs += [ ":treat_warnings_as_errors" ] } + + # A good chunk of non-Chromium code uses exit-time destructors, Abseil being + # one such case. + configs += [ ":no_exit_time_destructors" ] } # noshadowing ----------------------------------------------------------------- @@ -2470,9 +2475,7 @@ config("no_chromium_code") { # Allows turning -Wshadow on. config("noshadowing") { - # This flag has to be disabled for nacl because the nacl compiler is too - # strict about shadowing. - if (is_clang && (!is_nacl || is_nacl_saigo)) { + if (is_clang) { cflags = [ "-Wshadow" ] } } @@ -2537,7 +2540,7 @@ config("thin_archive") { "-T", "-s", ] - } else if ((is_posix && !is_nacl && (!is_apple || use_lld)) || is_fuchsia) { + } else if ((is_posix && (!is_apple || use_lld)) || is_fuchsia) { # The macOS and iOS default linker ld64 does not support reading thin # archives. arflags = [ @@ -2606,13 +2609,23 @@ config("unnecessary_virtual_specifier_warning") { # This will generate warnings when using Clang if code generates exit-time # destructors, which will slow down closing the program. -# TODO(thakis): Make this a blocklist instead, http://crbug.com/101600 +# TODO(crbug.com/40031409): Remove this config once -Wexit-time-destructors is +# being passed by default and shown to be working stable enough. config("wexit_time_destructors") { - if (is_clang) { + if (!is_wexit_time_destructors_default && is_clang) { cflags = [ "-Wexit-time-destructors" ] } } +# This config should be used to disable `Wexit-time-destructors` warnings in +# targets that are not ready to handle this warning, or that require such +# exclusion. +config("no_exit_time_destructors") { + if (is_clang) { + cflags = [ "-Wno-exit-time-destructors" ] + } +} + # Some code presumes that pointers to structures/objects are compatible # regardless of whether what they point to is already known to be valid. # gcc 4.9 and earlier had no way of suppressing this warning without @@ -2669,11 +2682,6 @@ if (is_win) { if (is_official_build) { common_optimize_on_ldflags += [ "/OPT:REF" ] # Remove unreferenced data. } - - if (is_clang) { - # See below. - common_optimize_on_cflags += [ "/clang:-fno-math-errno" ] - } } else { common_optimize_on_cflags = [] common_optimize_on_ldflags = [] @@ -2708,7 +2716,7 @@ if (is_win) { "-fdata-sections", "-ffunction-sections", ] - if ((!is_nacl || is_nacl_saigo) && is_clang) { + if (is_clang) { # We don't care about unique section names, this makes object files a bit # smaller. common_optimize_on_cflags += [ "-fno-unique-section-names" ] @@ -2725,14 +2733,6 @@ if (is_win) { common_optimize_on_ldflags += [ "-Wl,--gc-sections" ] } - - # We cannot rely on errno being set after math functions, - # especially since glibc does not set it. Thus, use -fno-math-errno - # so that the compiler knows it can inline math functions. - # Note that this is different from -ffast-math (even though -ffast-math - # implies -fno-math-errno), which also allows a number of unsafe - # optimizations. - common_optimize_on_cflags += [ "-fno-math-errno" ] } config("default_stack_frames") { @@ -2861,29 +2861,17 @@ config("no_optimize") { # -Os for select targets on platforms that use optimize_for_size. No-op # elsewhere. config("optimize_max") { - if (is_nacl && is_nacl_irt) { - # The NaCl IRT is a special case and always wants its own config. - # Various components do: - # if (!is_debug) { - # configs -= [ "//build/config/compiler:default_optimization" ] - # configs += [ "//build/config/compiler:optimize_max" ] - # } - # So this config has to have the selection logic just like - # "default_optimization", below. - configs = [ "//build/config/nacl:irt_optimize" ] + ldflags = common_optimize_on_ldflags + if (is_win) { + # Favor speed over size, /O2 must be before the common flags. + # /O2 implies /Ot, /Oi, and /GF. + cflags = [ "/O2" ] + common_optimize_on_cflags + } else if (optimize_for_fuzzing) { + cflags = [ "-O1" ] + common_optimize_on_cflags } else { - ldflags = common_optimize_on_ldflags - if (is_win) { - # Favor speed over size, /O2 must be before the common flags. - # /O2 implies /Ot, /Oi, and /GF. - cflags = [ "/O2" ] + common_optimize_on_cflags - } else if (optimize_for_fuzzing) { - cflags = [ "-O1" ] + common_optimize_on_cflags - } else { - cflags = [ "-O2" ] + common_optimize_on_cflags - } - rustflags = [ "-Copt-level=3" ] + cflags = [ "-O2" ] + common_optimize_on_cflags } + rustflags = [ "-Copt-level=3" ] } # This config can be used to override the default settings for per-component @@ -2894,32 +2882,20 @@ config("optimize_max") { # TODO(crbug.com/41259697) - rework how all of these configs are related # so that we don't need this disclaimer. config("optimize_speed") { - if (is_nacl && is_nacl_irt) { - # The NaCl IRT is a special case and always wants its own config. - # Various components do: - # if (!is_debug) { - # configs -= [ "//build/config/compiler:default_optimization" ] - # configs += [ "//build/config/compiler:optimize_max" ] - # } - # So this config has to have the selection logic just like - # "default_optimization", below. - configs = [ "//build/config/nacl:irt_optimize" ] - } else { - ldflags = common_optimize_on_ldflags - if (is_win) { - # Favor speed over size, /O2 must be before the common flags. - # /O2 implies /Ot, /Oi, and /GF. - cflags = [ "/O2" ] + common_optimize_on_cflags - if (is_clang) { - cflags += [ "/clang:-O3" ] - } - } else if (optimize_for_fuzzing) { - cflags = [ "-O1" ] + common_optimize_on_cflags - } else { - cflags = [ "-O3" ] + common_optimize_on_cflags + ldflags = common_optimize_on_ldflags + if (is_win) { + # Favor speed over size, /O2 must be before the common flags. + # /O2 implies /Ot, /Oi, and /GF. + cflags = [ "/O2" ] + common_optimize_on_cflags + if (is_clang) { + cflags += [ "/clang:-O3" ] } - rustflags = [ "-Copt-level=3" ] + } else if (optimize_for_fuzzing) { + cflags = [ "-O1" ] + common_optimize_on_cflags + } else { + cflags = [ "-O3" ] + common_optimize_on_cflags } + rustflags = [ "-Copt-level=3" ] } config("optimize_fuzzing") { @@ -2932,11 +2908,7 @@ config("optimize_fuzzing") { # The default optimization applied to all targets. This will be equivalent to # either "optimize" or "no_optimize", depending on the build flags. config("default_optimization") { - if (is_nacl && is_nacl_irt) { - # The NaCl IRT is a special case and always wants its own config. - # It gets optimized the same way regardless of the type of build. - configs = [ "//build/config/nacl:irt_optimize" ] - } else if (is_debug) { + if (is_debug) { configs = [ ":no_optimize" ] } else if (optimize_for_fuzzing) { assert(!is_win, "Fuzzing optimize level not supported on Windows") @@ -2992,10 +2964,10 @@ config("afdo") { cflags = [] if (clang_emit_debug_info_for_profiling) { # Add the following flags to generate debug info for profiling. - cflags += [ "-gline-tables-only" ] - if (!is_nacl) { - cflags += [ "-fdebug-info-for-profiling" ] - } + cflags += [ + "-gline-tables-only", + "-fdebug-info-for-profiling", + ] } if (_clang_sample_profile != "") { assert(chrome_pgo_phase == 0, "AFDO can't be used in PGO builds") @@ -3104,7 +3076,7 @@ config("symbols") { # On aix -gdwarf causes linker failures due to thread_local variables. # On zos -gdwarf causes INSUFFICIENT ABOVE THE LINE STORAGE WAS AVAILABLE. - if (!is_nacl && current_os != "aix" && current_os != "zos") { + if (current_os != "aix" && current_os != "zos") { if (use_dwarf5) { cflags += [ "-gdwarf-5" ] rustflags += [ "-Zdwarf-version=5" ] @@ -3123,18 +3095,11 @@ config("symbols") { } } - # The gcc-based nacl compilers don't support -fdebug-compilation-dir (see - # elsewhere in this file), so they can't have build-dir-independent output. - # Moreover pnacl does not support newer flags such as -fdebug-prefix-map - # Disable symbols for nacl object files to get deterministic, - # build-directory-independent output. - # Keeping -g2 for saigo as it's the only toolchain whose artifacts that are - # part of chromium release (other nacl toolchains are used only for tests). - if ((!is_nacl || is_nacl_saigo) && current_os != "zos") { + if (current_os != "zos") { cflags += [ "-g2" ] } - if (!is_nacl && is_clang && !is_tsan && !is_asan) { + if (is_clang && !is_tsan && !is_asan) { # gcc generates dwarf-aranges by default on -g1 and -g2. On clang it has # to be manually enabled. # @@ -3154,24 +3119,13 @@ config("symbols") { asmflags = cflags ldflags = [] - # Split debug info with all thinlto builds except nacl and apple. + # Split debug info with all thinlto builds except apple. # thinlto requires -gsplit-dwarf in ldflags. - if (use_debug_fission && use_thin_lto && !is_nacl && !is_apple) { + if (use_debug_fission && use_thin_lto && !is_apple) { ldflags += [ "-gsplit-dwarf" ] } - # TODO(thakis): Figure out if there's a way to make this go for 32-bit, - # currently we get "warning: - # obj/native_client/src/trusted/service_runtime/sel_asm/nacl_switch_32.o: - # DWARF info may be corrupt; offsets in a range list entry are in different - # sections" there. Maybe just a bug in nacl_switch_32.S. - _enable_gdb_index = - symbol_level == 2 && !is_apple && !is_nacl && current_cpu != "x86" && - current_os != "zos" && use_lld && !is_wasm && - # Disable on non-fission 32-bit Android because it pushes - # libcomponents_unittests over the 4gb size limit. - !(is_android && !use_debug_fission && current_cpu != "x64" && - current_cpu != "arm64") + _enable_gdb_index = symbol_level == 2 && !is_apple && use_lld && !is_wasm if (_enable_gdb_index) { if (is_clang) { # This flag enables the GNU-format pubnames and pubtypes sections, @@ -3184,14 +3138,14 @@ config("symbols") { } } - # Compress debug on 32-bit ARM to stay under 4GB file size limit. + # Compress debug on 32-bit 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_win && + if (symbol_level == 2 && !use_debug_fission && !is_win && (current_cpu == "arm" || current_cpu == "x86")) { configs += [ "//build/config:compress_debug_sections" ] } - if (is_clang && !is_nacl && is_win && !is_component_build) { + if (is_clang && is_win && !is_component_build) { # Remove unreferenced methods to reduce type info in symbols. # See: https://github.com/llvm/llvm-project/pull/87018. # The downside with this flag is precisely that: Unreferenced methods get @@ -3204,7 +3158,7 @@ config("symbols") { cflags += [ "-gomit-unreferenced-methods" ] } - if (is_clang && (!is_nacl || is_nacl_saigo)) { + if (is_clang) { if (is_apple) { # TODO(crbug.com/40117949): Investigate missing debug info on mac. # Make sure we don't use constructor homing on mac. @@ -3264,7 +3218,7 @@ config("minimal_symbols") { # TODO(thakis): Remove this once mac_deployment_target is 10.11. cflags += [ "-gdwarf-4" ] rustflags += [ "-Zdwarf-version=4" ] - } else if (!use_dwarf5 && !is_nacl && current_os != "aix") { + } else if (!use_dwarf5 && current_os != "aix") { # On aix -gdwarf causes linker failures due to thread_local variables. # Recent clang versions default to DWARF5 on Linux, and Android is about # to switch. TODO: Adopt that in controlled way. @@ -3272,23 +3226,14 @@ config("minimal_symbols") { rustflags += [ "-Zdwarf-version=4" ] } - if (use_dwarf5 && !is_nacl) { + if (use_dwarf5) { cflags += [ "-gdwarf-5" ] rustflags += [ "-Zdwarf-version=5" ] } - # The gcc-based nacl compilers don't support -fdebug-compilation-dir (see - # elsewhere in this file), so they can't have build-dir-independent output. - # Moreover pnacl does not support newer flags such as -fdebug-prefix-map - # Disable symbols for nacl object files to get deterministic, - # build-directory-independent output. - # Keeping -g1 for saigo as it's the only toolchain whose artifacts that are - # part of chromium release (other nacl toolchains are used only for tests). - if (!is_nacl || is_nacl_saigo) { - cflags += [ "-g1" ] - } + cflags += [ "-g1" ] - if (!is_nacl && is_clang && !is_tsan && !is_asan && current_os != "zos") { + if (is_clang && !is_tsan && !is_asan && current_os != "zos") { # See comment for -gdwarf-aranges in config("symbols"). cflags += [ "-gdwarf-aranges" ] } @@ -3397,7 +3342,7 @@ if (is_android) { # Initialize all variables on the stack if needed. config("default_init_stack_vars") { cflags = [] - if (init_stack_vars && is_clang && !is_nacl && !using_sanitizer) { + if (init_stack_vars && is_clang && !using_sanitizer) { if (init_stack_vars_zero) { cflags += [ "-ftrivial-auto-var-init=zero" ] } else { diff --git a/naiveproxy/src/build/config/compiler/compiler.gni b/naiveproxy/src/build/config/compiler/compiler.gni index e80fb44fa6..babd5a12fa 100644 --- a/naiveproxy/src/build/config/compiler/compiler.gni +++ b/naiveproxy/src/build/config/compiler/compiler.gni @@ -32,6 +32,9 @@ declare_args() { # The default linker everywhere else. use_lld = is_clang && current_os != "zos" + # If false, build using C++20; otherwise, build using C++23. + use_cxx23 = false + # If true, optimize for size. # Default to favoring speed over size for platforms not listed below. optimize_for_size = @@ -45,6 +48,12 @@ declare_args() { # With GCC, warnings in no-Chromium code are always not treated as errors. treat_warnings_as_errors = true + # How clang should report warnings, either false to report in the usual + # manner, or true to add source range information to the diagnostics in + # a form suitable for subsequent processing with scripts. With GCC, or + # on Windows, the warning format is not affected. + diagnostics_print_source_range_info = false + # How many symbols to include in the build. This affects the performance of # the build since the symbols are large and dealing with them is slow. # 2 means regular build with symbols. @@ -126,9 +135,6 @@ declare_args() { use_ml_inliner = host_os == "linux" && is_android && !llvm_android_mainline # https://crbug.com/1468680 - # Set to true to use the android unwinder V2 implementation. - use_android_unwinder_v2 = true - # Whether we should consider the profile we're using to be accurate. Accurate # profiles have the benefit of (potentially substantial) binary size # reductions, by instructing the compiler to optimize cold and uncovered @@ -243,7 +249,7 @@ enable_arm_cfi_table = is_android && !is_component_build && current_cpu == "arm" # deterministic builds to reduce compile times, so this is less relevant for # official builders. strip_absolute_paths_from_debug_symbols_default = - is_android || is_fuchsia || is_nacl || (is_win && use_lld) || is_linux || + is_android || is_fuchsia || (is_win && use_lld) || is_linux || is_chromeos || (is_apple && !enable_dsyms) # If the platform uses stripped absolute paths by default, then we don't expose @@ -306,7 +312,7 @@ if (symbol_level == -1) { # info or variable info, so we can leave that out to speed up the build. # Sanitizers also require symbols for filename suppressions to work. symbol_level = 1 - } else if ((!is_nacl && !is_linux && !is_chromeos && !is_fuchsia && + } else if ((!is_linux && !is_chromeos && !is_fuchsia && current_os != "aix") || is_debug || is_castos || is_cast_android) { # Linux builds slower by having symbols as part of the target binary, diff --git a/naiveproxy/src/build/config/compiler/pgo/BUILD.gn b/naiveproxy/src/build/config/compiler/pgo/BUILD.gn index ac98e53b6b..546c99aac3 100644 --- a/naiveproxy/src/build/config/compiler/pgo/BUILD.gn +++ b/naiveproxy/src/build/config/compiler/pgo/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/config/chrome_build.gni") import("//build/config/clang/clang.gni") import("//build/config/compiler/compiler.gni") import("//build/config/compiler/pgo/pgo.gni") @@ -14,7 +15,7 @@ config("pgo_instrumentation_flags") { # Only add flags when chrome_pgo_phase == 1, so that variables we would use # are not required to be defined when we're not actually using PGO. - if (chrome_pgo_phase == 1 && is_clang && !is_nacl && is_a_target_toolchain) { + if (chrome_pgo_phase == 1 && is_clang && is_a_target_toolchain) { cflags = [ "-fprofile-generate" ] if (temporal_pgo_profile) { cflags += [ @@ -37,7 +38,7 @@ config("pgo_optimization_flags") { # Only add flags when chrome_pgo_phase == 2, so that variables we would use # are not required to be defined when we're not actually using PGO. - if (chrome_pgo_phase == 2 && is_clang && !is_nacl && is_a_target_toolchain) { + if (chrome_pgo_phase == 2 && is_clang && is_a_target_toolchain) { _pgo_target = "" # There are txt files used by //tools/update_pgo_profiles.py to decide which @@ -63,7 +64,9 @@ config("pgo_optimization_flags") { _pgo_target = "linux" } else if (is_android) { # Use |current_cpu| and not |target_cpu|; for Android we may built both. - if (current_cpu == "arm64") { + if (is_desktop_android && current_cpu == "x64") { + _pgo_target = "android-desktop-x64" + } else if (current_cpu == "arm64") { _pgo_target = "android-arm64" } else { _pgo_target = "android-arm32" @@ -98,6 +101,8 @@ config("pgo_optimization_flags") { inputs = [ "//chrome/build/android-arm32.pgo.txt" ] } else if (_pgo_target == "android-arm64") { inputs = [ "//chrome/build/android-arm64.pgo.txt" ] + } else if (_pgo_target == "android-desktop-x64") { + inputs = [ "//chrome/build/android-desktop-x64.pgo.txt" ] } if (_pgo_target != "" && pgo_data_path == "") { @@ -125,6 +130,13 @@ config("pgo_optimization_flags") { } assert(pgo_data_path != "", "Please set pgo_data_path to point at the profile data") + + # Ensure that the actual PGO profile that is used in the build is also + # listed in inputs in addition to any sha1 .txt files. This way the object + # files are rebuilt whenever the .txt files change or whenever the actual + # profile changes. + inputs += [ pgo_data_path ] + cflags = [ "-fprofile-use=" + rebase_path(pgo_data_path, root_build_dir), diff --git a/naiveproxy/src/build/config/freetype/BUILD.gn b/naiveproxy/src/build/config/freetype/BUILD.gn index 88a9c59f0a..981ad9956e 100644 --- a/naiveproxy/src/build/config/freetype/BUILD.gn +++ b/naiveproxy/src/build/config/freetype/BUILD.gn @@ -9,6 +9,6 @@ group("freetype") { if (use_system_freetype) { public_configs = [ "//build/linux:freetype_from_pkgconfig" ] } else { - public_deps = [ "//third_party:freetype_harfbuzz" ] + public_deps = [ "//third_party/freetype" ] } } diff --git a/naiveproxy/src/build/config/fuchsia/BUILD.gn b/naiveproxy/src/build/config/fuchsia/BUILD.gn index b6ef61df75..8cc07774c1 100644 --- a/naiveproxy/src/build/config/fuchsia/BUILD.gn +++ b/naiveproxy/src/build/config/fuchsia/BUILD.gn @@ -3,6 +3,7 @@ # found in the LICENSE file. import("//build/config/clang/clang.gni") +import("//build/config/fuchsia/config.gni") import("//build/config/fuchsia/generate_runner_scripts.gni") import("//build/config/fuchsia/gn_configs.gni") @@ -21,6 +22,10 @@ config("compiler") { "-fexperimental-relative-c++-abi-vtables", ] cflags_cc = [ "-fexperimental-relative-c++-abi-vtables" ] + + if (is_web_engine) { + defines = [ "IS_WEB_ENGINE" ] + } } # Files required to run on Fuchsia on isolated swarming clients. diff --git a/naiveproxy/src/build/config/fuchsia/generate_runner_scripts.gni b/naiveproxy/src/build/config/fuchsia/generate_runner_scripts.gni index 2c7b54ab39..4ead42b87f 100644 --- a/naiveproxy/src/build/config/fuchsia/generate_runner_scripts.gni +++ b/naiveproxy/src/build/config/fuchsia/generate_runner_scripts.gni @@ -214,10 +214,6 @@ template("fuchsia_test_runner") { executable_args += [ package_name ] - if (defined(invoker.use_test_server) && invoker.use_test_server) { - executable_args += [ "--enable-test-server" ] - } - if (default_fuchsia_device_node_name != "") { executable_args += [ "--target-id", diff --git a/naiveproxy/src/build/config/gclient_args.gni b/naiveproxy/src/build/config/gclient_args.gni index 6ac11b19b1..44b02dc4c8 100644 --- a/naiveproxy/src/build/config/gclient_args.gni +++ b/naiveproxy/src/build/config/gclient_args.gni @@ -10,6 +10,7 @@ checkout_mutter = false checkout_openxr = false checkout_src_internal = false checkout_src_internal_infra = false +checkout_clusterfuzz_data = false cros_boards = "" cros_boards_with_qemu_images = "" generate_location_tags = true \ No newline at end of file diff --git a/naiveproxy/src/build/config/ios/BUILD.gn b/naiveproxy/src/build/config/ios/BUILD.gn index 6a98460e80..9cd1fb75e0 100644 --- a/naiveproxy/src/build/config/ios/BUILD.gn +++ b/naiveproxy/src/build/config/ios/BUILD.gn @@ -67,7 +67,7 @@ config("compiler") { swiftflags += [ "-swift-version", - "5", + "6", ] cflags_objcc = [ diff --git a/naiveproxy/src/build/config/ios/ios_sdk_overrides.gni b/naiveproxy/src/build/config/ios/ios_sdk_overrides.gni index 2816b8a672..03f747901d 100644 --- a/naiveproxy/src/build/config/ios/ios_sdk_overrides.gni +++ b/naiveproxy/src/build/config/ios/ios_sdk_overrides.gni @@ -5,12 +5,18 @@ # This file contains arguments that subprojects may choose to override. It # asserts that those overrides are used, to prevent unused args warnings. +import("//build/config/apple/mobile_config.gni") import("//build/config/features.gni") declare_args() { # Version of iOS that we're targeting. if (use_blink) { - ios_deployment_target = "18.4" + if (target_platform == "iphoneos") { + ios_deployment_target = "26.0" + } else { + # tvOS requires at least SDK version 17.4. + ios_deployment_target = "17.4" + } } else { ios_deployment_target = "17.0" } @@ -19,6 +25,6 @@ declare_args() { # Always assert that ios_deployment_target is used on non-iOS platforms to # prevent unused args warnings. if (!is_ios) { - assert(ios_deployment_target == "17.0" || ios_deployment_target == "18.4" || - true) + assert(ios_deployment_target == "17.0" || ios_deployment_target == "17.4" || + ios_deployment_target == "26.0" || true) } diff --git a/naiveproxy/src/build/config/ios/ios_test_runner_wrapper.gni b/naiveproxy/src/build/config/ios/ios_test_runner_wrapper.gni index 6fac03ff47..6ec79acb3f 100644 --- a/naiveproxy/src/build/config/ios/ios_test_runner_wrapper.gni +++ b/naiveproxy/src/build/config/ios/ios_test_runner_wrapper.gni @@ -68,9 +68,9 @@ template("ios_test_runner_wrapper") { _rebased_xcode_path = rebase_path("//Xcode.app", root_build_dir) _rebased_ios_runtime_cache_prefix = rebase_path("//Runtime-ios-", root_build_dir) + _rebased_out_dir = + rebase_path("${root_build_dir}/ios-test-results", root_build_dir) - # --out-dir argument is specified in gn_isolate_map.pyl because - # ${ISOLATED_OUTDIR} doesn't get resolved through this wrapper. executable_args += [ "--xcode-path", "@WrappedPath(${_rebased_xcode_path})", @@ -78,6 +78,13 @@ template("ios_test_runner_wrapper") { "@WrappedPath(${_rebased_mac_toolchain})", "--runtime-cache-prefix", "@WrappedPath(${_rebased_ios_runtime_cache_prefix})", + + # To make the generated script easier to run locally, tentatively set an + # `--out-dir` at build time. If the command line contains multiple + # `--out-dir`s, the last option wins, so the bots can override this at + # runtime when `${ISOLATED_OUTDIR}` is resolved. + "--out-dir", + "@WrappedPath(${_rebased_out_dir})", ] # Default retries to 3 diff --git a/naiveproxy/src/build/config/ios/rules.gni b/naiveproxy/src/build/config/ios/rules.gni index d7fe32f7f1..e9ddde5f8c 100644 --- a/naiveproxy/src/build/config/ios/rules.gni +++ b/naiveproxy/src/build/config/ios/rules.gni @@ -465,6 +465,7 @@ template("ios_app_bundle") { _info_plist_path, ] sources += ios_mobileprovision_files + sources += [ ios_mobileprovision_files_filelist ] outputs = [ _generate_entitlements_output ] @@ -472,10 +473,8 @@ template("ios_app_bundle") { "generate-entitlements", "-e=" + rebase_path(_entitlements_path, root_build_dir), "-p=" + rebase_path(_info_plist_path, root_build_dir), + "-M=" + rebase_path(ios_mobileprovision_files_filelist, root_build_dir), ] - foreach(mobileprovision, ios_mobileprovision_files) { - args += [ "-m=" + rebase_path(mobileprovision, root_build_dir) ] - } args += rebase_path(outputs, root_build_dir) } @@ -1284,7 +1283,6 @@ template("ios_xctest_test") { # extra_system_frameworks. extra_system_frameworks = [ "$ios_sdk_platform_path/Developer/Library/Frameworks/XCTest.framework", - "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTAutomationSupport.framework", "$ios_sdk_platform_path/Developer/usr/lib/libXCTestBundleInject.dylib", ] @@ -1436,7 +1434,6 @@ template("ios_xcuitest_test_runner_bundle") { # extra_system_frameworks. extra_system_frameworks = [ "$ios_sdk_platform_path/Developer/Library/Frameworks/XCTest.framework", - "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTAutomationSupport.framework", ] # Xcode 13 now depends on XCTestCore. To keep things future proof, copy over diff --git a/naiveproxy/src/build/config/locales.gni b/naiveproxy/src/build/config/locales.gni index 428136f8fc..4d503e1523 100644 --- a/naiveproxy/src/build/config/locales.gni +++ b/naiveproxy/src/build/config/locales.gni @@ -16,7 +16,7 @@ declare_args() { # pass the "--translate-genders" flag into GRIT to generate 4 translation # files per locale ("", "_FEMININE", "_MASCULINE", "_NEUTER") instead of # one. - translate_genders = false + translate_genders = !is_ios } # The following additional platform specific lists are created: diff --git a/naiveproxy/src/build/config/mac/BUILD.gn b/naiveproxy/src/build/config/mac/BUILD.gn index 66ca06b7e8..d9218b3ca1 100644 --- a/naiveproxy/src/build/config/mac/BUILD.gn +++ b/naiveproxy/src/build/config/mac/BUILD.gn @@ -37,6 +37,12 @@ config("compiler") { ldflags = common_mac_flags + # ld64 defaults to fixup chains on macOS 12+ when targeting arm64 and on + # macOS 13+ when targeting x86_64. + # ld64.lld currently defaults to it on macOS 13+. + # Force it on; for Chromium it should work on macOS 12 even on x86_64. + ldflags += [ "-Wl,-fixup_chains" ] + if (save_unstripped_output) { ldflags += [ "-Wcrl,unstripped," + rebase_path(root_out_dir) ] } @@ -60,6 +66,20 @@ config("runtime_library") { asmflags = common_flags cflags = common_flags ldflags = common_flags + + # Record the SDK as 26.0, even though that may not be the SDK in use. This + # convinces macOS 26 (and its betas) to enable new features gated on that SDK + # being used at build time, before actually migrating to that SDK (which is + # currently in beta, and which we wouldn’t normally use until released). On + # macOS < 26, this white lie is a no-op, as older versions won’t change + # behaviors if this field is set to anything newer than they’re aware of. On + # macOS 26, this enables Liquid Glass, and disables the undesirable + # SystemVersionCompat OS version reporting, where macOS 26 calls itself macOS + # 16. + # + # TODO(https://crbug.com/423933062): Remove this once the macOS 26 SDK is in + # use. + ldflags += [ "-Wl,-platform_version,macos,$mac_deployment_target,26.0" ] } # On Mac, this is used for everything except static libraries. diff --git a/naiveproxy/src/build/config/mac/mac_sdk.gni b/naiveproxy/src/build/config/mac/mac_sdk.gni index 786b566786..94880f8c88 100644 --- a/naiveproxy/src/build/config/mac/mac_sdk.gni +++ b/naiveproxy/src/build/config/mac/mac_sdk.gni @@ -46,14 +46,14 @@ declare_args() { mac_sdk_name = "macosx" # The SDK version used when making official builds. This is a single exact - # version, not a minimum. If this version isn't available official builds + # version, not a minimum. If this version isn't available, official builds # will fail. - mac_sdk_official_version = "15.4" + mac_sdk_official_version = "15.5" # The SDK build version used when making official builds. This is a single # exact version found at "System/Library/CoreServices/SystemVersion.plist" # inside the SDK. - mac_sdk_official_build_version = "24E241" + mac_sdk_official_build_version = "24F74" # Production builds should use hermetic Xcode. If you want to do production # builds with system Xcode to test new SDKs, set this. diff --git a/naiveproxy/src/build/config/nacl/BUILD.gn b/naiveproxy/src/build/config/nacl/BUILD.gn deleted file mode 100644 index 77b04d71b1..0000000000 --- a/naiveproxy/src/build/config/nacl/BUILD.gn +++ /dev/null @@ -1,132 +0,0 @@ -# Copyright (c) 2014 The Native Client Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/nacl/config.gni") - -# Native Client Definitions -config("nacl_defines") { - if (is_linux || is_chromeos || is_android || is_nacl) { - defines = [ - "_POSIX_C_SOURCE=199506", - "_XOPEN_SOURCE=600", - "_GNU_SOURCE=1", - "__STDC_LIMIT_MACROS=1", - ] - } else if (is_win) { - defines = [ "__STDC_LIMIT_MACROS=1" ] - } - - if (current_cpu == "pnacl") { - # TODO: Remove the following definition once NACL_BUILD_ARCH and - # NACL_BUILD_SUBARCH are defined by the PNaCl toolchain. - defines += [ "NACL_BUILD_ARCH=pnacl" ] - } -} - -config("nexe_defines") { - defines = [ - "DYNAMIC_ANNOTATIONS_ENABLED=1", - "DYNAMIC_ANNOTATIONS_PREFIX=NACL_", - ] -} - -config("nacl_warnings") { - if (is_win) { - # Some NaCl code uses forward declarations of static const variables, - # with initialized definitions later on. (The alternative would be - # many, many more forward declarations of everything used in that - # const variable's initializer before the definition.) The Windows - # compiler doesn't see that there is an initializer later in the file, - # and warns about the forward declaration. - cflags = [ "/wd4132" ] - } -} - -config("nacl_static_libstdc++") { - # The sysroot of linux x86 bots can have a different version of libstdc++ - # than the one that is on the bots natively. Linking dynamically against - # libstdc++ can then lead to linking against symbols that are not found when - # running the executable. - # Therefore, link statically instead. - if (is_linux && current_cpu == "x86") { - ldflags = [ "-static-libstdc++" ] - } -} - -# The base target that all targets in the NaCl build should depend on. -# This allows configs to be modified for everything in the NaCl build, even when -# the NaCl build is composed into the Chrome build. (GN has no functionality to -# add flags to everything in //native_client, having a base target works around -# that limitation.) -source_set("nacl_base") { - public_configs = [ - ":nacl_defines", - ":nacl_warnings", - ":nacl_static_libstdc++", - ] - if (current_os == "nacl") { - public_configs += [ ":nexe_defines" ] - } -} - -config("compiler") { - configs = [] - cflags = [] - ldflags = [] - libs = [] - - if (is_clang && current_cpu != "pnacl") { - # -no-integrated-as is the default in nacl-clang for historical - # compatibility with inline assembly code and so forth. But there - # are no such cases in Chromium code, and -integrated-as is nicer in - # general. Moreover, the IRT must be built using LLVM's assembler - # on x86-64 to preserve sandbox base address hiding. Use it - # everywhere for consistency (and possibly quicker builds). - cflags += [ "-integrated-as" ] - } - - asmflags = cflags -} - -config("compiler_codegen") { - cflags = [] - - if (is_nacl_irt) { - cflags += [ - # A debugger should be able to unwind IRT call frames. This is - # the default behavior on x86-64 and when compiling C++ with - # exceptions enabled; the change is for the benefit of x86-32 C. - # The frame pointer is unnecessary when unwind tables are used. - "-fasynchronous-unwind-tables", - "-fomit-frame-pointer", - ] - - if (current_cpu == "x86") { - # The x86-32 IRT needs to be callable with an under-aligned - # stack; so we disable SSE instructions, which can fault on - # misaligned addresses. See - # https://code.google.com/p/nativeclient/issues/detail?id=3935 - cflags += [ - "-mstackrealign", - "-mno-sse", - ] - } - } - - asmflags = cflags -} - -config("irt_optimize") { - cflags = [ - # Optimize for space, keep the IRT nexe small. - "-Os", - - # These are omitted from non-IRT libraries to keep the libraries - # themselves small. - "-ffunction-sections", - "-fdata-sections", - ] - - ldflags = [ "-Wl,--gc-sections" ] -} diff --git a/naiveproxy/src/build/config/nacl/config.gni b/naiveproxy/src/build/config/nacl/config.gni deleted file mode 100644 index c8062b41a8..0000000000 --- a/naiveproxy/src/build/config/nacl/config.gni +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright 2015 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -declare_args() { - # Native Client supports multiple toolchains: - # - nacl_glibc, based on gcc and glibc. - # - pnacl_newlib, based on llvm 3.7 and newlib (default). - # - saigo_newlib, based on llvm 12+ and newlib. - - # True if nacl_glibc is used. - is_nacl_glibc = false - - # True if saigo_newlib is used. - is_nacl_saigo = false -} - -nacl_toolchain_dir = "//native_client/toolchain/${host_os}_x86" - -if (is_nacl_glibc) { - if (current_cpu == "x86" || current_cpu == "x64") { - nacl_toolchain_package = "nacl_x86_glibc" - } else if (current_cpu == "arm") { - nacl_toolchain_package = "nacl_arm_glibc" - } -} else { - nacl_toolchain_package = "pnacl_newlib" -} - -if (current_cpu == "pnacl") { - _nacl_tuple = "pnacl" -} else if (current_cpu == "x86" || current_cpu == "x64") { - _nacl_tuple = "x86_64-nacl" -} else if (current_cpu == "arm") { - _nacl_tuple = "arm-nacl" -} else if (current_cpu == "mipsel") { - _nacl_tuple = "mipsel-nacl" -} else { - # In order to allow this file to be included unconditionally - # from build files that can't depend on //components/nacl/features.gni - # we provide a dummy value that should be harmless if nacl isn't needed. - # If nacl *is* needed this will result in a real error, indicating that - # people need to set the toolchain path correctly. - _nacl_tuple = "unknown" -} - -nacl_toolchain_bindir = "${nacl_toolchain_dir}/${nacl_toolchain_package}/bin" -nacl_toolchain_tooldir = - "${nacl_toolchain_dir}/${nacl_toolchain_package}/${_nacl_tuple}" -nacl_toolprefix = "${nacl_toolchain_bindir}/${_nacl_tuple}-" - -nacl_irt_toolchain = "//build/toolchain/nacl:irt_" + current_cpu -is_nacl_irt = current_toolchain == nacl_irt_toolchain diff --git a/naiveproxy/src/build/config/nacl/host_toolchain.gni b/naiveproxy/src/build/config/nacl/host_toolchain.gni deleted file mode 100644 index 6bb2221ae6..0000000000 --- a/naiveproxy/src/build/config/nacl/host_toolchain.gni +++ /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. - -default_nacl_bootstrap_compiler = "g++" -if (default_toolchain == "//build/toolchain/cros:target") { - import("//build/toolchain/cros_toolchain.gni") - if (target_cpu == "arm64" && current_cpu == "arm") { - default_nacl_bootstrap_compiler = cros_nacl_helper_arm32_cxx - } else { - default_nacl_bootstrap_compiler = cros_target_cxx - } -} else if (current_cpu == "arm" && !is_android) { - default_nacl_bootstrap_compiler = "arm-linux-gnueabihf-g++" -} else if (current_cpu == "mipsel" && !is_android) { - default_nacl_bootstrap_compiler = "mipsel-linux-gnu-g++" -} - -declare_args() { - # The compiler for the trusted nacl_helper_bootstrap binary. - nacl_bootstrap_compiler = default_nacl_bootstrap_compiler -} diff --git a/naiveproxy/src/build/config/nacl/rules.gni b/naiveproxy/src/build/config/nacl/rules.gni deleted file mode 100644 index a15d32622c..0000000000 --- a/naiveproxy/src/build/config/nacl/rules.gni +++ /dev/null @@ -1,130 +0,0 @@ -# Copyright 2015 The Native Client Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/nacl/config.gni") - -# Generate a nmf file -# -# Native Client Manifest (nmf) is a JSON file that tells the browser where to -# download and load Native Client application files and libraries. -# -# Variables: -# executables: .nexe/.pexe/.bc executables to generate nmf for -# lib_prefix: path to prepend to shared libraries in the nmf -# nmf: the name and the path of the output file -# nmfflags: additional flags for the nmf generator -# stage_dependencies: directory for staging libraries -template("generate_nmf") { - assert(defined(invoker.executables), "Must define executables") - assert(defined(invoker.nmf), "Must define nmf") - - action(target_name) { - forward_variables_from(invoker, - [ - "deps", - "data_deps", - "executables", - "lib_prefix", - "nmf", - "nmfflags", - "public_deps", - "stage_dependencies", - "testonly", - "visibility", - ]) - if (!defined(nmfflags)) { - nmfflags = [] - } - - # TODO(phosek): Remove this conditional once - # https://bugs.chromium.org/p/nativeclient/issues/detail?id=4339 is - # resolved. - if (current_cpu == "pnacl") { - objdump = rebase_path("${nacl_toolchain_bindir}/x86_64-nacl-objdump") - } else { - objdump = rebase_path("${nacl_toolprefix}objdump") - } - if (host_os == "win") { - objdump += ".exe" - } - - script = "//native_client_sdk/src/tools/create_nmf.py" - inputs = [ objdump ] - sources = executables - outputs = [ nmf ] - if (is_nacl_glibc) { - if (defined(stage_dependencies)) { - nmfflags += [ "--stage-dependencies=" + - rebase_path(stage_dependencies, root_build_dir) ] - lib_path = stage_dependencies - } else { - lib_path = root_build_dir - } - if (defined(lib_prefix)) { - nmfflags += [ "--lib-prefix=" + lib_prefix ] - lib_path += "/${lib_prefix}" - } - - # Starts empty so the code below can use += everywhere. - data = [] - - nmfflags += - [ "--library-path=" + rebase_path(root_out_dir, root_build_dir) ] - - # NOTE: There is no explicit dependency for the lib directory - # (lib32 and lib64 for x86/x64) created in the product directory. - # They are created as a side-effect of nmf creation. - if (current_cpu != "x86" && current_cpu != "x64") { - nmfflags += - [ "--library-path=" + - rebase_path("${nacl_toolchain_tooldir}/lib", root_build_dir) ] - if (current_cpu == "arm") { - data += [ "${lib_path}/libarm/" ] - } else { - data += [ "${lib_path}/lib/" ] - } - } else { - # For x86-32, the lib/ directory is called lib32/ instead. - if (current_cpu == "x86") { - nmfflags += - [ "--library-path=" + - rebase_path("${nacl_toolchain_tooldir}/lib32", root_build_dir) ] - data += [ "${lib_path}/lib32/" ] - } - - # x86-32 Windows needs to build both x86-32 and x86-64 NaCl - # binaries into the same nmf covering both architectures. That - # gets handled at a higher level (see the nacl_test_data template), - # so a single generate_nmf invocation gets both x86-32 and x86-64 - # nexes listed in executables. - if (current_cpu == "x64" || target_os == "win") { - # For x86-64, the lib/ directory is called lib64/ instead - # when copied by create_nmf.py. - glibc_tc = "//build/toolchain/nacl:glibc" - assert(current_toolchain == "${glibc_tc}_${current_cpu}") - if (current_cpu == "x64") { - x64_out_dir = root_out_dir - } else { - x64_out_dir = get_label_info(":${target_name}(${glibc_tc}_x64)", - "root_out_dir") - } - nmfflags += [ - "--library-path=" + rebase_path(x64_out_dir, root_build_dir), - "--library-path=" + - rebase_path("${nacl_toolchain_tooldir}/lib", root_build_dir), - ] - data += [ "${lib_path}/lib64/" ] - } - } - } - args = [ - "--no-default-libpath", - "--objdump=" + rebase_path(objdump, root_build_dir), - "--output=" + rebase_path(nmf, root_build_dir), - ] + nmfflags + rebase_path(sources, root_build_dir) - if (is_nacl_glibc && current_cpu == "arm") { - deps += [ "//native_client/src/untrusted/elf_loader:elf_loader" ] - } - } -} diff --git a/naiveproxy/src/build/config/rust.gni b/naiveproxy/src/build/config/rust.gni index bd18d13119..7b09b0d80f 100644 --- a/naiveproxy/src/build/config/rust.gni +++ b/naiveproxy/src/build/config/rust.gni @@ -64,10 +64,6 @@ declare_args() { # not break incremental builds. rustc_version = "" - # If you're using a Rust toolchain as specified by rust_sysroot_absolute, - # you can specify whether it supports nacl here. - rust_toolchain_supports_nacl = false - # Whether artifacts produced by the Rust compiler can participate in ThinLTO. # # One important consideration is whether the linker uses the same LLVM @@ -112,8 +108,8 @@ declare_args() { use_chromium_rust_toolchain = rust_sysroot_absolute == "" # Platform support for the Rust toolchain. -chromium_toolchain_supports_platform = !is_nacl && !is_wasm -custom_toolchain_supports_platform = !is_nacl || rust_toolchain_supports_nacl +chromium_toolchain_supports_platform = !is_wasm +custom_toolchain_supports_platform = true # Not all target triples (GN toolchains) are supported by the Rust compiler. # Define if we support the current GN toolchain. diff --git a/naiveproxy/src/build/config/sanitizers/BUILD.gn b/naiveproxy/src/build/config/sanitizers/BUILD.gn index 66b993426a..e2f39f029a 100644 --- a/naiveproxy/src/build/config/sanitizers/BUILD.gn +++ b/naiveproxy/src/build/config/sanitizers/BUILD.gn @@ -179,9 +179,6 @@ config("default_sanitizer_ldflags") { visibility = [ ":default_sanitizer_flags", ":deps", - - # https://crbug.com/360158. - "//tools/ipc_fuzzer/fuzzer:ipc_fuzzer", ] if (is_posix || is_fuchsia) { diff --git a/naiveproxy/src/build/config/siso/android.star b/naiveproxy/src/build/config/siso/android.star index 45a906aa16..f6a1c3e6ba 100644 --- a/naiveproxy/src/build/config/siso/android.star +++ b/naiveproxy/src/build/config/siso/android.star @@ -43,13 +43,13 @@ def __step_config(ctx, step_config): remote_run = True # Turn this to False when you do file access trace. # Run static analysis steps locally when build server is enabled. + # android_static_analysis = "build_server" by default. # https://chromium.googlesource.com/chromium/src/+/main/docs/android_build_instructions.md#asynchronous-static-analysis remote_run_static_analysis = False if "args.gn" in ctx.metadata: gn_args = gn.args(ctx) - # android_static_analysis = "build_server" by default. - if gn_args.get("android_static_analysis") == '"on"': + if gn_args.get("android_static_analysis") in ('"on"', '"off"'): remote_run_static_analysis = True if gn_args.get("enable_kythe_annotations") == "true": # Remote Kythe annotations isn't supported. @@ -347,14 +347,14 @@ def __android_compile_resources_handler(ctx, cmd): # --webp-cache-dir=obj/android-webp-cache inputs = [] for i, arg in enumerate(cmd.args): - for k in ["--dependencies-res-zips=", "--dependencies-res-zip-overlays=", "--extra-res-packages="]: + for k in ["--dependencies-res-zips=", "--dependencies-res-zip-overlays="]: if arg.startswith(k): arg = arg.removeprefix(k) _, v = __filearg(ctx, arg) for f in v: f = ctx.fs.canonpath(f) inputs.append(f) - if k == "--dependencies-res-zips=" and ctx.fs.exists(f + ".info"): + if ctx.fs.exists(f + ".info"): inputs.append(f + ".info") ctx.actions.fix( @@ -470,7 +470,7 @@ def __android_trace_event_bytecode_rewriter(ctx, cmd): trace_event_adder_json = json.decode( str(ctx.fs.read(ctx.fs.canonpath("gen/build/android/bytecode/trace_event_adder.build_config.json"))), ) - for path in trace_event_adder_json.get("host_classpath", []): + for path in trace_event_adder_json.get("processed_classpath", []): inputs.append(ctx.fs.canonpath(path)) ctx.actions.fix( @@ -579,26 +579,17 @@ def __android_turbine_handler(ctx, cmd): inputs = cmd.inputs + inputs, ) -def __deps_configs(ctx, build_config_path, seen, inputs): - if build_config_path in seen: +def __recursive_params_json(ctx, params_path, seen, inputs): + if params_path in seen: return - seen[build_config_path] = True - params_path = build_config_path.replace(".build_config.json", ".params.json") - inputs.append(build_config_path) + seen[params_path] = True inputs.append(params_path) - build_config_data = json.decode(str(ctx.fs.read(build_config_path))) - params_data = None + params_data = json.decode(str(ctx.fs.read(params_path))) # Entries can be in either .build_config.json or in .params.json. for configs_key in ["deps_configs", "public_deps_configs"]: - sub_configs = build_config_data.get(configs_key) - if not sub_configs: - if not params_data: - params_data = json.decode(str(ctx.fs.read(params_path))) - sub_configs = params_data.get(configs_key, []) - - for f in sub_configs: - __deps_configs(ctx, ctx.fs.canonpath(f), seen, inputs) + for f in params_data.get(configs_key, []): + __recursive_params_json(ctx, ctx.fs.canonpath(f), seen, inputs) def __android_write_build_config_handler(ctx, cmd): # Script: @@ -606,14 +597,13 @@ def __android_write_build_config_handler(ctx, cmd): # GN Config: # https://crsrc.org/c/build/config/android/internal_rules.gni;l=122;drc=99e4f79301e108ea3d27ec84320f430490382587 # Sample args: + # --output gen/third_party/android_deps/org_jetbrains_kotlinx_kotlinx_metadata_jvm_java.build_config.json # --depfile gen/third_party/android_deps/org_jetbrains_kotlinx_kotlinx_metadata_jvm_java__build_config_crbug_908819.d - # --params gen/third_party/android_deps/org_jetbrains_kotlinx_kotlinx_metadata_jvm_java.params.json inputs = [] seen = {} for i, arg in enumerate(cmd.args): - if arg == "--params": - params_path = ctx.fs.canonpath(cmd.args[i + 1]) - output_build_config_path = params_path.replace(".params.json", ".build_config.json") + if arg == "--output": + params_path = ctx.fs.canonpath(cmd.args[i + 1].replace(".build_config.json", ".params.json")) v = json.decode(str(ctx.fs.read(params_path))) path = v.get("shared_libraries_runtime_deps_file") if path: @@ -621,16 +611,14 @@ def __android_write_build_config_handler(ctx, cmd): path = v.get("secondary_abi_shared_libraries_runtime_deps_file") if path: inputs.append(ctx.fs.canonpath(path)) - for k in ["apk_under_test_config", "base_module_config", "parent_module_config", "suffix_apk_assets_used_by_config"]: - path = v.get(k) - if path: - path = ctx.fs.canonpath(path) - if path != output_build_config_path: - __deps_configs(ctx, path, seen, inputs) - for k in ["deps_configs", "public_deps_configs", "processor_configs", "module_configs"]: + for k in ["deps_configs", "public_deps_configs", "processor_configs"]: for path in v.get(k, []): path = ctx.fs.canonpath(path) - __deps_configs(ctx, path, seen, inputs) + __recursive_params_json(ctx, path, seen, inputs) + path = v.get("apk_under_test_config") + if path: + path = ctx.fs.canonpath(path) + __recursive_params_json(ctx, path, seen, inputs) ctx.actions.fix(inputs = cmd.inputs + inputs) diff --git a/naiveproxy/src/build/config/siso/backend_config/google.star b/naiveproxy/src/build/config/siso/backend_config/google.star index 348317edc2..31b3687d29 100644 --- a/naiveproxy/src/build/config/siso/backend_config/google.star +++ b/naiveproxy/src/build/config/siso/backend_config/google.star @@ -7,7 +7,7 @@ load("@builtin//struct.star", "module") def __platform_properties(ctx): - container_image = "docker://gcr.io/chops-public-images-prod/rbe/siso-chromium/linux@sha256:ef35d347f4a4a2d32b76fd908e66e96f59bf8ba7379fd5626548244c45343b2b" + container_image = "docker://gcr.io/chops-public-images-prod/rbe/siso-chromium/linux@sha256:d7cb1ab14a0f20aa669c23f22c15a9dead761dcac19f43985bf9dd5f41fbef3a" return { "default": { "OSFamily": "Linux", diff --git a/naiveproxy/src/build/config/siso/backend_config/google_cros_chroot.star b/naiveproxy/src/build/config/siso/backend_config/google_cros_chroot.star index ea1855d882..2763740c7a 100644 --- a/naiveproxy/src/build/config/siso/backend_config/google_cros_chroot.star +++ b/naiveproxy/src/build/config/siso/backend_config/google_cros_chroot.star @@ -8,7 +8,7 @@ load("@builtin//struct.star", "module") def __platform_properties(ctx): # LINT.IfChange - container_image = "docker://gcr.io/chops-public-images-prod/rbe/siso-chromium/linux@sha256:ef35d347f4a4a2d32b76fd908e66e96f59bf8ba7379fd5626548244c45343b2b" + container_image = "docker://gcr.io/chops-public-images-prod/rbe/siso-chromium/linux@sha256:d7cb1ab14a0f20aa669c23f22c15a9dead761dcac19f43985bf9dd5f41fbef3a" return { "default": { diff --git a/naiveproxy/src/build/config/siso/clang_exception.star b/naiveproxy/src/build/config/siso/clang_exception.star index c6452884ff..0b4f205c2f 100644 --- a/naiveproxy/src/build/config/siso/clang_exception.star +++ b/naiveproxy/src/build/config/siso/clang_exception.star @@ -52,7 +52,37 @@ def __step_config(ctx, step_config, use_windows_worker = None): "name": "slow_compile", "action_outs": [ # keep-sorted start + "./obj/content/browser/browser/browser_interface_binders.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/prerender_browsertest.o", + "./obj/content/test/content_browsertests/site_per_process_browsertest.o", "./obj/content/test/content_unittests/auction_runner_unittest.o", + "./obj/third_party/abseil-cpp/absl/functional/any_invocable_test/any_invocable_test.o", + "./obj/third_party/highway/highway_tests/cast_test.o", + "./obj/third_party/highway/highway_tests/convert_test.o", + "./obj/third_party/highway/highway_tests/demote_test.o", + "./obj/third_party/highway/highway_tests/div_test.o", + "./obj/third_party/highway/highway_tests/if_test.o", + "./obj/third_party/highway/highway_tests/interleaved_test.o", + "./obj/third_party/highway/highway_tests/logical_test.o", + "./obj/third_party/highway/highway_tests/mask_mem_test.o", + "./obj/third_party/highway/highway_tests/mask_test.o", + "./obj/third_party/highway/highway_tests/masked_arithmetic_test.o", + "./obj/third_party/highway/highway_tests/memory_test.o", + "./obj/third_party/highway/highway_tests/rotate_test.o", + "./obj/third_party/highway/highway_tests/shift_test.o", + "./obj/third_party/highway/highway_tests/shuffle4_test.o", + "./obj/third_party/highway/highway_tests/widen_mul_test.o", + # keep-sorted end + ], + "timeout": "4m", + }, + { + "name": "slow_scandeps", + "action_outs": [ + # keep-sorted start + "./obj/chrome/browser/prefs/impl/browser_prefs.o", # keep-sorted end ], "timeout": "4m", diff --git a/naiveproxy/src/build/config/siso/clang_mac.star b/naiveproxy/src/build/config/siso/clang_mac.star index f0f3d02511..a79351572e 100644 --- a/naiveproxy/src/build/config/siso/clang_mac.star +++ b/naiveproxy/src/build/config/siso/clang_mac.star @@ -4,11 +4,11 @@ # found in the LICENSE file. """Siso configuration for clang/mac.""" -load("@builtin//lib/gn.star", "gn") load("@builtin//struct.star", "module") load("./clang_all.star", "clang_all") load("./clang_exception.star", "clang_exception") load("./clang_unix.star", "clang_unix") +load("./gn_logs.star", "gn_logs") load("./mac_sdk.star", "mac_sdk") load("./rewrapper_cfg.star", "rewrapper_cfg") @@ -48,7 +48,7 @@ def __step_config(ctx, step_config): elif rule["platform_ref"] == "large": rule["platform_ref"] = "clang_large" step_config["rules"].append(rule) - elif gn.args(ctx).get("use_remoteexec") == "true": + elif gn_logs.read(ctx).get("use_remoteexec") == "true": fail("remoteexec requires rewrapper config") step_config = clang_exception.step_config(ctx, step_config) diff --git a/naiveproxy/src/build/config/siso/clang_unix.star b/naiveproxy/src/build/config/siso/clang_unix.star index 4f5f3b3f7b..ab469f7310 100644 --- a/naiveproxy/src/build/config/siso/clang_unix.star +++ b/naiveproxy/src/build/config/siso/clang_unix.star @@ -12,35 +12,31 @@ load("./config.star", "config") load("./gn_logs.star", "gn_logs") load("./win_sdk.star", "win_sdk") -def __clang_modulemap(ctx, cmd): - """Fixes inputs for clang compile actions with modulemap. +def __add_generated_libcxx_headers(ctx, cmd): + """Adds libc++ headers as tool inputs for clang compile actions. - But this is simplified implementation to parse current modulemap. - https://clang.llvm.org/docs/Modules.html#module-map-file + This is needed because libc++ headers in the build directory are not always + discovered by the precomputed tree and scandeps. It identifies them using + `-isystem` flags and `libcxx_headers.gni`. """ - inputs = [] + libcxx_headers = [] + for line in str(ctx.fs.read("buildtools/third_party/libc++/libcxx_headers.gni")).split("\n"): + if "third_party/libc++/src/include" in line: + libcxx_headers.append(line.split("src/include/")[1].removesuffix("\",")) + + tool_inputs = [] for arg in cmd.args: - module_config = arg.removeprefix("-fmodule-map-file=") - if arg == module_config: + isystem = arg.removeprefix("-isystem") + if arg == isystem or "third_party/libc++/src/include" not in isystem: continue - module_config = ctx.fs.canonpath(module_config) - module_dir = path.dir(module_config) - for line in str(ctx.fs.read(module_config)).split("\n"): - # Remove one line comment. - line = line.split("//")[0] - - # Extract a quoted path if any. - quoted_paths = line.split("\"") - if len(quoted_paths) > 2: - include_path = quoted_paths[1] - include_path = path.join(module_dir, include_path) - inputs.append(include_path) - - ctx.actions.fix(tool_inputs = cmd.tool_inputs + inputs) + isystem = ctx.fs.canonpath(isystem) + for header in libcxx_headers: + tool_inputs.append(path.join(isystem, header)) + ctx.actions.fix(tool_inputs = cmd.tool_inputs + tool_inputs) def __clang_compile_coverage(ctx, cmd): - __clang_modulemap(ctx, cmd) + __add_generated_libcxx_headers(ctx, cmd) clang_command = clang_code_coverage_wrapper.run(ctx, list(cmd.args)) ctx.actions.fix(args = clang_command) @@ -102,7 +98,7 @@ def __clang_link(ctx, cmd): ctx.actions.fix(inputs = cmd.inputs + inputs) __handlers = { - "clang_modulemap": __clang_modulemap, + "add_generated_libcxx_headers": __add_generated_libcxx_headers, "clang_compile_coverage": __clang_compile_coverage, "clang_link": __clang_link, } @@ -229,7 +225,7 @@ def __rules(ctx): "third_party/llvm-build/Release+Asserts/bin/clang++", ], "exclude_input_patterns": ["*.stamp"], - "handler": "clang_modulemap", + "handler": "add_generated_libcxx_headers", "remote": True, "input_root_absolute_path": input_root_absolute_path, "canonicalize_dir": canonicalize_dir, @@ -269,6 +265,7 @@ def __rules(ctx): "third_party/llvm-build/Release+Asserts/bin/clang++", ], "exclude_input_patterns": ["*.stamp"], + "handler": "add_generated_libcxx_headers", "remote": True, "timeout": "2m", "input_root_absolute_path": input_root_absolute_path_for_objc, @@ -419,6 +416,7 @@ def __rules(ctx): "exclude_input_patterns": [ "*.cc", "*.h", + "*.info", "*.js", "*.pak", "*.py", diff --git a/naiveproxy/src/build/config/siso/clang_windows.star b/naiveproxy/src/build/config/siso/clang_windows.star index 9f9ad122f6..f1deb0e066 100644 --- a/naiveproxy/src/build/config/siso/clang_windows.star +++ b/naiveproxy/src/build/config/siso/clang_windows.star @@ -4,7 +4,6 @@ # found in the LICENSE file. """Siso configuration for clang-cl/windows.""" -load("@builtin//lib/gn.star", "gn") load("@builtin//struct.star", "module") load("./clang_all.star", "clang_all") load("./clang_code_coverage_wrapper.star", "clang_code_coverage_wrapper") @@ -214,7 +213,7 @@ def __step_config(ctx, step_config): }, ]) step_config = clang_exception.step_config(ctx, step_config, use_windows_worker) - elif gn.args(ctx).get("use_remoteexec") == "true": + elif gn_logs.read(ctx).get("use_remoteexec") == "true": fail("remoteexec requires rewrapper config") return step_config diff --git a/naiveproxy/src/build/config/siso/config.star b/naiveproxy/src/build/config/siso/config.star index 960f09d308..4b0e4f58ad 100644 --- a/naiveproxy/src/build/config/siso/config.star +++ b/naiveproxy/src/build/config/siso/config.star @@ -26,6 +26,11 @@ __KNOWN_CONFIG_OPTIONS = [ # because developers need objects and tests locally for debugging # and testing. "remote-link", + + # Unset timeout from rules to allow long remote steps. + # This is useful when remote actions are expected to take longer than + # the configured timeouts. e.g. remote linking for official builds. + "no-remote-timeout", ] def __check(ctx): diff --git a/naiveproxy/src/build/config/siso/mac_sdk.star b/naiveproxy/src/build/config/siso/mac_sdk.star index cfb5fe7714..3f1178b983 100644 --- a/naiveproxy/src/build/config/siso/mac_sdk.star +++ b/naiveproxy/src/build/config/siso/mac_sdk.star @@ -36,7 +36,8 @@ def __filegroups(ctx): "includes": sdk_includes, }, } - if gn.args(ctx).get("use_remoteexec") == "true": + gn_logs_data = gn_logs.read(ctx) + if gn_logs_data.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. @@ -44,7 +45,6 @@ def __filegroups(ctx): # # 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", diff --git a/naiveproxy/src/build/config/siso/main.star b/naiveproxy/src/build/config/siso/main.star index 698c1fd869..34bb20173d 100644 --- a/naiveproxy/src/build/config/siso/main.star +++ b/naiveproxy/src/build/config/siso/main.star @@ -10,6 +10,7 @@ load("@builtin//runtime.star", "runtime") load("@builtin//struct.star", "module") load("./backend_config/backend.star", "backend") load("./blink_all.star", "blink_all") +load("./config.star", "config") load("./gn_logs.star", "gn_logs") load("./linux.star", chromium_linux = "chromium") load("./mac.star", chromium_mac = "chromium") @@ -21,12 +22,20 @@ load("./simple.star", "simple") load("./windows.star", chromium_windows = "chromium") def __disable_remote(ctx, step_config): - if gn.args(ctx).get("use_remoteexec") == "true": + gn_logs_data = gn_logs.read(ctx) + if gn_logs_data.get("use_remoteexec") == "true": return step_config for rule in step_config["rules"]: rule["remote"] = False return step_config +def __unset_timeout(ctx, step_config): + if not config.get(ctx, "no-remote-timeout"): + return step_config + for rule in step_config["rules"]: + rule.pop("timeout", None) + return step_config + def init(ctx): print("runtime: os:%s arch:%s run:%d" % ( runtime.os, @@ -79,6 +88,7 @@ def init(ctx): rule["remote_command"] = arg0 step_config = __disable_remote(ctx, step_config) + step_config = __unset_timeout(ctx, step_config) filegroups = {} filegroups.update(blink_all.filegroups(ctx)) diff --git a/naiveproxy/src/build/config/siso/mojo.star b/naiveproxy/src/build/config/siso/mojo.star index 92d46b98a9..9a28d6345e 100644 --- a/naiveproxy/src/build/config/siso/mojo.star +++ b/naiveproxy/src/build/config/siso/mojo.star @@ -29,10 +29,8 @@ def __step_config(ctx, step_config): { "name": "mojo/mojom_parser", "command_prefix": platform.python_bin + " ../../mojo/public/tools/mojom/mojom_parser.py", - # TODO: b/285078792 - Win cross compile on Linux worker doesn't work with input_root_absolute_path=true. "remote": runtime.os != "windows", "canonicalize_dir": True, - "input_root_absolute_path": True, "timeout": "2m", "output_local": True, "platform_ref": platform_ref, diff --git a/naiveproxy/src/build/config/siso/rust.star b/naiveproxy/src/build/config/siso/rust.star index 37ced20b70..9656b4f0fb 100644 --- a/naiveproxy/src/build/config/siso/rust.star +++ b/naiveproxy/src/build/config/siso/rust.star @@ -166,23 +166,32 @@ def __step_config(ctx, step_config): platform_ref = "large" # Rust actions run faster on large workers. remote = True - remote_link = True + + # TODO(crbug.com/434857701): fix link for target_arch="x86" + remote_link = False + clang_inputs = [ + "third_party/llvm-build/Release+Asserts:rustlink", + ] if runtime.os != "linux": remote = False remote_link = False elif "args.gn" in ctx.metadata: gn_args = gn.args(ctx) - if gn_args.get("target_os") in ('"mac"', '"ios"', '"win"'): + target_os = gn_args.get("target_os") + if target_os in ('"mac"', '"ios"'): + remote = False remote_link = False - clang_inputs = [ - "build/linux/debian_bullseye_amd64-sysroot:rustlink", - "third_party/llvm-build/Release+Asserts:rustlink", - ] - if win_sdk.enabled(ctx): - clang_inputs.append(win_sdk.toolchain_dir(ctx) + ":libs") - else: - remote = False - remote_link = False + elif target_os == '"win"': + remote_link = False + if win_sdk.enabled(ctx): + clang_inputs.append(win_sdk.toolchain_dir(ctx) + ":libs") + else: + remote = False + else: + # TODO(crbug.com/434857701): fix sysroot for target_arch="x86" + clang_inputs.append( + "build/linux/debian_bullseye_amd64-sysroot:rustlink", + ) rust_toolchain = [ # TODO(b/285225184): use precomputed subtree @@ -191,7 +200,7 @@ def __step_config(ctx, step_config): rust_inputs = [ "build/action_helpers.py", "build/gn_helpers.py", - "build/rust/rustc_wrapper.py", + "build/rust/gni_impl/rustc_wrapper.py", ] + rust_toolchain rust_indirect_inputs = { "includes": [ @@ -263,7 +272,7 @@ def __step_config(ctx, step_config): }, { "name": "rust/run_build_script", - "command_prefix": "python3 ../../build/rust/run_build_script.py", + "command_prefix": "python3 ../../build/rust/gni_impl/run_build_script.py", "inputs": [ "third_party/rust-toolchain:toolchain", "third_party/rust:rustlib", @@ -288,7 +297,7 @@ def __step_config(ctx, step_config): # rust/bindgen fails remotely when *.d does not exist. # TODO(b/356496947): need to run scandeps? "name": "rust/bindgen", - "command_prefix": "python3 ../../build/rust/run_bindgen.py", + "command_prefix": "python3 ../../build/rust/gni_impl/run_bindgen.py", "inputs": rust_toolchain + clang_inputs, "remote": False, "timeout": "2m", diff --git a/naiveproxy/src/build/config/unsafe_buffers_paths.txt b/naiveproxy/src/build/config/unsafe_buffers_paths.txt index 29db2f9957..57c1d12d18 100644 --- a/naiveproxy/src/build/config/unsafe_buffers_paths.txt +++ b/naiveproxy/src/build/config/unsafe_buffers_paths.txt @@ -8,7 +8,6 @@ .buffers,libc # Directories to exempt from checks --base/allocator/ -base/third_party/ -codelabs/ # Examples, keep simple. -chrome/browser/platform_experience/win/ @@ -17,17 +16,16 @@ -chrome/installer/mac/third_party/ -chromeos/assistant/internal -components/optimization_guide/internal/ --ios/ --ios_internal/ --native_client/ +-ios/third_party/ -net/third_party/ --ppapi/ +-services/shape_detection/internal/barhopper/ -testing/iossim/ -third_party/ +third_party/blink/ ++third_party/jni_zero/ +third_party/ipcz/ ++third_party/liburlpattern/ -tools/ -ui/gl/ # Unsafe generated files. -url/third_party/ -v8/ - diff --git a/naiveproxy/src/build/config/warning_suppression.txt b/naiveproxy/src/build/config/warning_suppression.txt index 3f123d7d5d..d1e75ad43d 100644 --- a/naiveproxy/src/build/config/warning_suppression.txt +++ b/naiveproxy/src/build/config/warning_suppression.txt @@ -44,4 +44,4 @@ src:*{/,\\}third_party{/,\\}nearby{/,\\}* # As an experiment, we're breaking the policy and suppressing it permanently. src:*{/,\\}third_party{/,\\}* # v8's build system isn't amenable to fixes: https://crbug.com/408259026 -src:*{/,\\}v8{/,\\}* \ No newline at end of file +src:*{/,\\}v8{/,\\}* diff --git a/naiveproxy/src/build/config/win/BUILD.gn b/naiveproxy/src/build/config/win/BUILD.gn index aaeadc3132..eae6724d4a 100644 --- a/naiveproxy/src/build/config/win/BUILD.gn +++ b/naiveproxy/src/build/config/win/BUILD.gn @@ -81,7 +81,6 @@ config("compiler") { # for precompiled headers where the same source file is compiled in both # modes. cflags_c = [ "/TC" ] - cflags_cc = [ "/TP" ] if (is_clang) { # Required to make the 19041 SDK compatible with clang-cl. diff --git a/naiveproxy/src/build/download_nacl_toolchains.py b/naiveproxy/src/build/download_nacl_toolchains.py deleted file mode 100755 index 1b86a4bb9e..0000000000 --- a/naiveproxy/src/build/download_nacl_toolchains.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2012 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Shim to run nacl toolchain download script only if there is a nacl dir.""" - - -import os -import shutil -import sys - - -def Main(args): - script_dir = os.path.dirname(os.path.abspath(__file__)) - src_dir = os.path.dirname(script_dir) - nacl_dir = os.path.join(src_dir, 'native_client') - nacl_build_dir = os.path.join(nacl_dir, 'build') - package_version_dir = os.path.join(nacl_build_dir, 'package_version') - package_version = os.path.join(package_version_dir, 'package_version.py') - if not os.path.exists(package_version): - print("Can't find '%s'" % package_version) - print('Presumably you are intentionally building without NativeClient.') - print('Skipping NativeClient toolchain download.') - sys.exit(0) - sys.path.insert(0, package_version_dir) - import package_version - - # BUG: - # We remove this --optional-pnacl argument, and instead replace it with - # --no-pnacl for most cases. However, if the bot name is an sdk - # bot then we will go ahead and download it. This prevents increasing the - # gclient sync time for developers, or standard Chrome bots. - if '--optional-pnacl' in args: - args.remove('--optional-pnacl') - use_pnacl = False - buildbot_name = os.environ.get('BUILDBOT_BUILDERNAME', '') - if 'pnacl' in buildbot_name and 'sdk' in buildbot_name: - use_pnacl = True - if use_pnacl: - print('\n*** DOWNLOADING PNACL TOOLCHAIN ***\n') - else: - args = ['--exclude', 'pnacl_newlib'] + args - - # Only download the ARM gcc toolchain if we are building for ARM - # TODO(olonho): we need to invent more reliable way to get build - # configuration info, to know if we're building for ARM. - if 'target_arch=arm' not in os.environ.get('GYP_DEFINES', ''): - args = ['--exclude', 'nacl_arm_newlib'] + args - - return package_version.main(args) - - -if __name__ == '__main__': - sys.exit(Main(sys.argv[1:])) diff --git a/naiveproxy/src/build/fuchsia/linux_internal.sdk.sha1 b/naiveproxy/src/build/fuchsia/linux_internal.sdk.sha1 index b8f39f9e2b..9f4e4c078c 100644 --- a/naiveproxy/src/build/fuchsia/linux_internal.sdk.sha1 +++ b/naiveproxy/src/build/fuchsia/linux_internal.sdk.sha1 @@ -1 +1 @@ -28.20250609.102.1 +28.20250730.101.1 diff --git a/naiveproxy/src/build/fuchsia/test/browser_runner.py b/naiveproxy/src/build/fuchsia/test/browser_runner.py index 725f3ee7d7..7cb6f3ac4c 100644 --- a/naiveproxy/src/build/fuchsia/test/browser_runner.py +++ b/naiveproxy/src/build/fuchsia/test/browser_runner.py @@ -6,7 +6,6 @@ import os import re import subprocess -import tempfile import time from typing import List, Optional from urllib.parse import urlparse @@ -24,7 +23,8 @@ class BrowserRunner: def __init__(self, browser_type: str, target_id: Optional[str] = None, - output_dir: Optional[str] = None): + output_dir: Optional[str] = None, + logs_dir: Optional[str] = None): self._browser_type = browser_type assert self._browser_type in [WEB_ENGINE_SHELL, CAST_STREAMING_SHELL] self._target_id = target_id @@ -33,7 +33,9 @@ class BrowserRunner: self._browser_proc = None self._symbolizer_proc = None self._devtools_port = None - self._log_fs = None + if not logs_dir: + logs_dir = os.environ.get('ISOLATED_OUTDIR', '/tmp') + self._log_fs = open(os.path.join(logs_dir, 'browser.log'), 'w') output_root = os.path.join(self._output_dir, 'gen', 'fuchsia_web') if self._browser_type == WEB_ENGINE_SHELL: @@ -146,7 +148,7 @@ class BrowserRunner: stderr=subprocess.STDOUT, target_id=self._target_id) # The stdout will be forwarded to the symbolizer, then to the _log_fs. - self._log_fs = tempfile.NamedTemporaryFile() + assert self._log_fs self._symbolizer_proc = run_symbolizer(self._id_files, self._browser_proc.stdout, self._log_fs) diff --git a/naiveproxy/src/build/fuchsia/test/chrome_driver_wrapper.py b/naiveproxy/src/build/fuchsia/test/chrome_driver_wrapper.py index 59242a0d7d..29110c5680 100644 --- a/naiveproxy/src/build/fuchsia/test/chrome_driver_wrapper.py +++ b/naiveproxy/src/build/fuchsia/test/chrome_driver_wrapper.py @@ -7,9 +7,9 @@ import logging import os import subprocess +import sys from contextlib import AbstractContextManager -from typing import List # From vpython wheel. # pylint: disable=import-error @@ -31,7 +31,7 @@ class ChromeDriverWrapper(AbstractContextManager): communicating with it. This class expects the chromedriver exists at clang_x64/stripped/chromedriver in output dir.""" - def __init__(self, extra_args: List[str] = None): + def __init__(self): # The reference of the webdriver.Chrome instance. self._driver = None @@ -44,7 +44,13 @@ class ChromeDriverWrapper(AbstractContextManager): self._proc: subprocess.Popen = None # Extra arguments sent to run_test.py webpage process. - self._extra_args = extra_args or [] + self._extra_args = [] + for arg in sys.argv: + # The image update should happen before running the + # web_engine_shell. + if (arg.startswith('--os-check=') or + arg.startswith('--system-image-dir=')): + self._extra_args.append(arg) def __enter__(self): """Starts the run_test.py and the chromedriver connecting to it, must be diff --git a/naiveproxy/src/build/fuchsia/test/compatible_utils_unittests.py b/naiveproxy/src/build/fuchsia/test/compatible_utils_unittests.py index b23701975a..8f859c2a6f 100755 --- a/naiveproxy/src/build/fuchsia/test/compatible_utils_unittests.py +++ b/naiveproxy/src/build/fuchsia/test/compatible_utils_unittests.py @@ -107,6 +107,11 @@ class CompatibleUtilsTest(unittest.TestCase): self.assertRaises(IOError, compatible_utils.get_sdk_hash, 'some/image/dir') + def test_get_ssh_prefix(self) -> None: + """Ensures the get_ssh_prefix won't return a None.""" + self.assertIsNotNone(compatible_utils.get_ssh_prefix( + ("host.test", 80))) + def test_install_symbols(self): """Test |install_symbols|.""" def trim_noop_prefixes(path): diff --git a/naiveproxy/src/build/fuchsia/test/coveragetest.py b/naiveproxy/src/build/fuchsia/test/coveragetest.py index aabd164bd2..4bf56b1c7f 100755 --- a/naiveproxy/src/build/fuchsia/test/coveragetest.py +++ b/naiveproxy/src/build/fuchsia/test/coveragetest.py @@ -22,7 +22,7 @@ COVERED_FILES = [ TESTED_FILES = [ 'bundled_test_runner.py', 'common.py', 'component_storage.py', 'ffx_emulator.py', 'modification_waiter.py', 'monitors.py', - 'serial_boot_device.py', 'test_server.py', 'version.py' + 'serial_boot_device.py', 'version.py' ] diff --git a/naiveproxy/src/build/fuchsia/test/gs_util_wrapper.py b/naiveproxy/src/build/fuchsia/test/gs_util_wrapper.py index 0e7fb8393e..1f48f70a12 100644 --- a/naiveproxy/src/build/fuchsia/test/gs_util_wrapper.py +++ b/naiveproxy/src/build/fuchsia/test/gs_util_wrapper.py @@ -8,13 +8,19 @@ import os import subprocess import sys -from typing import List +from typing import List, Optional from common import DIR_SRC_ROOT -def _find_gsutil() -> str: +def _find_gsutil() -> Optional[str]: """ Returns the location of the gsutil.py. """ + if not os.path.isfile( + os.path.join(DIR_SRC_ROOT, 'build', 'find_depot_tools.py')): + # No gsutil.py and find_depot_tools.py wrapper, will run gsutil + # directly. + return None + sys.path.append(os.path.join(DIR_SRC_ROOT, 'build')) # Do not pollute the environment, callers should not use find_depot_tools # directly. @@ -31,4 +37,7 @@ GSUTIL_PATH = _find_gsutil() def run_gsutil(args: List[str]) -> None: """ Runs gsutil with |args| and throws CalledProcessError if the process failed. """ + if not GSUTIL_PATH: + # Try to run gsutil directly if there isn't a gsutil.py wrapper. + return subprocess.run(['gsutil'] + args, check=True) return subprocess.run([sys.executable, GSUTIL_PATH] + args, check=True) diff --git a/naiveproxy/src/build/fuchsia/test/run_executable_test.py b/naiveproxy/src/build/fuchsia/test/run_executable_test.py index 3d23c154a3..feca5a236e 100755 --- a/naiveproxy/src/build/fuchsia/test/run_executable_test.py +++ b/naiveproxy/src/build/fuchsia/test/run_executable_test.py @@ -20,8 +20,6 @@ from compatible_utils import map_filter_file_to_package_file from ffx_integration import FfxTestRunner, run_symbolizer from test_runner import TestRunner -DEFAULT_TEST_SERVER_CONCURRENCY = 4 - def _copy_custom_output_file(test_runner: FfxTestRunner, file: str, dest: str) -> None: @@ -68,7 +66,6 @@ class ExecutableTestRunner(TestRunner): self._isolated_script_test_perf_output = None self._logs_dir = logs_dir self._test_launcher_summary_output = None - self._test_server = None self._test_realm = test_realm def _get_args(self) -> List[str]: @@ -99,10 +96,6 @@ class ExecutableTestRunner(TestRunner): parser.add_argument('--test-launcher-jobs', type=int, help='Sets the number of parallel test jobs.') - parser.add_argument('--enable-test-server', - action='store_true', - default=False, - help='Enable Chrome test server spawner.') parser.add_argument('--test-arg', dest='test_args', action='append', @@ -139,22 +132,6 @@ class ExecutableTestRunner(TestRunner): args.test_launcher_filter_file.split(';')) child_args.append('--test-launcher-filter-file=' + ';'.join(test_launcher_filter_files)) - if args.test_launcher_jobs is not None: - test_concurrency = args.test_launcher_jobs - else: - test_concurrency = DEFAULT_TEST_SERVER_CONCURRENCY - if args.enable_test_server: - # Repos other than chromium may not have chrome_test_server_spawner, - # and they may not run server at all, so only import the test_server - # when it's really necessary. - - # pylint: disable=import-outside-toplevel - from test_server import setup_test_server - # pylint: enable=import-outside-toplevel - self._test_server, spawner_url_base = setup_test_server( - self._target_id, test_concurrency) - child_args.append('--remote-test-server-spawner-url-base=%s' % - spawner_url_base) if get_host_arch() == 'x64': # TODO(crbug.com/40202294) Remove once Vulkan is enabled by # default. @@ -169,8 +146,6 @@ class ExecutableTestRunner(TestRunner): return child_args def _postprocess(self, test_runner: FfxTestRunner) -> None: - if self._test_server: - self._test_server.Stop() if self._test_launcher_summary_output: _copy_custom_output_file( test_runner, diff --git a/naiveproxy/src/build/fuchsia/test/run_webpage_test.py b/naiveproxy/src/build/fuchsia/test/run_webpage_test.py index 95de542041..8b5c1f3f47 100644 --- a/naiveproxy/src/build/fuchsia/test/run_webpage_test.py +++ b/naiveproxy/src/build/fuchsia/test/run_webpage_test.py @@ -46,7 +46,7 @@ class WebpageTestRunner(TestRunner): target_id: Optional[str], logs_dir: Optional[str]) -> None: super().__init__(out_dir, test_args, ['web_engine_shell'], target_id) self._runner = browser_runner.BrowserRunner( - browser_runner.WEB_ENGINE_SHELL, target_id, out_dir) + browser_runner.WEB_ENGINE_SHELL, target_id, out_dir, logs_dir) if logs_dir: self.port_file = os.path.join(logs_dir, _DEVTOOLS_PORT_FILE) else: diff --git a/naiveproxy/src/build/fuchsia/test/test_server.py b/naiveproxy/src/build/fuchsia/test/test_server.py index 23a1dea28c..6d3540403a 100644 --- a/naiveproxy/src/build/fuchsia/test/test_server.py +++ b/naiveproxy/src/build/fuchsia/test/test_server.py @@ -8,15 +8,12 @@ import os import sys import subprocess -from typing import List, Optional, Tuple +from typing import List, Tuple -from common import DIR_SRC_ROOT, get_free_local_port, get_ssh_address +from common import DIR_SRC_ROOT, get_free_local_port from compatible_utils import get_ssh_prefix sys.path.append(os.path.join(DIR_SRC_ROOT, 'build', 'util', 'lib', 'common')) -# pylint: disable=import-error,wrong-import-position -import chrome_test_server_spawner -# pylint: enable=import-error,wrong-import-position def _run_ssh_tunnel(target_addr: str, command: str, @@ -133,71 +130,3 @@ def cancel_port_forwarding(target_addr: str, fuchsia_port: int, host_port: int, should still be used to cancel the port forwarding.""" _run_ssh_tunnel(target_addr, 'cancel', _forward_command(fuchsia_port, host_port, port_forwarding)) - - -# Disable pylint errors since the subclass is not from this directory. -# pylint: disable=invalid-name,missing-function-docstring -class SSHPortForwarder(chrome_test_server_spawner.PortForwarder): - """Implementation of chrome_test_server_spawner.PortForwarder that uses - SSH's remote port forwarding feature to forward ports.""" - - def __init__(self, target_addr: str) -> None: - self._target_addr = target_addr - - # Maps the host (server) port to the device port number. - self._port_mapping = {} - - def Map(self, port_pairs: List[Tuple[int, int]]) -> None: - for p in port_pairs: - fuchsia_port, host_port = p - assert fuchsia_port == 0, \ - 'Port forwarding with a fixed fuchsia-port is unsupported yet.' - self._port_mapping[host_port] = \ - port_forward(self._target_addr, host_port) - - def GetDevicePortForHostPort(self, host_port: int) -> int: - return self._port_mapping[host_port] - - def Unmap(self, device_port: int) -> None: - for host_port, fuchsia_port in self._port_mapping.items(): - if fuchsia_port == device_port: - cancel_port_forwarding(self._target_addr, 0, host_port, True) - del self._port_mapping[host_port] - return - - raise Exception('Unmap called for unknown port: %d' % device_port) - - -# pylint: enable=invalid-name,missing-function-docstring - - -def setup_test_server(target_id: Optional[str], test_concurrency: int)\ - -> Tuple[chrome_test_server_spawner.SpawningServer, str]: - """Provisions a test server and configures |target_id| to use it. - - Args: - target_id: The target to which port forwarding to the test server will - be established. - test_concurrency: The number of parallel test jobs that will be run. - - Returns a tuple of a SpawningServer object and the local url to use on - |target_id| to reach the test server.""" - - logging.debug('Starting test server.') - - target_addr = get_ssh_address(target_id) - - # The TestLauncher can launch more jobs than the limit specified with - # --test-launcher-jobs so the max number of spawned test servers is set to - # twice that limit here. See https://crbug.com/913156#c19. - spawning_server = chrome_test_server_spawner.SpawningServer( - 0, SSHPortForwarder(target_addr), test_concurrency * 2) - - forwarded_port = port_forward(target_addr, spawning_server.server_port) - spawning_server.Start() - - logging.debug('Test server listening for connections (port=%d)', - spawning_server.server_port) - logging.debug('Forwarded port is %d', forwarded_port) - - return (spawning_server, 'http://localhost:%d' % forwarded_port) diff --git a/naiveproxy/src/build/fuchsia/test/test_server_unittests.py b/naiveproxy/src/build/fuchsia/test/test_server_unittests.py deleted file mode 100755 index 38bdb912c3..0000000000 --- a/naiveproxy/src/build/fuchsia/test/test_server_unittests.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env vpython3 -# 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. -"""File for testing test_server.py.""" - -import unittest -import unittest.mock as mock - -from subprocess import CalledProcessError - -import test_server - -# TODO(crbug.com/40935291): Specifying fuchsia-port is unsupported yet. -_FUCHSIA_PORT = 0 -_TARGET_ADDR = '127.0.0.1:33333' -_HOST_PORT = 55555 - -port_pair = (_FUCHSIA_PORT, _HOST_PORT) - -# Test names should be self-explained. -# pylint: disable=missing-function-docstring - -class TestServerTest(unittest.TestCase): - """Unittests for test_server.py.""" - - def setUp(self) -> None: - self._subprocess_patcher = mock.patch('test_server.subprocess.run') - self._log_patcher = mock.patch('test_server.logging.debug') - self._subprocess_mock = self._subprocess_patcher.start() - self._log_mock = self._log_patcher.start() - self.addCleanup(self._log_mock.stop) - self.addCleanup(self._subprocess_mock.stop) - - self._cmd_mock = mock.Mock() - self._cmd_mock.returncode = 0 - self._cmd_mock.stdout = str(port_pair[0]) - self._subprocess_mock.return_value = self._cmd_mock - - self._forwarder = test_server.SSHPortForwarder(_TARGET_ADDR) - self._forwarder.Map([port_pair]) - - def test_ssh_port_forwarder(self) -> None: - self.assertEqual(self._subprocess_mock.call_count, 2) - self.assertEqual( - self._forwarder.GetDevicePortForHostPort(port_pair[1]), - port_pair[0]) - - def test_ssh_port_forwarder_unmapped(self) -> None: - self._forwarder.Unmap(port_pair[0]) - # Unmap should raise an exception if no ports are mapped. - with self.assertRaises(Exception): - self._forwarder.Unmap(port_pair[0]) - - def test_ssh_port_forwarder_ssh_exception(self) -> None: - # Unmap should also raise an exception if the unmap command fails. - self._subprocess_mock.side_effect = [ - self._cmd_mock, - CalledProcessError(cmd='ssh', returncode=1) - ] - with self.assertRaises(Exception): - self._forwarder.Unmap(port_pair[0]) - self.assertEqual(self._subprocess_mock.call_count, 4) - - def test_ssh_port_forward_unmap(self) -> None: - self._cmd_mock.returncode = 0 - self._forwarder.Unmap(port_pair[0]) - self.assertEqual(self._subprocess_mock.call_count, 4) - - def test_port_forward_exception(self) -> None: - """Tests that exception is raised if |port_forward| command fails.""" - cmd_mock = mock.Mock() - cmd_mock.returncode = 1 - self._subprocess_mock.return_value = cmd_mock - with self.assertRaises(Exception): - test_server.port_forward(_TARGET_ADDR, _FUCHSIA_PORT) - - @mock.patch('test_server.chrome_test_server_spawner.SpawningServer') - @mock.patch('test_server.port_forward') - def test_setup_test_server(self, forward_mock, server_mock) -> None: - """Test |setup_test_server|.""" - - forward_mock.return_value = _FUCHSIA_PORT - server = test_server.chrome_test_server_spawner.SpawningServer - server.Start = mock.Mock() - server_mock.return_value = server - with mock.patch('test_server.get_ssh_address'): - _, url = test_server.setup_test_server(_TARGET_ADDR, 4) - self.assertTrue(str(_FUCHSIA_PORT) in url) - - -if __name__ == '__main__': - unittest.main() diff --git a/naiveproxy/src/build/install-build-deps.py b/naiveproxy/src/build/install-build-deps.py index 412962fedf..8800d36164 100755 --- a/naiveproxy/src/build/install-build-deps.py +++ b/naiveproxy/src/build/install-build-deps.py @@ -10,16 +10,22 @@ import argparse import functools +import logging import os import re import shutil import subprocess import sys +logging.basicConfig(stream=sys.stderr, + level=logging.INFO, + format='%(name)s [%(levelname)s]: %(message)s') +logger = logging.getLogger(os.path.basename(sys.argv[0])) + @functools.lru_cache(maxsize=1) def build_apt_package_list(): - print("Building apt package list.", file=sys.stderr) + logger.info("Building apt package list.") output = subprocess.check_output(["apt-cache", "dumpavail"]).decode() arch_map = {"i386": ":i386"} package_regex = re.compile(r"^Package: (.+?)$.+?^Architecture: (.+?)$", @@ -134,8 +140,8 @@ def parse_args(argv): def check_lsb_release(): if not shutil.which("lsb_release"): - print("ERROR: lsb_release not found in $PATH", file=sys.stderr) - print("try: sudo apt-get install lsb-release", file=sys.stderr) + logger.error("lsb_release not found in $PATH") + logger.error("try: sudo apt-get install lsb-release") sys.exit(1) @@ -149,7 +155,7 @@ def distro_codename(): def requires_pinned_linux_libc(): # See: https://crbug.com/403291652 and b/408002335 name = subprocess.check_output(["uname", "-r"]).decode().strip() - return name == '6.12.12-1rodete2-amd64' + return name.startswith('6.12.') and name.endswith('rodete1-amd64') def add_version_workaround(packages): @@ -171,36 +177,32 @@ def check_distro(options): if (distro_codename() not in supported_codenames and distro_id not in supported_ids): - print( - "WARNING: The following distributions are supported,", - "but distributions not in the list below can also try to install", - "dependencies by passing the `--unsupported` parameter.", - "EoS refers to end of standard support and does not include", - "extended security support.", - "\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 11 (bullseye) or later", - sep="\n", - file=sys.stderr, - ) + logger.warning( + ("The following distributions are supported, " + "but distributions not in the list below can also try to install " + "dependencies by passing the `--unsupported` parameter.")) + logger.warning( + ("EoS refers to end of standard support and does not include " + "extended security support.\n" + "\tUbuntu 20.04 LTS (focal with EoS April 2025)\n" + "\tUbuntu 22.04 LTS (jammy with EoS June 2027)\n" + "\tUbuntu 24.04 LTS (noble with EoS June 2029)\n" + "\tDebian 11 (bullseye) or later")) sys.exit(1) def check_architecture(): architecture = subprocess.check_output(["uname", "-m"]).decode().strip() if architecture not in ["i686", "x86_64", 'aarch64']: - print("Only x86 and ARM64 architectures are currently supported", - file=sys.stderr) + logger.error("Only x86 and ARM64 architectures are currently supported") sys.exit(1) def check_root(): if os.geteuid() != 0: - print("Running as non-root user.", file=sys.stderr) - print("You might have to enter your password one or more times for 'sudo'.", - file=sys.stderr) - print(file=sys.stderr) + logger.info("Running as non-root user.") + logger.info( + "You might have to enter your password one or more times for 'sudo'.\n") def apt_update(options): @@ -463,9 +465,9 @@ def lib_list(): def lib32_list(options): if not options.lib32: - print("Skipping 32-bit libraries.", file=sys.stderr) + logger.info("Skipping 32-bit libraries.") return [] - print("Including 32-bit libraries.", file=sys.stderr) + logger.info("Including 32-bit libraries.") packages = [ # 32-bit libraries needed for a 32-bit build @@ -524,9 +526,9 @@ def lib32_list(options): # added here. def backwards_compatible_list(options): if not options.backwards_compatible: - print("Skipping backwards compatible packages.", file=sys.stderr) + logger.info("Skipping backwards compatible packages.") return [] - print("Including backwards compatible packages.", file=sys.stderr) + logger.info("Including backwards compatible packages.") packages = [ "7za", @@ -687,9 +689,9 @@ def backwards_compatible_list(options): def arm_list(options): if not options.arm: - print("Skipping ARM cross toolchain.", file=sys.stderr) + logger.info("Skipping ARM cross toolchain.") return [] - print("Including ARM cross toolchain.", file=sys.stderr) + logger.info("Including ARM cross toolchain.") # arm cross toolchain packages needed to build chrome on armhf packages = [ @@ -739,9 +741,9 @@ def dbg_package_name(package): def dbg_list(options): if not options.syms: - print("Skipping debugging symbols.", file=sys.stderr) + logger.info("Skipping debugging symbols.") return [] - print("Including debugging symbols.", file=sys.stderr) + logger.info("Including debugging symbols.") packages = [ dbg_package for package in lib_list() @@ -814,25 +816,23 @@ def quick_check(options): unknown.append(p) if not_installed: - print("WARNING: The following packages are not installed:", file=sys.stderr) - print(" ".join(not_installed), file=sys.stderr) + logger.warning("The following packages are not installed:") + logger.warning(" ".join(not_installed)) if unknown: - print("WARNING: The following packages are unknown to your system", - file=sys.stderr) - print("(maybe missing a repo or need to 'sudo apt-get update'):", - file=sys.stderr) - print(" ".join(unknown), file=sys.stderr) + logger.error("The following packages are unknown to your system") + logger.error("(maybe missing a repo or need to `sudo apt-get update`):") + logger.error(" ".join(unknown)) sys.exit(1) def find_missing_packages(options): - print("Finding missing packages...", file=sys.stderr) + logger.info("Finding missing packages...") packages = package_list(options) - packages_str = " ".join(packages) - print("Packages required: " + packages_str, file=sys.stderr) + packages_str = "\n ".join(packages) + logger.info("Packages required:\n " + packages_str) query_cmd = ["apt-get", "--just-print", "install"] + packages env = os.environ.copy() @@ -862,22 +862,24 @@ def install_packages(options): try: packages = find_missing_packages(options) if packages: - quiet = ["-qq", "--assume-yes"] if options.no_prompt else [] - subprocess.check_call(["sudo", "apt-get", "install"] + quiet + packages) - print(file=sys.stderr) + cmd = ["apt-get", "install"] + if options.no_prompt: + cmd = [ + "DEBIAN_FRONTEND=noninteractive", *cmd, "-qq", "--allow-downgrades", + "--assume-yes" + ] + subprocess.check_call(["sudo", *cmd, *packages]) + logger.info("") else: - print("No missing packages, and the packages are up to date.", - file=sys.stderr) + logger.info("No missing packages, and the packages are up to date.") except subprocess.CalledProcessError as e: # An apt-get exit status of 100 indicates that a real error has occurred. - print("`apt-get --just-print install ...` failed", file=sys.stderr) + logger.error("`apt-get --just-print install ...` failed") if e.stdout is not None: - print("It produced the following output:", file=sys.stderr) - print(e.stdout, file=sys.stderr) - print("You will have to install the above packages yourself.", - file=sys.stderr) - print(file=sys.stderr) + logger.error("It produced the following output:\n") + logger.error(e.stdout.decode("utf-8")) + logger.error("You will have to install the above packages yourself.\n") sys.exit(100) @@ -885,9 +887,9 @@ def install_packages(options): # apt-get, since install-chromeos-fonts depends on curl. def install_chromeos_fonts(options): if not options.chromeos_fonts: - print("Skipping installation of Chrome OS fonts.", file=sys.stderr) + logger.info("Skipping installation of Chrome OS fonts.") return - print("Installing Chrome OS fonts.", file=sys.stderr) + logger.info("Installing Chrome OS fonts.") dir = os.path.abspath(os.path.dirname(__file__)) @@ -896,28 +898,25 @@ def install_chromeos_fonts(options): ["sudo", os.path.join(dir, "linux", "install-chromeos-fonts.py")]) except subprocess.CalledProcessError: - print("ERROR: The installation of the Chrome OS default fonts failed.", - file=sys.stderr) + logger.error("The installation of the Chrome OS default fonts failed.") if (subprocess.check_output( ["stat", "-f", "-c", "%T", dir], ).decode().startswith("nfs")): - print( - "The reason is that your repo is installed on a remote file system.", - file=sys.stderr) + logger.error( + "The reason is that your repo is installed on a remote file system.") else: - print( - "This is expected if your repo is installed on a remote file system.", - file=sys.stderr) + logger.info( + "This is expected if your repo is installed on a remote file system.") - print("It is recommended to install your repo on a local file system.", - file=sys.stderr) - print("You can skip the installation of the Chrome OS default fonts with", - file=sys.stderr) - print("the command line option: --no-chromeos-fonts.", file=sys.stderr) + logger.info( + "It is recommended to install your repo on a local file system.") + logger.info( + "You can skip the installation of the Chrome OS default fonts with") + logger.info("the command line option: --no-chromeos-fonts.") sys.exit(1) def install_locales(): - print("Installing locales.", file=sys.stderr) + logger.info("Installing locales.") CHROMIUM_LOCALES = [ "da_DK.UTF-8", "en_US.UTF-8", "fr_FR.UTF-8", "he_IL.UTF-8", "zh_TW.UTF-8" ] @@ -934,7 +933,7 @@ def install_locales(): if locale_gen != old_locale_gen: subprocess.check_call(["sudo", "locale-gen"]) else: - print("Locales already up-to-date.", file=sys.stderr) + logger.info("Locales already up-to-date.") else: for locale in CHROMIUM_LOCALES: subprocess.check_call(["sudo", "locale-gen", locale]) diff --git a/naiveproxy/src/build/linux/BUILD.gn b/naiveproxy/src/build/linux/BUILD.gn index 653951df53..362296ecfd 100644 --- a/naiveproxy/src/build/linux/BUILD.gn +++ b/naiveproxy/src/build/linux/BUILD.gn @@ -26,8 +26,7 @@ if (use_system_freetype) { # the system, use with caution,for details see build/config/freetype/BUILD.gn. pkg_config("freetype_from_pkgconfig") { visibility = [ - "//build/config/freetype:freetype", - "//third_party:freetype_harfbuzz", + "//build/config/freetype", "//third_party/harfbuzz-ng:harfbuzz_source", ] packages = [ "freetype2" ] diff --git a/naiveproxy/src/build/linux/amd64/module.modulemap b/naiveproxy/src/build/linux/amd64/module.modulemap index 1a86045728..d50a3a3a5c 100644 --- a/naiveproxy/src/build/linux/amd64/module.modulemap +++ b/naiveproxy/src/build/linux/amd64/module.modulemap @@ -2,37 +2,84 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -module sysroot_features [system] [extern_c] { +module sysroot_limits [system] [extern_c] { header "../debian_bullseye_amd64-sysroot/usr/include/features.h" + header "../debian_bullseye_amd64-sysroot/usr/include/linux/limits.h" header "../debian_bullseye_amd64-sysroot/usr/include/stdc-predef.h" - header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/sys/cdefs.h" - header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/gnu/stubs.h" + header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/bits/long-double.h" header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/bits/wordsize.h" + header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/gnu/stubs-64.h" + header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/gnu/stubs.h" + header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/sys/cdefs.h" } -module sysroot_bits [system] [extern_c] { - header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/bits/floatn.h" - header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/bits/stdint-intn.h" - header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/bits/stdint-uintn.h" - header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" - header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/bits/pthreadtypes-arch.h" - header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" +module sysroot [system] [extern_c] { + header "../debian_bullseye_amd64-sysroot/usr/include/alloca.h" + header "../debian_bullseye_amd64-sysroot/usr/include/asm-generic/errno-base.h" + header "../debian_bullseye_amd64-sysroot/usr/include/asm-generic/errno.h" + header "../debian_bullseye_amd64-sysroot/usr/include/endian.h" + header "../debian_bullseye_amd64-sysroot/usr/include/linux/errno.h" + header "../debian_bullseye_amd64-sysroot/usr/include/locale.h" + header "../debian_bullseye_amd64-sysroot/usr/include/nl_types.h" header "../debian_bullseye_amd64-sysroot/usr/include/pthread.h" -} - -module sysroot_time [system] [extern_c] { + header "../debian_bullseye_amd64-sysroot/usr/include/setjmp.h" + header "../debian_bullseye_amd64-sysroot/usr/include/signal.h" + header "../debian_bullseye_amd64-sysroot/usr/include/stdc-predef.h" + header "../debian_bullseye_amd64-sysroot/usr/include/stdlib.h" + header "../debian_bullseye_amd64-sysroot/usr/include/stdio.h" + header "../debian_bullseye_amd64-sysroot/usr/include/strings.h" header "../debian_bullseye_amd64-sysroot/usr/include/time.h" - header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/bits/types/struct_timespec.h" - header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/bits/types/struct_timeval.h" -} - -module sysroot_types [system] [extern_c] { - header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/bits/types/__fpos64_t.h" - header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h" - header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/bits/types/__sigset_t.h" + header "../debian_bullseye_amd64-sysroot/usr/include/unistd.h" + header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/asm/errno.h" + header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/gnu/stubs.h" header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/sys/select.h" header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/sys/types.h" - // sys/types.h imports types with a #include that are designed to make be made available to users. - // Eg. if you include sys/types.h, it should give you size_t, but size_t is defined by a transitive dependency. + header "../debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/sys/ucontext.h" + // Needs to be textual due to missing include of stddef.h in pthread.h + textual header "../debian_bullseye_amd64-sysroot/usr/include/sched.h" + // Allow files such as sys/types.h to re-export size_t export * } + +// The following are all textual because they are the subject of include_next +// from a non-textual module. +// eg. usr/include/errno.h is included by std_errno_h +module sysroot_ctype [system] [extern_c] { + textual header "../debian_bullseye_amd64-sysroot/usr/include/ctype.h" +} + +module sysroot_errno [system] [extern_c] { + textual header "../debian_bullseye_amd64-sysroot/usr/include/errno.h" +} + +module sysroot_fenv [system] [extern_c] { + textual header "../debian_bullseye_amd64-sysroot/usr/include/fenv.h" +} + +module sysroot_math [system] [extern_c] { + textual header "../debian_bullseye_amd64-sysroot/usr/include/math.h" +} + +module sysroot_inttypes [system] [extern_c] { + textual header "../debian_bullseye_amd64-sysroot/usr/include/inttypes.h" +} + +module sysroot_string [system] [extern_c] { + textual header "../debian_bullseye_amd64-sysroot/usr/include/string.h" +} + +module sysroot_stdatomic [system] [extern_c] { + textual header "../debian_bullseye_amd64-sysroot/usr/include/stdatomic.h" +} + +module sysroot_stdint [system] [extern_c] { + textual header "../debian_bullseye_amd64-sysroot/usr/include/stdint.h" +} + +module sysroot_uchar [system] [extern_c] { + textual header "../debian_bullseye_amd64-sysroot/usr/include/uchar.h" +} + +module sysroot_wctype [system] [extern_c] { + textual header "../debian_bullseye_amd64-sysroot/usr/include/wctype.h" +} \ No newline at end of file diff --git a/naiveproxy/src/build/linux/sysroot_scripts/sysroot_creator.py b/naiveproxy/src/build/linux/sysroot_scripts/sysroot_creator.py index 5448159208..afc5b2d55b 100755 --- a/naiveproxy/src/build/linux/sysroot_scripts/sysroot_creator.py +++ b/naiveproxy/src/build/linux/sysroot_scripts/sysroot_creator.py @@ -582,17 +582,8 @@ def removing_unnecessary_files(install_root, arch): def strip_sections(install_root: str, arch: str): """ Strips all sections from ELF files except for dynamic linking and - essential sections. Skips static libraries (.a), object files (.o), and a - few files used by other Chromium-related projects. + essential sections. Skips static libraries (.a) and object files (.o). """ - PRESERVED_FILES = ( - # Old debian(bullseye) has ld-2.31.so, - # while in trixie, it is ld-linux-$ARCH.so.2 - r'(libc\.so\.\d)|(libc-\d.\d\d\.so)', - r'(libm\.so\.\d)|(libm-\d.\d\d\.so)', - r'(ld-linux.*\.so\.\d)|(ld-\d.\d\d\.so)', - ) - PRESERVED_SECTIONS = { ".dynamic", ".dynstr", @@ -605,19 +596,9 @@ def strip_sections(install_root: str, arch: str): ".note.gnu.build-id", } - preserved_files_count = 0 - lib_dir = LIB_DIRS[RELEASES[arch]] - lib_arch_path = os.path.join(install_root, lib_dir, TRIPLES[arch]) for root, _, files in os.walk(install_root): for file in files: file_path = os.path.join(root, file) - if file_path.startswith(lib_arch_path): - for preserved in PRESERVED_FILES: - if re.match(preserved, - file) and not os.path.islink(file_path): - preserved_files_count += 1 - continue - if (os.access(file, os.X_OK) or file.endswith((".a", ".o")) or os.path.islink(file_path)): continue @@ -652,10 +633,6 @@ def strip_sections(install_root: str, arch: str): for section in sections_to_remove ] + [file_path]) subprocess.run(objcopy_cmd, check=True, stderr=subprocess.PIPE) - if preserved_files_count != len(PRESERVED_FILES): - raise Exception( - f"Expected file(s) to preserve missing, preserved " + - f"{preserved_files_count}, expected {len(PRESERVED_FILES)}") def record_metadata(install_root: str) -> dict[str, tuple[float, float]]: diff --git a/naiveproxy/src/build/mac/find_sdk.py b/naiveproxy/src/build/mac/find_sdk.py index 3dcc4d5d36..c83a3d1151 100755 --- a/naiveproxy/src/build/mac/find_sdk.py +++ b/naiveproxy/src/build/mac/find_sdk.py @@ -76,12 +76,14 @@ def main(): raise SdkError('Install Xcode, launch it, accept the license ' + 'agreement, and run `sudo xcode-select -s /path/to/Xcode.app` ' + 'to continue.') - sdks = [re.findall('^MacOSX(\d+\.\d+)\.sdk$', s) for s in os.listdir(sdk_dir)] + sdk_dir_list = os.listdir(sdk_dir) + sdks = [re.findall('^MacOSX(\d+\.\d+)\.sdk$', s) for s in sdk_dir_list] sdks = [s[0] for s in sdks if s] # [['10.5'], ['10.6']] => ['10.5', '10.6'] sdks = [s for s in sdks # ['10.5', '10.6'] => ['10.6'] if parse_version(s) >= parse_version(min_sdk_version)] if not sdks: - raise Exception('No %s+ SDK found' % min_sdk_version) + raise Exception( + f'No {min_sdk_version}+ SDK found. {sdk_dir} contains: {sdk_dir_list}') best_sdk = sorted(sdks, key=parse_version)[0] sdk_name = 'MacOSX' + best_sdk + '.sdk' sdk_path = os.path.join(sdk_dir, sdk_name) diff --git a/naiveproxy/src/build/mac_toolchain.py b/naiveproxy/src/build/mac_toolchain.py index 5485da007e..d0645e4fb9 100755 --- a/naiveproxy/src/build/mac_toolchain.py +++ b/naiveproxy/src/build/mac_toolchain.py @@ -33,18 +33,19 @@ def LoadPList(path): return plistlib.load(f) -# This contains binaries from Xcode 16.3 (16E140) along with -# the macOS SDK 15.4 (24E241). To build these packages, see comments in -# build/xcode_binaries.yaml. -# To update the version numbers, open Xcode's "About Xcode" or run -# `xcodebuild -version` for the Xcode version, and run -# `xcrun --show-sdk-version` and `xcrun --show-sdk-build-version`for -# the SDK version. To update the _TAG, use the output of the -# `cipd create` command mentioned in xcode_binaries.yaml; -# it's the part after the colon. +# This contains binaries from Xcode 16.4 (16F6) along with the macOS SDK 15.5 +# (24F74). To build these packages, see comments in build/xcode_binaries.yaml. +# +# To update the version numbers, open Xcode's "About Xcode" or run `xcodebuild +# -version` for the Xcode version, and run `xcrun --show-sdk-version` and `xcrun +# --show-sdk-build-version` for the SDK version. To update the _TAG, use the +# output of the `cipd create` command mentioned in xcode_binaries.yaml; it's the +# part after the colon. Or check the CIPD site +# (https://chrome-infra-packages.appspot.com/) at the path given in +# MAC_BINARIES_LABEL. MAC_BINARIES_LABEL = 'infra_internal/ios/xcode/xcode_binaries/mac-amd64' -MAC_BINARIES_TAG = 'mTokcQKuRc0gN_OU1e_CxtZJq6Gy8TnPTbmjyXA5kR4C' +MAC_BINARIES_TAG = 'F1uq3udJtPSmTDjMME_VqfH5PfdlNy2zKWvgVy-tBZoC' # The toolchain will not be downloaded if the minimum OS version is not met. 19 # is the major version number for macOS 10.15. Xcode 15.0 only runs on macOS diff --git a/naiveproxy/src/build/mcp_servers/.style.yapf b/naiveproxy/src/build/mcp_servers/.style.yapf new file mode 100644 index 0000000000..557fa7bf84 --- /dev/null +++ b/naiveproxy/src/build/mcp_servers/.style.yapf @@ -0,0 +1,2 @@ +[style] +based_on_style = pep8 diff --git a/naiveproxy/src/build/mcp_servers/.vpython3 b/naiveproxy/src/build/mcp_servers/.vpython3 new file mode 100644 index 0000000000..7a04dc99cb --- /dev/null +++ b/naiveproxy/src/build/mcp_servers/.vpython3 @@ -0,0 +1,135 @@ +# This is a vpython "spec" file. +# +# It describes patterns for python wheel dependencies of the python scripts in +# the chromium repo, particularly for dependencies that have compiled components +# (since pure-python dependencies can be easily vendored into third_party). +# +# When vpython is invoked, it finds this file and builds a python VirtualEnv, +# containing all of the dependencies described in this file, fetching them from +# CIPD (the "Chrome Infrastructure Package Deployer" service). Unlike `pip`, +# this never requires the end-user machine to have a working python extension +# compilation environment. All of these packages are built using: +# https://chromium.googlesource.com/infra/infra/+/main/infra/tools/dockerbuild/ +# +# All python scripts in the repo share this same spec, to avoid dependency +# fragmentation. +# +# If you have depot_tools installed in your $PATH, you can invoke python scripts +# in this repo by running them as you normally would run them, except +# substituting `vpython` instead of `python` on the command line, e.g.: +# vpython path/to/script.py some --arguments +# +# Read more about `vpython` and how to modify this file here: +# https://chromium.googlesource.com/infra/infra/+/main/doc/users/vpython.md + +python_version: "3.11" + +# The default set of platforms vpython checks does not yet include mac-arm64. +# Setting `verify_pep425_tag` to the list of platforms we explicitly must support +# allows us to ensure that vpython specs stay mac-arm64-friendly +verify_pep425_tag: [ + {python: "cp311", abi: "cp311", platform: "manylinux1_x86_64"}, + {python: "cp311", abi: "cp311", platform: "linux_arm64"}, + + {python: "cp311", abi: "cp311", platform: "macosx_10_10_intel"}, + {python: "cp311", abi: "cp311", platform: "macosx_11_0_arm64"}, + + {python: "cp311", abi: "cp311", platform: "win32"}, + {python: "cp311", abi: "cp311", platform: "win_amd64"} +] + +# Necessary for all Python-based MCP servers. Subsequent wheels in this block +# are its dependencies. +wheel: < + name: "infra/python/wheels/mcp-py3" + version: "version:1.9.4" +> +wheel: < + name: "infra/python/wheels/annotated-types-py3" + version: "version:0.7.0" +> +wheel: < + name: "infra/python/wheels/anyio-py3" + version: "version:4.9.0" +> +wheel: < + name: "infra/python/wheels/certifi-py3" + version: "version:2025.4.26" +> +wheel: < + name: "infra/python/wheels/click-py3" + version: "version:8.0.3" +> +wheel: < + name: "infra/python/wheels/colorama-py2_py3" + version: "version:0.4.1" +> +wheel: < + name: "infra/python/wheels/h11-py3" + version: "version:0.16.0" +> +wheel: < + name: "infra/python/wheels/httpcore-py3" + version: "version:1.0.9" +> +wheel: < + name: "infra/python/wheels/httpx-py3" + version: "version:0.28.1" +> +wheel: < + name: "infra/python/wheels/httpx_sse-py3" + version: "version:0.4.1" +> +wheel: < + name: "infra/python/wheels/idna-py3" + version: "version:3.4" +> +wheel: < + name: "infra/python/wheels/pydantic-py3" + version: "version:2.11.7" +> +wheel: < + name: "infra/python/wheels/pydantic_core/${vpython_platform}" + version: "version:2.33.2" +> +wheel: < + name: "infra/python/wheels/pydantic-settings-py3" + version: "version:2.10.1" +> +wheel: < + name: "infra/python/wheels/python-dotenv-py3" + version: "version:1.1.1" +> +wheel: < + name: "infra/python/wheels/python-multipart-py3" + version: "version:0.0.20" +> +wheel: < + name: "infra/python/wheels/sniffio-py3" + version: "version:1.3.0" +> +wheel: < + name: "infra/python/wheels/sse-starlette-py3" + version: "version:2.4.1" +> +wheel: < + name: "infra/python/wheels/starlette-py3" + version: "version:0.47.1" +> +wheel: < + name: "infra/python/wheels/typing-extensions-py3" + version: "version:4.13.2" +> +wheel: < + name: "infra/python/wheels/typing-inspection-py3" + version: "version:0.4.1" +> +wheel: < + name: "infra/python/wheels/uvicorn-py3" + version: "version:0.35.0" +> + +wheel: < + name: "infra/python/wheels/pyfakefs-py3" + version: "version:5.5.0" +> \ No newline at end of file diff --git a/naiveproxy/src/build/mcp_servers/OWNERS b/naiveproxy/src/build/mcp_servers/OWNERS new file mode 100644 index 0000000000..51da76f8de --- /dev/null +++ b/naiveproxy/src/build/mcp_servers/OWNERS @@ -0,0 +1 @@ +bsheedy@chromium.org \ No newline at end of file diff --git a/naiveproxy/src/build/mcp_servers/PRESUBMIT.py b/naiveproxy/src/build/mcp_servers/PRESUBMIT.py new file mode 100644 index 0000000000..827fe56e86 --- /dev/null +++ b/naiveproxy/src/build/mcp_servers/PRESUBMIT.py @@ -0,0 +1,45 @@ +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""Presubmit script for //build/mcp_servers. + +See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts +for more details about the presubmit API built into depot_tools. +""" + +PRESUBMIT_VERSION = '2.0.0' + + +def _GetChromiumSrcPath(input_api): + """Returns the path to the Chromium src directory.""" + return input_api.os_path.realpath( + input_api.os_path.join(input_api.PresubmitLocalPath(), '..', '..')) + + +def CheckUnittests(input_api, output_api): + """Runs all unittests in the directory and subdirectories.""" + return input_api.canned_checks.RunUnitTestsInDirectory( + input_api, + output_api, + input_api.PresubmitLocalPath(), + [r'^.+_unittest\.py$'], + ) + + +def CheckPylint(input_api, output_api): + """Runs pylint on all directory content and subdirectories.""" + chromium_src_path = _GetChromiumSrcPath(input_api) + extra_path_components = [ + ('build', ), + ] + extra_paths = [ + input_api.os_path.join(chromium_src_path, *component) + for component in extra_path_components + ] + pylint_checks = input_api.canned_checks.GetPylint( + input_api, + output_api, + extra_paths_list=extra_paths, + pylintrc='pylintrc', + version='3.2') + return input_api.RunTests(pylint_checks) diff --git a/naiveproxy/src/build/mcp_servers/build_information.py b/naiveproxy/src/build/mcp_servers/build_information.py new file mode 100755 index 0000000000..ca21b0fa5f --- /dev/null +++ b/naiveproxy/src/build/mcp_servers/build_information.py @@ -0,0 +1,259 @@ +#!/usr/bin/env vpython3 +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""MCP server for providing information relevant to Chromium builds.""" + +import enum +import glob +import os +import platform +import re +import sys + +# vpython-provided modules +# pylint: disable=import-error +from mcp.server import fastmcp +# pylint: enable=import-error + +# pylint: disable=wrong-import-position +sys.path.insert(0, + os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) +import gn_helpers +# pylint: enable=wrong-import-position + +CHROMIUM_ROOT = os.path.realpath( + os.path.join(os.path.dirname(__file__), '..', '..')) + +GN_ARGS_FILE = 'args.gn' + +TARGET_OS_REGEX = re.compile(r'^\s*target_os\s*=\s*\"(\w*)\"\s*$') +TARGET_CPU_REGEX = re.compile(r'^\s*target_cpu\s*=\s*\"((?:\w|\d)*)\"\s*$') +IMPORT_REGEX = re.compile(r'^\s*import\(\"//([^\"]+)\"\)$') + + +class Architecture(enum.Enum): + UNKNOWN = 0 + INTEL = 1 + ARM = 2 + + +class Bitness(enum.Enum): + UNKNOWN = 0 + THIRTY_TWO = 1 + SIXTY_FOUR = 2 + + +class ValidOs(enum.StrEnum): + UNKNOWN = 'unknown' + LINUX = 'linux' + MAC = 'mac' + WIN = 'win' + + +class ValidArch(enum.StrEnum): + UNKNOWN = 'unknown' + ARM = 'arm' + ARM64 = 'arm64' + X86 = 'x86' + X64 = 'x64' + + +mcp = fastmcp.FastMCP(name="Chromium Build Information") + + +# This tool can be moved to a resource once Gemini CLI supports them. +@mcp.tool() +def get_host_os() -> str: + """Retrieves the operating system used by the current host. The return + value is directly comparable with the target_os GN arg, except in the case + of 'unknown'.""" + current_platform = sys.platform + if current_platform in ('linux', 'cygwin'): + return ValidOs.LINUX + if current_platform == 'win32': + return ValidOs.WIN + if current_platform == 'darwin': + return ValidOs.MAC + return ValidOs.UNKNOWN + + +# This tool can be moved to a resource once Gemini CLI supports them. +@mcp.tool() +def get_host_arch() -> str: + """Retrieves the CPU architecture used by the current host. The return + value is directly comparable with the target_cpu GN arg, except in the + case of 'unknown'.""" + arch = _get_host_architecture() + bits = _get_host_bits() + + match (arch, bits): + case (Architecture.INTEL, Bitness.THIRTY_TWO): + return ValidArch.X86 + case (Architecture.INTEL, Bitness.SIXTY_FOUR): + return ValidArch.X64 + case (Architecture.ARM, Bitness.THIRTY_TWO): + return ValidArch.ARM + case (Architecture.ARM, Bitness.SIXTY_FOUR): + return ValidArch.ARM64 + case _: + return ValidArch.UNKNOWN + + +def _get_host_architecture() -> Architecture: + """Helper to retrieve the primary CPU architecture for the host. + + Does not include any bitness information. + + Returns: + An Architecture enum value corresponding to the found architecture. + """ + native_arm = platform.machine().lower() in ('arm', 'arm64') + # This is necessary for the case of running x86 Python on arm devices via + # an emulator. In this case, platform.machine() will show up as an x86 + # processor. + emulated_x86 = 'armv8' in platform.processor().lower() + if native_arm or emulated_x86: + return Architecture.ARM + + native_x86 = platform.machine().lower() in ('x86', 'x86_64', 'amd64') + if native_x86: + return Architecture.INTEL + + return Architecture.UNKNOWN + + +def _get_host_bits() -> Bitness: + """Helper to retrieve the CPU bitness for the host. + + Returns: + A Bitness enum value corresponding to the found bitness. + """ + # Per the Python documentation for platform.architecture(), the most + # reliable to get the bitness of the Python interpreter is to check + # sys.maxsize. + is_64bits = sys.maxsize > 2**32 + if is_64bits: + return Bitness.SIXTY_FOUR + return Bitness.THIRTY_TWO + + +# This tool can be moved to a resource once Gemini CLI supports them. +@mcp.tool() +def get_all_build_directories() -> list[str]: + """Retrieves a list of all valid build/output directories within the repo. + Returned paths are relative to the chromium/src root directory.""" + return _get_standard_build_directories() + _get_cros_build_directories() + + +# This tool can be moved to a resource once Gemini CLI supports them. +@mcp.tool() +def get_valid_build_directories_for_config(target_os: str, + target_cpu: str) -> list[str]: + """Retrieves a list of all valid build/output directories within the repo + that can be used to compile for the provided operatying system and + architecture. Returned paths are relative to the chromium/src root + directory.""" + valid_directories = [] + for d in get_all_build_directories(): + abspath = os.path.join(CHROMIUM_ROOT, d) + if _directory_builds_for_config(abspath, target_os, target_cpu): + valid_directories.append(d) + return valid_directories + + +# This tool can be moved to a resource once Gemini CLI supports them. +@mcp.tool() +def get_valid_build_directories_for_current_host() -> list[str]: + """Retrieves a list of all valid build/output directories within the repo + that can be used to compile for the current host. This is equivalent to + running the get_valid_build_directories_for_config tool with the host's + information. Returned paths are relative to the chromium/src root + directory.""" + host_os = get_host_os() + if host_os == ValidOs.UNKNOWN: + return [] + host_arch = get_host_arch() + if host_arch == ValidArch.UNKNOWN: + return [] + return get_valid_build_directories_for_config(host_os, host_arch) + + +def _get_standard_build_directories() -> list[str]: + """Gets all valid output directories under out/. + + Returns: + A list of strings, each element containing a relative path from the + Chromium root directory to a valid output directory. + """ + return _get_build_directories_under_dir('out') + + +def _get_cros_build_directories() -> list[str]: + """Gets all valid CrOS output directories. + + By convention, CrOS builds in out_ directories instead of in + the out/ directory. + + Returns: + A list of strings, each element containing a relative path from the + Chromium root directory to a valid output directory. + """ + return _get_build_directories_under_dir('out_*') + + +def _get_build_directories_under_dir(directory: str) -> list[str]: + """Gets all valid output directories under the specified |directory|. + + Args: + directory: A relative path to a directory under the Chromium root + directory. + + Returns: + A list of strings, each element containing a relative path from the + Chromium root directory to a valid output directory. + """ + valid_directories = [] + valid_args_files = glob.glob( + os.path.join(CHROMIUM_ROOT, directory, '*', GN_ARGS_FILE)) + for vaf in valid_args_files: + valid_directories.append( + os.path.relpath(os.path.dirname(vaf), CHROMIUM_ROOT)) + return valid_directories + + +def _directory_builds_for_config(directory: str, target_os: str, + target_cpu: str) -> bool: + """Checks whether the specified directory builds for the specified config. + + Args: + directory: The output directory to check. + target_os: The target_os GN arg value to look for. + target_cpu: The target_cpu GN arg value to look for. + + Returns: + True if |directory| builds for |target_os| and |target_cpu|, otherwise + False. + """ + args_file = os.path.join(directory, GN_ARGS_FILE) + try: + with open(args_file, encoding='utf-8') as infile: + contents = infile.read() + except OSError: + return False + + try: + gn_args = gn_helpers.FromGNArgs(contents) + except (gn_helpers.GNError, OSError): + return False + + if gn_args.get('target_os', get_host_os()) != target_os: + return False + if gn_args.get('target_cpu', get_host_arch()) != target_cpu: + return False + + return True + + +if __name__ == '__main__': + mcp.run() diff --git a/naiveproxy/src/build/mcp_servers/build_information_unittest.py b/naiveproxy/src/build/mcp_servers/build_information_unittest.py new file mode 100755 index 0000000000..83431b8357 --- /dev/null +++ b/naiveproxy/src/build/mcp_servers/build_information_unittest.py @@ -0,0 +1,537 @@ +#!/usr/bin/env vpython3 +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""Unittests for build_information.py.""" + +# pylint: disable=protected-access + +import os +import sys +import unittest +from unittest import mock + +# vpython-provided modules +# pylint: disable=import-error +from pyfakefs import fake_filesystem_unittest +# pylint: enable=import-error + +# pylint: disable=wrong-import-position +sys.path.insert(0, + os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) +from mcp_servers import build_information +# pylint: enable=wrong-import-position + +CHROMIUM_ROOT = build_information.CHROMIUM_ROOT + + +class GetHostOsTest(unittest.TestCase): + + @mock.patch('sys.platform', 'linux') + def test_get_host_os_linux(self): + """Test get_host_os on linux.""" + self.assertEqual(build_information.get_host_os(), + build_information.ValidOs.LINUX) + + @mock.patch('sys.platform', 'cygwin') + def test_get_host_os_cygwin_is_linux(self): + """Test get_host_os on cygwin returns linux.""" + self.assertEqual(build_information.get_host_os(), + build_information.ValidOs.LINUX) + + @mock.patch('sys.platform', 'win32') + def test_get_host_os_win(self): + """Test get_host_os on windows.""" + self.assertEqual(build_information.get_host_os(), + build_information.ValidOs.WIN) + + @mock.patch('sys.platform', 'darwin') + def test_get_host_os_mac(self): + """Test get_host_os on mac.""" + self.assertEqual(build_information.get_host_os(), + build_information.ValidOs.MAC) + + @mock.patch('sys.platform', 'freebsd') + def test_get_host_os_unknown(self): + """Test get_host_os on an unknown os.""" + self.assertEqual(build_information.get_host_os(), + build_information.ValidOs.UNKNOWN) + + +class GetHostArchTest(unittest.TestCase): + + @mock.patch('mcp_servers.build_information._get_host_bits', + return_value=build_information.Bitness.SIXTY_FOUR) + @mock.patch('mcp_servers.build_information._get_host_architecture', + return_value=build_information.Architecture.INTEL) + def test_get_host_arch_x64(self, _mock_arch, _mock_bits): + """Test get_host_arch for x64.""" + self.assertEqual(build_information.get_host_arch(), + build_information.ValidArch.X64) + + @mock.patch('mcp_servers.build_information._get_host_bits', + return_value=build_information.Bitness.THIRTY_TWO) + @mock.patch('mcp_servers.build_information._get_host_architecture', + return_value=build_information.Architecture.INTEL) + def test_get_host_arch_x86(self, _mock_arch, _mock_bits): + """Test get_host_arch for x86.""" + self.assertEqual(build_information.get_host_arch(), + build_information.ValidArch.X86) + + @mock.patch('mcp_servers.build_information._get_host_bits', + return_value=build_information.Bitness.SIXTY_FOUR) + @mock.patch('mcp_servers.build_information._get_host_architecture', + return_value=build_information.Architecture.ARM) + def test_get_host_arch_arm64(self, _mock_arch, _mock_bits): + """Test get_host_arch for arm64.""" + self.assertEqual(build_information.get_host_arch(), + build_information.ValidArch.ARM64) + + @mock.patch('mcp_servers.build_information._get_host_bits', + return_value=build_information.Bitness.THIRTY_TWO) + @mock.patch('mcp_servers.build_information._get_host_architecture', + return_value=build_information.Architecture.ARM) + def test_get_host_arch_arm(self, _mock_arch, _mock_bits): + """Test get_host_arch for arm.""" + self.assertEqual(build_information.get_host_arch(), + build_information.ValidArch.ARM) + + @mock.patch('mcp_servers.build_information._get_host_bits') + @mock.patch('mcp_servers.build_information._get_host_architecture', + return_value=build_information.Architecture.UNKNOWN) + def test_get_host_arch_unknown_arch(self, _mock_arch, _mock_bits): + """Test get_host_arch for unknown architecture.""" + self.assertEqual(build_information.get_host_arch(), + build_information.ValidArch.UNKNOWN) + + @mock.patch('mcp_servers.build_information._get_host_bits', + return_value=build_information.Bitness.UNKNOWN) + @mock.patch('mcp_servers.build_information._get_host_architecture', + return_value=build_information.Architecture.INTEL) + def test_get_host_arch_intel_unknown_bits(self, _mock_arch, _mock_bits): + """Test get_host_arch for intel with unknown bitness.""" + self.assertEqual(build_information.get_host_arch(), + build_information.ValidArch.UNKNOWN) + + @mock.patch('mcp_servers.build_information._get_host_bits', + return_value=build_information.Bitness.UNKNOWN) + @mock.patch('mcp_servers.build_information._get_host_architecture', + return_value=build_information.Architecture.ARM) + def test_get_host_arch_arm_unknown_bits(self, _mock_arch, _mock_bits): + """Test get_host_arch for arm with unknown bitness.""" + self.assertEqual(build_information.get_host_arch(), + build_information.ValidArch.UNKNOWN) + + +class GetHostArchitectureTest(unittest.TestCase): + + @mock.patch('platform.processor', return_value='GenuineIntel') + @mock.patch('platform.machine', return_value='x86_64') + def test_get_host_architecture_intel_x64(self, _mock_machine, + _mock_processor): + """Test _get_host_architecture for intel x64.""" + self.assertEqual(build_information._get_host_architecture(), + build_information.Architecture.INTEL) + + @mock.patch('platform.processor', return_value='GenuineIntel') + @mock.patch('platform.machine', return_value='x86') + def test_get_host_architecture_intel_x86(self, _mock_machine, + _mock_processor): + """Test _get_host_architecture for intel x86.""" + self.assertEqual(build_information._get_host_architecture(), + build_information.Architecture.INTEL) + + @mock.patch('platform.processor', return_value='AuthenticAMD') + @mock.patch('platform.machine', return_value='amd64') + def test_get_host_architecture_intel_amd64(self, _mock_machine, + _mock_processor): + """Test _get_host_architecture for intel amd64.""" + self.assertEqual(build_information._get_host_architecture(), + build_information.Architecture.INTEL) + + @mock.patch('platform.processor', return_value='Apple M1') + @mock.patch('platform.machine', return_value='arm64') + def test_get_host_architecture_arm_native_arm64(self, _mock_machine, + _mock_processor): + """Test _get_host_architecture for native arm64.""" + self.assertEqual(build_information._get_host_architecture(), + build_information.Architecture.ARM) + + @mock.patch('platform.processor', return_value='ARMv7') + @mock.patch('platform.machine', return_value='arm') + def test_get_host_architecture_arm_native_arm(self, _mock_machine, + _mock_processor): + """Test _get_host_architecture for native arm.""" + self.assertEqual(build_information._get_host_architecture(), + build_information.Architecture.ARM) + + @mock.patch('platform.processor', return_value='... armv8 ...') + @mock.patch('platform.machine', return_value='x86_64') + def test_get_host_architecture_arm_emulated_x86(self, _mock_machine, + _mock_processor): + """Test _get_host_architecture for emulated x86 on arm.""" + self.assertEqual(build_information._get_host_architecture(), + build_information.Architecture.ARM) + + @mock.patch('platform.processor', return_value='mips') + @mock.patch('platform.machine', return_value='mips') + def test_get_host_architecture_unknown(self, _mock_machine, + _mock_processor): + """Test _get_host_architecture for an unknown architecture.""" + self.assertEqual(build_information._get_host_architecture(), + build_information.Architecture.UNKNOWN) + + +class GetHostBitsTest(unittest.TestCase): + + @mock.patch('sys.maxsize', 2**32 + 1) + def test_get_host_bits_64(self): + """Test _get_host_bits for 64-bit.""" + self.assertEqual(build_information._get_host_bits(), + build_information.Bitness.SIXTY_FOUR) + + @mock.patch('sys.maxsize', 2**32 - 1) + def test_get_host_bits_32(self): + """Test _get_host_bits for 32-bit.""" + self.assertEqual(build_information._get_host_bits(), + build_information.Bitness.THIRTY_TWO) + + +class GetAllBuildDirectoriesTest(fake_filesystem_unittest.TestCase): + + def setUp(self): + self.setUpPyfakefs() + self.fs.create_dir(CHROMIUM_ROOT) + + def test_get_all_build_directories(self): + """Test getting all build directories (standard and CrOS).""" + self.fs.create_file( + os.path.join(CHROMIUM_ROOT, 'out', 'Debug', 'args.gn')) + self.fs.create_file( + os.path.join(CHROMIUM_ROOT, 'out_cros', 'Debug', 'args.gn')) + dirs = build_information.get_all_build_directories() + self.assertEqual( + set(dirs), + {os.path.join('out', 'Debug'), + os.path.join('out_cros', 'Debug')}) + + +class GetValidBuildDirectoriesForConfigTest(fake_filesystem_unittest.TestCase): + + def setUp(self): + self.setUpPyfakefs() + self.fs.create_dir(CHROMIUM_ROOT) + + # Matching dir + self.fs.create_file(os.path.join(CHROMIUM_ROOT, 'out', 'Linux_x64', + 'args.gn'), + contents='target_os = "linux"\ntarget_cpu = "x64"') + # Mismatching os + self.fs.create_file(os.path.join(CHROMIUM_ROOT, 'out', 'Win_x64', + 'args.gn'), + contents='target_os = "win"\ntarget_cpu = "x64"') + # Mismatching cpu + self.fs.create_file( + os.path.join(CHROMIUM_ROOT, 'out', 'Linux_arm64', 'args.gn'), + contents='target_os = "linux"\ntarget_cpu = "arm64"') + # No args specified (should match) + self.fs.create_file(os.path.join(CHROMIUM_ROOT, 'out', 'Default', + 'args.gn'), + contents='is_debug = true') + # CrOS dir that matches + self.fs.create_file(os.path.join(CHROMIUM_ROOT, 'out_cros', + 'linux_x64', 'args.gn'), + contents='target_os = "linux"\ntarget_cpu = "x64"') + # Dir with no args.gn + self.fs.create_dir(os.path.join(CHROMIUM_ROOT, 'out', 'NoArgs')) + + @mock.patch('mcp_servers.build_information.get_host_arch', + return_value='x64') + @mock.patch('mcp_servers.build_information.get_host_os', + return_value='linux') + def test_get_valid_build_information(self, _, __): + """Test getting valid build directories for a specific config.""" + dirs = build_information.get_valid_build_directories_for_config( + 'linux', 'x64') + self.assertEqual( + set(dirs), { + os.path.join('out', 'Linux_x64'), + os.path.join('out', 'Default'), + os.path.join('out_cros', 'linux_x64') + }) + + +class GetValidBuildDirectoriesForCurrentHostTest(unittest.TestCase): + + @mock.patch( + 'mcp_servers.build_information.get_valid_build_directories_for_config') + @mock.patch('mcp_servers.build_information.get_host_arch') + @mock.patch('mcp_servers.build_information.get_host_os') + def test_valid_host_info(self, mock_get_os, mock_get_arch, + mock_get_valid_dirs): + """Test getting dirs for current host with valid host info.""" + mock_get_os.return_value = build_information.ValidOs.LINUX + mock_get_arch.return_value = build_information.ValidArch.X64 + mock_get_valid_dirs.return_value = ['out/Release'] + + result = ( + build_information.get_valid_build_directories_for_current_host()) + + mock_get_valid_dirs.assert_called_once_with('linux', 'x64') + self.assertEqual(result, ['out/Release']) + + @mock.patch('mcp_servers.build_information.get_host_arch') + @mock.patch('mcp_servers.build_information.get_host_os') + def test_unknown_os(self, mock_get_os, mock_get_arch): + """Test getting dirs for host with unknown OS returns empty list.""" + mock_get_os.return_value = build_information.ValidOs.UNKNOWN + mock_get_arch.return_value = build_information.ValidArch.X64 + + result = ( + build_information.get_valid_build_directories_for_current_host()) + self.assertEqual(result, []) + + @mock.patch('mcp_servers.build_information.get_host_arch') + @mock.patch('mcp_servers.build_information.get_host_os') + def test_unknown_arch(self, mock_get_os, mock_get_arch): + """Test getting dirs for host with unknown arch returns empty list.""" + mock_get_os.return_value = build_information.ValidOs.LINUX + mock_get_arch.return_value = build_information.ValidArch.UNKNOWN + + result = ( + build_information.get_valid_build_directories_for_current_host()) + self.assertEqual(result, []) + + +class GetStandardBuildDirectoriesTest(fake_filesystem_unittest.TestCase): + + def setUp(self): + self.setUpPyfakefs() + self.fs.create_dir(CHROMIUM_ROOT) + + def test_get_standard_build_directories(self): + """Test getting standard build directories.""" + self.fs.create_file( + os.path.join(CHROMIUM_ROOT, 'out', 'Debug', 'args.gn')) + self.fs.create_file( + os.path.join(CHROMIUM_ROOT, 'out_cros', 'Debug', 'args.gn')) + dirs = build_information._get_standard_build_directories() + self.assertEqual(set(dirs), {os.path.join('out', 'Debug')}) + + +class GetCrosBuildDirectoriesTest(fake_filesystem_unittest.TestCase): + + def setUp(self): + self.setUpPyfakefs() + self.fs.create_dir(CHROMIUM_ROOT) + + def test_get_cros_build_directories(self): + """Test getting CrOS build directories.""" + self.fs.create_file( + os.path.join(CHROMIUM_ROOT, 'out', 'Debug', 'args.gn')) + self.fs.create_file( + os.path.join(CHROMIUM_ROOT, 'out_cros', 'Debug', 'args.gn')) + dirs = build_information._get_cros_build_directories() + self.assertEqual(set(dirs), {os.path.join('out_cros', 'Debug')}) + + +class GetBuildDirectoriesUnderDirTest(fake_filesystem_unittest.TestCase): + + def setUp(self): + self.setUpPyfakefs() + self.fs.create_dir(CHROMIUM_ROOT) + + def test_get_build_directories_under_dir_no_directories(self): + """Test behavior with no valid dirs.""" + self.fs.create_dir(os.path.join(CHROMIUM_ROOT, 'out')) + self.assertEqual( + build_information._get_build_directories_under_dir('out'), []) + + def test_get_build_directories_under_dir_multiple_valid(self): + """Test behavior with multiple valid dirs.""" + self.fs.create_file( + os.path.join(CHROMIUM_ROOT, 'out', 'Debug', 'args.gn')) + self.fs.create_file( + os.path.join(CHROMIUM_ROOT, 'out', 'Release', 'args.gn')) + self.assertEqual( + set(build_information._get_build_directories_under_dir('out')), + {os.path.join('out', 'Debug'), + os.path.join('out', 'Release')}) + + def test_get_build_directories_under_dir_with_invalid(self): + """Test behavior with a mix of valid/invalid dirs.""" + self.fs.create_dir(os.path.join(CHROMIUM_ROOT, 'out', 'Debug')) + self.fs.create_file( + os.path.join(CHROMIUM_ROOT, 'out', 'Release', 'args.gn')) + self.assertEqual( + build_information._get_build_directories_under_dir('out'), + [os.path.join('out', 'Release')]) + + def test_get_build_directories_under_dir_with_glob(self): + """Test behavior with a glob pattern.""" + self.fs.create_file( + os.path.join(CHROMIUM_ROOT, 'out_foo', 'Debug', 'args.gn')) + self.fs.create_file( + os.path.join(CHROMIUM_ROOT, 'out_bar', 'Release', 'args.gn')) + self.fs.create_dir(os.path.join(CHROMIUM_ROOT, 'out_baz', 'Debug')) + self.assertEqual( + set(build_information._get_build_directories_under_dir('out_*')), { + os.path.join('out_foo', 'Debug'), + os.path.join('out_bar', 'Release') + }) + + +class DirectoryBuildsForConfigTest(fake_filesystem_unittest.TestCase): + + def setUp(self): + self.setUpPyfakefs() + self.fs.create_dir(CHROMIUM_ROOT) + self.build_dir = os.path.join(CHROMIUM_ROOT, 'out', 'Release') + self.fs.create_dir(self.build_dir) + self.args_gn_path = os.path.join(self.build_dir, 'args.gn') + + self.os_patcher = mock.patch( + 'mcp_servers.build_information.get_host_os', return_value='linux') + self.os_mock = self.os_patcher.start() + self.addCleanup(self.os_patcher.stop) + self.arch_patcher = mock.patch( + 'mcp_servers.build_information.get_host_arch', return_value='x64') + self.arch_mock = self.arch_patcher.start() + self.addCleanup(self.arch_patcher.stop) + + def test_no_args_gn_file(self): + """Test directory without args.gn returns False.""" + self.assertFalse( + build_information._directory_builds_for_config( + self.build_dir, 'linux', 'x64')) + + def test_empty_args_gn_matching_defaults(self): + """Test empty args.gn is true if defaults match requested config.""" + self.fs.create_file(self.args_gn_path, contents='') + self.assertTrue( + build_information._directory_builds_for_config( + self.build_dir, 'linux', 'x64')) + self.os_mock.assert_called_once() + self.arch_mock.assert_called_once() + + def test_empty_args_gn_mismatching_os_default(self): + """Test empty args.gn is false if default os mismatches.""" + self.os_mock.return_value = 'win' + self.fs.create_file(self.args_gn_path, contents='') + self.assertFalse( + build_information._directory_builds_for_config( + self.build_dir, 'linux', 'x64')) + self.os_mock.assert_called_once() + + def test_empty_args_gn_mismatching_cpu_default(self): + """Test empty args.gn is false if default cpu mismatches.""" + self.arch_mock.return_value = 'arm64' + self.fs.create_file(self.args_gn_path, contents='') + self.assertFalse( + build_information._directory_builds_for_config( + self.build_dir, 'linux', 'x64')) + self.os_mock.assert_called_once() + self.arch_mock.assert_called_once() + + def test_matching_os_and_cpu(self): + """Test args.gn with matching os and cpu.""" + self.fs.create_file(self.args_gn_path, + contents='target_os = "linux"\ntarget_cpu = "x64"') + self.assertTrue( + build_information._directory_builds_for_config( + self.build_dir, 'linux', 'x64')) + + def test_mismatching_os(self): + """Test args.gn with mismatching os.""" + self.fs.create_file(self.args_gn_path, + contents='target_os = "win"\ntarget_cpu = "x64"') + self.assertFalse( + build_information._directory_builds_for_config( + self.build_dir, 'linux', 'x64')) + + def test_mismatching_cpu(self): + """Test args.gn with mismatching cpu.""" + self.fs.create_file( + self.args_gn_path, + contents='target_os = "linux"\ntarget_cpu = "arm64"') + self.assertFalse( + build_information._directory_builds_for_config( + self.build_dir, 'linux', 'x64')) + + def test_only_os_matching_cpu_default(self): + """Test only os in args.gn is true if default cpu matches.""" + self.fs.create_file(self.args_gn_path, contents='target_os = "linux"') + self.assertTrue( + build_information._directory_builds_for_config( + self.build_dir, 'linux', 'x64')) + self.arch_mock.assert_called_once() + + def test_only_os_mismatching_cpu_default(self): + """Test only os in args.gn is false if default cpu mismatches.""" + self.arch_mock.return_value = 'arm64' + self.fs.create_file(self.args_gn_path, contents='target_os = "linux"') + self.assertFalse( + build_information._directory_builds_for_config( + self.build_dir, 'linux', 'x64')) + self.arch_mock.assert_called_once() + + def test_only_cpu_matching_os_default(self): + """Test only cpu in args.gn is true if default os matches.""" + self.fs.create_file(self.args_gn_path, contents='target_cpu = "x64"') + self.assertTrue( + build_information._directory_builds_for_config( + self.build_dir, 'linux', 'x64')) + self.os_mock.assert_called_once() + + def test_only_cpu_mismatching_os_default(self): + """Test only cpu in args.gn is false if default os mismatches.""" + self.os_mock.return_value = 'win' + self.fs.create_file(self.args_gn_path, contents='target_cpu = "x64"') + self.assertFalse( + build_information._directory_builds_for_config( + self.build_dir, 'linux', 'x64')) + self.os_mock.assert_called_once() + + def test_with_import_matching(self): + """Test matching config from an imported .gni file.""" + gni_import_path = '//build/config.gni' + gni_path = os.path.join(CHROMIUM_ROOT, 'build', 'config.gni') + self.fs.create_file(gni_path, contents='target_os = "linux"') + self.fs.create_file( + self.args_gn_path, + contents=f'import("{gni_import_path}")\ntarget_cpu = "x64"') + self.assertTrue( + build_information._directory_builds_for_config( + self.build_dir, 'linux', 'x64')) + + def test_with_import_mismatching(self): + """Test mismatching config from an imported .gni file.""" + gni_import_path = '//build/config.gni' + gni_path = os.path.join(CHROMIUM_ROOT, 'build', 'config.gni') + self.fs.create_file(gni_path, contents='target_os = "win"') + self.fs.create_file( + self.args_gn_path, + contents=f'import("{gni_import_path}")\ntarget_cpu = "x64"') + self.assertFalse( + build_information._directory_builds_for_config( + self.build_dir, 'linux', 'x64')) + + def test_with_nonexistent_import(self): + """Test args.gn with a non-existent import returns False.""" + self.fs.create_file(self.args_gn_path, + contents='import("//build/nonexistent.gni")') + self.assertFalse( + build_information._directory_builds_for_config( + self.build_dir, 'linux', 'x64')) + + def test_with_malformed_file(self): + """Test that a malformed args.gn returns False.""" + self.fs.create_file(self.args_gn_path, + contents='target_os = "linux"\nasdf asdf') + self.assertFalse( + build_information._directory_builds_for_config( + self.build_dir, 'linux', 'x64')) + + +if __name__ == '__main__': + unittest.main() diff --git a/naiveproxy/src/build/mcp_servers/pylintrc b/naiveproxy/src/build/mcp_servers/pylintrc new file mode 100644 index 0000000000..be14919909 --- /dev/null +++ b/naiveproxy/src/build/mcp_servers/pylintrc @@ -0,0 +1,251 @@ +[MAIN] + +# Pickle collected data for later comparisons. +persistent=yes + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + pylint_quotes, + pylint.extensions.no_self_use + +# Configure quote preferences. +string-quote = single-avoid-escape +triple-quote = double +docstring-quote = double + +[MESSAGES CONTROL] + +# Disable the message, report, category or checker with the given id(s). +disable=duplicate-code, + fixme, + invalid-name, + locally-disabled, + locally-enabled, + missing-docstring, + too-few-public-methods, + too-many-instance-attributes, + +# Pylint, or at least v1.5.6, does not properly handle adding comments between +# lines of disable= entries, nor does it allow multiple disable= lines, so +# we can't comment inline about why any of the above can't be removed. Thus, +# that information is here. + +# duplicate-code +# There is a bug in Pylint that prevents duplicate-code from being disabled for +# blocks of code, see https://github.com/PyCQA/pylint/issues/214. Since +# duplicate-code causes parts of the harness_script strings to be detected as +# duplicates, and there isn't a good solution to actually fix that, we need to +# keep this disabled until a fix is implemented and the Pylint version we use is +# upgraded. + +# fixme +# This complains about TODOs, which are perfectly valid to have. + +# invalid-name +# The default regular expressions for name validation don't like the conventions +# many Chromium Python files use, namely the use of upper camel case for method +# names. The regular expressions could be updated to handle this properly, but +# that would likely be part of a repo-wide linter update. + +# locally-disabled/locally-enabled +# There are valid cases where we want to selectively enable/disable lint errors +# in a particular file/scope, e.g. allowing protected access in unittests. + +# missing-docstring +# Docstrings are important, and proper use of them should be enforced. However, +# requiring a docstring on *every* method and class is overkill, as many are +# self-documenting due to being short and well-named. + +# too-few-public-methods +# This is supposedly to catch "functions disguised as classes", but we have +# never had issues with that. We do, however, use a handful of struct-like +# classes, which this complains about. + +# too-many-instance-attributes +# Only ends up complaining about struct-like classes. So, like +# too-few-public-methods, leave disabled instead of disabling on a per-class +# basis. + +# Other notes + +# too-many-arguments +# This one is borderline. There are legitimate cases of having too many +# arguments, but it also tends to flag cases that can't be fixed more often +# than fixable issues. There also doesn't appear to be an easy way to bump up +# the limit, as 5 is pretty small. + + +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html +output-format=text + +# Put messages in a separate file for each module / package specified on the +# command line instead of printing them on stdout. Reports (if any) will be +# written in a file name "pylint_global.[txt|html]". +files-output=no + +# Tells whether to display a full report or only the messages +# CHANGED: +reports=no + +# Activate the evaluation score. +score=no + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + + +[VARIABLES] + +# A regular expression matching the beginning of the name of dummy variables +# (i.e. not used). +dummy-variables-rgx=_|dummy + + +[TYPECHECK] + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of classes names for which member attributes should not be checked +# (useful for classes with attributes dynamically set). +ignored-classes=SQLObject, + twisted.internet.reactor, + hashlib, + google.appengine.api.memcache + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E0201 when accessed. Python regular +# expressions are accepted. +generated-members=REQUEST, + acl_users, + aq_parent, + multiprocessing.managers.SyncManager + + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=79 + +# Maximum number of lines in a module +max-module-lines=1000 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + + +[BASIC] + +# List of builtins function names that should not be used, separated by a comma +bad-functions=map, + filter, + apply, + input + +# Regular expression which should only match correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression which should only match correct module level names +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Regular expression which should only match correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Regular expression which should only match correct function names +function-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct method names +method-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct instance attribute names +attr-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct argument names +argument-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct variable names +variable-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct list comprehension / +# generator expression variable names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,k,ex,Run,_ + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# Regular expression which should only match functions or classes name which do +# not require a docstring +no-docstring-rgx=__.*__ + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=5 + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.* + +# Maximum number of locals for function / method body +max-locals=15 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of branch for function / method body +max-branchs=12 + +# Maximum number of statements in function / method body +max-statements=50 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + + +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub, + string, + TERMIOS, + Bastion, + rexec + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=Exception diff --git a/naiveproxy/src/build/modules/BUILD.gn b/naiveproxy/src/build/modules/BUILD.gn new file mode 100644 index 0000000000..674f3610df --- /dev/null +++ b/naiveproxy/src/build/modules/BUILD.gn @@ -0,0 +1,7 @@ +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +group("modules") { + deps = [ "//build/modules/modularize:no_modules" ] +} diff --git a/naiveproxy/src/build/modules/linux-x64/BUILD.gn b/naiveproxy/src/build/modules/linux-x64/BUILD.gn new file mode 100644 index 0000000000..c96deb47b9 --- /dev/null +++ b/naiveproxy/src/build/modules/linux-x64/BUILD.gn @@ -0,0 +1,240 @@ +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# AUTOGENERATED FILE. DO NOT EDIT. +# To regenerate, run build/modules/modularize/modularize.py + +import("//buildtools/third_party/libc++/modules.gni") + +builtin_module("_Builtin_float") { +} + +builtin_module("_Builtin_intrinsics") { + public_deps = [ + ":_Builtin_stddef", + ":_Builtin_stdint", + ":std_core", + ":sys_stage1", + ":sys_stage2", + ] +} + +builtin_module("_Builtin_inttypes") { + public_deps = [ + ":_Builtin_stdint", + ":sys_stage1", + ] +} + +builtin_module("_Builtin_iso646") { +} + +builtin_module("_Builtin_limits") { + public_deps = [ ":sys_stage1" ] +} + +builtin_module("_Builtin_stdalign") { +} + +builtin_module("_Builtin_stdarg") { +} + +builtin_module("_Builtin_stdatomic") { + public_deps = [ + ":_Builtin_stddef", + ":_Builtin_stdint", + ":sys_stage1", + ] +} + +builtin_module("_Builtin_stdbool") { +} + +builtin_module("_Builtin_stdcountof") { +} + +builtin_module("_Builtin_stddef") { +} + +builtin_module("_Builtin_stddef_wint_t") { +} + +builtin_module("_Builtin_stdint") { + public_deps = [ ":sys_stage1" ] +} + +builtin_module("_Builtin_stdnoreturn") { +} + +builtin_module("_Builtin_tgmath") { + public_deps = [ ":std_math_h" ] +} + +builtin_module("_Builtin_unwind") { + public_deps = [ ":_Builtin_stdint" ] +} + +builtin_module("ptrauth") { +} + +libcxx_module("std") { + public_deps = [ + ":_Builtin_limits", + ":_Builtin_stdalign", + ":_Builtin_stdarg", + ":_Builtin_stddef", + ":std_core", + ":std_ctype_h", + ":std_errno_h", + ":std_fenv_h", + ":std_float_h", + ":std_inttypes_h", + ":std_math_h", + ":std_private_mbstate_t", + ":std_string_h", + ":std_uchar_h", + ":std_wctype_h", + ":sys_stage1", + ":sys_stage2", + ] +} + +libcxx_module("std_complex_h") { + public_deps = [ + ":std", + ":sys_stage1", + ] +} + +libcxx_module("std_core") { + public_deps = [ + ":_Builtin_stddef", + ":_Builtin_stdint", + ":sys_stage1", + ] +} + +libcxx_module("std_ctype_h") { + public_deps = [ ":sys_stage1" ] +} + +libcxx_module("std_errno_h") { + public_deps = [ ":sys_stage1" ] +} + +libcxx_module("std_fenv_h") { + public_deps = [ ":sys_stage1" ] +} + +libcxx_module("std_float_h") { + public_deps = [ + ":_Builtin_float", + ":sys_stage1", + ] +} + +libcxx_module("std_inttypes_h") { + public_deps = [ + ":_Builtin_inttypes", + ":_Builtin_stdint", + ":sys_stage1", + ] +} + +libcxx_module("std_math_h") { + public_deps = [ + ":std_core", + ":sys_stage1", + ] +} + +libcxx_module("std_private_mbstate_t") { + public_deps = [ ":sys_stage1" ] +} + +libcxx_module("std_stdatomic_h") { + public_deps = [ + ":_Builtin_stdatomic", + ":sys_stage1", + ] +} + +libcxx_module("std_string_h") { + public_deps = [ + ":_Builtin_stddef", + ":sys_stage1", + ] +} + +libcxx_module("std_tgmath_h") { + public_deps = [ + ":std", + ":sys_stage1", + ] +} + +libcxx_module("std_uchar_h") { + public_deps = [ + ":_Builtin_stddef", + ":sys_stage1", + ] +} + +libcxx_module("std_wctype_h") { + public_deps = [ ":sys_stage1" ] +} + +sysroot_module("sys_stage1") { + public_deps = [ + ":_Builtin_stdarg", + ":_Builtin_stddef", + ] +} + +sysroot_module("sys_stage2") { + public_deps = [ + ":_Builtin_limits", + ":_Builtin_stddef", + ":sys_stage1", + ] +} + +alias("all_modules") { + actual = [ + ":_Builtin_float", + ":_Builtin_intrinsics", + ":_Builtin_inttypes", + ":_Builtin_iso646", + ":_Builtin_limits", + ":_Builtin_stdalign", + ":_Builtin_stdarg", + ":_Builtin_stdatomic", + ":_Builtin_stdbool", + ":_Builtin_stdcountof", + ":_Builtin_stddef", + ":_Builtin_stddef_wint_t", + ":_Builtin_stdint", + ":_Builtin_stdnoreturn", + ":_Builtin_tgmath", + ":_Builtin_unwind", + ":ptrauth", + ":std", + ":std_complex_h", + ":std_core", + ":std_ctype_h", + ":std_errno_h", + ":std_fenv_h", + ":std_float_h", + ":std_inttypes_h", + ":std_math_h", + ":std_private_mbstate_t", + ":std_stdatomic_h", + ":std_string_h", + ":std_tgmath_h", + ":std_uchar_h", + ":std_wctype_h", + ":sys_stage1", + ":sys_stage2", + ] +} diff --git a/naiveproxy/src/build/modules/linux-x64/module.modulemap b/naiveproxy/src/build/modules/linux-x64/module.modulemap new file mode 100644 index 0000000000..c0842e547f --- /dev/null +++ b/naiveproxy/src/build/modules/linux-x64/module.modulemap @@ -0,0 +1,126 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// AUTOGENERATED FILE. DO NOT EDIT. +// To regenerate, run build/modules/modularize/modularize.py + + +module sys_stage1 [system] [extern_c] { + module sysroot_alloca_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/alloca.h" + export * + } + module sysroot_asm_generic_errno_base_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/asm-generic/errno-base.h" + export * + } + module sysroot_asm_generic_errno_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/asm-generic/errno.h" + export * + } + module sysroot_asm_errno_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/asm/errno.h" + export * + } + module sysroot_endian_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/endian.h" + export * + } + module sysroot_fcntl_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/fcntl.h" + export * + } + module sysroot_features_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/features.h" + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/sys/cdefs.h" + export * + } + module sysroot_gnu_stubs_64_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/gnu/stubs-64.h" + export * + } + module sysroot_gnu_stubs_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/gnu/stubs.h" + export * + } + module sysroot_linux_errno_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/linux/errno.h" + export * + } + module sysroot_linux_falloc_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/linux/falloc.h" + export * + } + module sysroot_linux_limits_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/linux/limits.h" + export * + } + module sysroot_locale_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/locale.h" + export * + } + module sysroot_nl_types_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/nl_types.h" + export * + } + module sysroot_pthread_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/pthread.h" + export * + } + module sysroot_sched_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/sched.h" + export * + } + module sysroot_setjmp_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/setjmp.h" + export * + } + module sysroot_signal_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/signal.h" + export * + } + module sysroot_stdc_predef_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/stdc-predef.h" + export * + } + module sysroot_stdio_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/stdio.h" + export * + } + module sysroot_strings_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/strings.h" + export * + } + module sysroot_sys_select_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/sys/select.h" + export * + } + module sysroot_sys_types_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/sys/types.h" + export * + } + module sysroot_sys_ucontext_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/x86_64-linux-gnu/sys/ucontext.h" + export * + } + module sysroot_threads_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/threads.h" + export * + } + module sysroot_time_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/time.h" + export * + } + module sysroot_unistd_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/unistd.h" + export * + } +} + +module sys_stage2 [system] [extern_c] { + module sysroot_stdlib_h { + header "../../linux/debian_bullseye_amd64-sysroot/usr/include/stdlib.h" + export * + } +} diff --git a/naiveproxy/src/build/modules/modularize/BUILD.gn b/naiveproxy/src/build/modules/modularize/BUILD.gn new file mode 100644 index 0000000000..d1f33f875a --- /dev/null +++ b/naiveproxy/src/build/modules/modularize/BUILD.gn @@ -0,0 +1,8 @@ +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("no_modules") { + sources = [ "no_modules.cc" ] + use_libcxx_modules = false +} diff --git a/naiveproxy/src/build/modules/modularize/compiler.py b/naiveproxy/src/build/modules/modularize/compiler.py new file mode 100644 index 0000000000..b9ba024dc2 --- /dev/null +++ b/naiveproxy/src/build/modules/modularize/compiler.py @@ -0,0 +1,390 @@ +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import collections +import functools +import hashlib +import itertools +import logging +import pathlib +import pickle +import re +import shutil +import subprocess +import sys +import tempfile + +from graph import IncludeDir +from graph import Header +from graph import HeaderRef + +_MODULE_START = re.compile('^module ([a-z0-9_]+) ', flags=re.I) +_HEADER = re.compile('( textual)? header "([^"]*)"') + +# It doesn't matter if these don't work on all platforms. +# It'll just print a warning saying it failed to compile. +# This contains a list of files that aren't depended on by libc++, but we still +# want to precompile. +_SYSROOT_PRECOMPILED_HEADERS = ['fcntl.h'] + + +# Some of these steps are quite slow (O(minutes)). +# To allow for fast iteration of config, cache them. +def _maybe_cache(fn): + + @functools.wraps(fn) + def new_fn(self, *args, **kwargs): + # The results should be solely dependent on the GN out dir (assuming the + # user doesn't change args.gn) + gn_rel = str(self.gn_out.resolve()).lstrip('/') + cache_path = pathlib.Path(f'/tmp/modularize_cache', gn_rel, fn.__name__) + cache_path.parent.mkdir(exist_ok=True, parents=True) + if self._use_cache and cache_path.is_file(): + return pickle.loads(cache_path.read_bytes()) + result = fn(self, *args, **kwargs) + cache_path.write_bytes(pickle.dumps(result)) + return result + + return new_fn + + +# We don't need a true parse, just want to determine which modules correspond +# to which files. +def _parse_modulemap(path: pathlib.Path) -> dict[str, list[tuple[str, bool]]]: + """Parses a modulemap into name -> [(header, textual)]""" + modules = collections.defaultdict(list) + with path.open() as f: + for line in f: + mod = _MODULE_START.match(line) + if mod is not None: + current_module = mod.group(1) + header = _HEADER.search(line) + if header is not None: + modules[current_module].append((header.group(2), bool(header.group(1)))) + # This is a builtin module with feature requirements. + modules.pop('opencl_c', None) + return modules + + +class Compiler: + + def __init__(self, *, source_root: pathlib.Path, gn_out: pathlib.Path, + error_dir: pathlib.Path | None, use_cache: bool): + self._error_dir = error_dir + self._use_cache = use_cache + self.gn_out = gn_out + self.source_root = source_root + + self.os = self._get_os() + self.cpu = self._get_cpu() + + if self.os == 'linux': + self.sysroot = self.source_root / 'build/linux/debian_bullseye_amd64-sysroot/usr/include' + elif self.os == 'android': + self.sysroot = self.source_root / 'third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include' + else: + self.sysroot = list( + source_root.glob( + 'third_party/depot_tools/win_toolchain/vs_files/*/Windows Kits/10/Include/*' + ))[0] + self.msvc_dir = list( + source_root.glob( + 'third_party/depot_tools/win_toolchain/vs_files/*/VC/Tools/MSVC/*/include' + ))[0] + + def _parse_depfile(self, content: str) -> list[pathlib.Path]: + files = [] + # The file will look like: + # /dev/null: .cc \ + #
\ + # \ + # So we need [1:] to ensure it doesn't have a dependency on itself. + for line in content.rstrip().split('\n')[1:]: + # Remove both the trailing newlines and any escapes in the file names. + files.append( + pathlib.Path(self.gn_out, + line.replace('\\', '').strip(' ')).resolve()) + return files + + def _get_gn_arg(self, name: str) -> str: + content = (self.gn_out / 'args.gn').read_text() + ps = subprocess.run( + ['gn', 'args', '.', f'--list={name}', '--short'], + text=True, + check=False, + cwd=self.gn_out, + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL, + ) + + # GN args outputs errors to stdout, so we can't use check=True. + if ps.returncode != 0: + print(ps.stdout, file=sys.stderr) + exit(1) + + # output format: 'target_cpu = "x64"\n' + return ps.stdout.rstrip().split(' = ')[1].strip('"') + + def _clang_arg(self, arg: str) -> str: + if self.os == 'win': + return f'/clang:{arg}' + else: + return arg + + @_maybe_cache + def _get_cpu(self): + # If the target_cpu is not explicitly set, it returns the empty string and + # it uses the host_cpu instead. + return self._get_gn_arg('target_cpu') or self._get_gn_arg('host_cpu') + + @_maybe_cache + def _get_os(self): + # If the target_os is not explicitly set, it returns the empty string and + # it uses the host_os instead. + return self._get_gn_arg('target_os') or self._get_gn_arg('host_os') + + def _write_err(self, rel: str, content: bytes): + if self._error_dir is not None: + out = self._error_dir / rel + out.parent.mkdir(exist_ok=True, parents=True) + out.write_bytes(content) + + def split_path(self, path: pathlib.Path) -> tuple[IncludeDir, str]: + """Splits a path into the include directory it's under, and the string + needed to include it from a header file.""" + assert path.is_absolute() + for d, include_dir in self.include_dirs: + if path.is_relative_to(d): + return include_dir, str(path.relative_to(d)) + + # Apply two layers of cache here. + # The _maybe_cache layer caches between runs via a file. + # The functools.cache layer ensures you don't keep loading the pickle file. + @functools.cache + @_maybe_cache + def base_command(self) -> list[str]: + """Returns a command suitable for building for current platform""" + return subprocess.run( + [ + 'build/modules/modularize/no_modules_compile_command.sh', + str(self.gn_out), + self.os, + ], + check=True, + text=True, + cwd=self.source_root, + stdout=subprocess.PIPE, + # Strip the -o /dev/null with [:-2] + # Windows requires it to be at the end, otherwise it writes to {output}.obj. + ).stdout.rstrip().replace('\\', '').split(' ')[:-2] + + # Again, two layers of cache here to cache between runs and within a run. + @functools.cached_property + @_maybe_cache + def include_dirs(self) -> list[tuple[pathlib.Path, IncludeDir]]: + cmd = self.base_command() + [ + '-E', + '-v', + '-x', + 'c++', + '-', + '-o', + '/dev/null', + ] + cmd.remove('-c') + # include dir lines both start and end with whitespace + lines = [ + line.strip() for line in subprocess.run( + cmd, + cwd=self.gn_out, + text=True, + check=True, + stderr=subprocess.PIPE, + # We need to pass in a "file" so we pass in - and devnull so it's + # an empty file. + stdin=subprocess.DEVNULL, + ).stderr.replace('\\', '').split('\n') + ] + + dirs = lines[lines.index('#include <...> search starts here:') + + 1:lines.index('End of search list.')] + # We don't care about these. + dirs.remove('../..') + dirs.remove('gen') + dirs.remove('../../third_party/libc++abi/src/include') + + out = [] + for d in dirs: + d = (self.gn_out / d).resolve() + if d.is_relative_to(self.sysroot): + out.append((d, IncludeDir.Sysroot)) + elif 'libc++' in d.parts: + out.append((d, IncludeDir.LibCxx)) + elif 'clang' in d.parts: + out.append((d, IncludeDir.Builtin)) + else: + raise NotImplementedError(f'Unknown include directory {d}') + + return out + + def compile_one( + self, include: str + ) -> tuple[subprocess.CompletedProcess, None | list[pathlib.Path]]: + """Compiles a single source file including {include}. + + Args: + include: The string to #include (eg. 'vector') + + Returns: + The result of the compilation, and either: + None if no depfile was created, + A list of all files transitively required otherwise. + """ + with tempfile.TemporaryDirectory() as td: + source = pathlib.Path(td, 'source.cc') + source.write_text(f'#include <{include}>') + depfile = pathlib.Path(td, 'source.o.d') + command = self.base_command() + [ + # We write stderr to a file + '-fno-color-diagnostics', + '-x', + 'c++-header', + str(source), + self._clang_arg('-MD'), + self._clang_arg('-MF'), + self._clang_arg(depfile), + '-o', + '/dev/null', + ] + if logging.getLogger().isEnabledFor(logging.DEBUG): + logging.debug('Running command: (cd %s && %s)', self.gn_out, + ' '.join(command)) + ps = subprocess.run( + command, + stderr=subprocess.PIPE, + cwd=self.gn_out, + ) + # The depfile is generated even if it fails to compile. + try: + return ps, self._parse_depfile(depfile.read_text()) + except FileNotFoundError: + return ps, None + + @_maybe_cache + def compile_all(self) -> dict[HeaderRef, Header]: + """Generates a graph of headers by compiling all files in the sysroot.""" + if self._error_dir is not None: + shutil.rmtree(self._error_dir, ignore_errors=True) + + graph: dict[HeaderRef, Header] = {} + uncompiled = [] + seen = set() + + def visit(include: str): + if include not in seen: + uncompiled.append(include) + seen.add(include) + + # Use a list as a set because it's tiny. + seen_dirs = [IncludeDir.Sysroot] + + def add_to_dfs(kind: IncludeDir, modulemap: pathlib.Path): + if kind in seen_dirs: + return + seen_dirs.append(kind) + for mod, files in _parse_modulemap(modulemap).items(): + for path, textual in files: + graph[(kind, path)] = Header(include_dir=kind, + rel=path, + root_module=mod, + textual=textual) + visit(path) + + # Populate a list of initial headers to compile. + add_to_dfs( + IncludeDir.LibCxx, + self.source_root / 'third_party/libc++/src/include/module.modulemap.in') + for header in _SYSROOT_PRECOMPILED_HEADERS: + visit(header) + + # Could consider making the DFS parallel to improve performance. + # But it's a lot of effort for a script that's rarely run. + while uncompiled: + rel = uncompiled.pop() + + ps, files = self.compile_one(rel) + if files is None: + logging.warning("Failed to generate depfile while compiling %s", rel) + self._write_err(rel, ps.stderr) + continue + + abs_path = files[0] + kind, _ = self.split_path(abs_path) + + # The first time we come across a builtin header, we use that to find + # the builtin modulemap to ensure we compile every module in it. + add_to_dfs( + kind, + abs_path.parents[rel.count('/')] / 'module.modulemap', + ) + + if (kind, rel) not in graph: + # If we're seeing it for the first time here, but it's from another + # include dir, it must not be in the module map, so it should be treated as textual. + graph[(kind, rel)] = Header(include_dir=kind, + rel=rel, + textual=kind != IncludeDir.Sysroot) + state = graph[(kind, rel)] + state.abs = abs_path + + for to_abs in files[1:]: + to_kind, to_rel = self.split_path(to_abs) + assert (kind, rel) != (to_kind, to_rel) + if (to_kind, to_rel) not in graph: + graph[(to_kind, to_rel)] = Header( + include_dir=to_kind, + rel=to_rel, + abs=to_abs, + textual=to_kind != IncludeDir.Sysroot, + ) + state.deps.append((to_kind, to_rel)) + visit(to_rel) + + if ps.returncode == 0: + logging.debug('Compiled %s', state.pretty_name) + elif any([ + state.textual, + rel.startswith('bits/'), '/bits/' in rel, + rel.endswith('intrin.h') + ]): + # These things are generally expected to not compile standalone. + logging.debug('Probably fine: Failed to compile %s', state.pretty_name) + else: + if state.root_module != None: + logging.warning('%s was not textual but failed to compile', + state.pretty_name) + else: + # Since this isn't part of a modulemap we can choose to mark it as + # textual. + logging.warning('Failed to compile %s', state.pretty_name) + self._write_err(rel, ps.stderr) + + # If you can't compile it, assume it's textual + if state.root_module is None and ps.returncode != 0: + state.textual = True + + assert IncludeDir.Builtin in seen_dirs + + for header in graph.values(): + if header.abs is None: + for d, kind in self.include_dirs: + if header.include_dir == kind and (d / header.rel).is_file(): + header.abs = d / header.rel + break + assert header.abs is not None + + for dep in header.deps: + assert dep in graph + + return graph diff --git a/naiveproxy/src/build/modules/modularize/compiler_test.py b/naiveproxy/src/build/modules/modularize/compiler_test.py new file mode 100644 index 0000000000..7f72837ecf --- /dev/null +++ b/naiveproxy/src/build/modules/modularize/compiler_test.py @@ -0,0 +1,104 @@ +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import pathlib +import unittest +import tempfile +import textwrap + +from compiler import _maybe_cache +from compiler import _parse_modulemap +from compiler import Compiler +from modularize import SOURCE_ROOT + + +class TestableCompiler(Compiler): + n = 1 + + @_maybe_cache + def cached_n(self): + return self.n + + # Override these to prevent it from invoking GN + def _get_os(self): + return 'linux' + + def _get_cpu(self): + return 'x64' + + +class CompilerTest(unittest.TestCase): + + def setUp(self): + super().setUp() + self.compiler1 = TestableCompiler( + gn_out=pathlib.Path('/tmp/compiler1'), + source_root=SOURCE_ROOT, + error_dir=None, + use_cache=True, + ) + self.compiler1_uncached = TestableCompiler( + gn_out=pathlib.Path('/tmp/compiler1'), + source_root=SOURCE_ROOT, + error_dir=None, + use_cache=False, + ) + self.compiler2 = TestableCompiler( + gn_out=pathlib.Path('/tmp/compiler2'), + source_root=SOURCE_ROOT, + error_dir=None, + use_cache=True, + ) + + def test_maybe_cache(self): + # Uncached compilers should write to the cache, but not read from it. + self.compiler1.n = 2 + self.assertEqual(self.compiler1_uncached.cached_n(), 1) + self.assertEqual(self.compiler1.cached_n(), 1) + self.compiler1_uncached.n = 3 + self.assertEqual(self.compiler1_uncached.cached_n(), 3) + self.assertEqual(self.compiler1.cached_n(), 3) + + # This one should be unrelated since it has a different gn_out dir. + self.compiler2.n = 4 + self.assertEqual(self.compiler2.cached_n(), 4) + + def test_parse_modulemap(self): + self.assertDictEqual( + # It's a defaultdict + _parse_modulemap(SOURCE_ROOT / + 'build/modules/modularize/testdata/module.modulemap'), + { + 'first': [ + ('first.h', False), + ('../first_textual.h', True), + ], + 'second': [ + ('second.h', False), + ('../second_textual.h', True), + ] + }, + ) + + def test_parse_depfile(self): + self.assertListEqual( + self.compiler1._parse_depfile( + textwrap.dedent("""\ + /dev/null: /tmp/main.cc \\ + ../up.cc \\ + path/to/relative.cc \\ + /path/to/absolute.cc \\ + path\\ with\\ spaces.cc \\ + """)), + [ + pathlib.Path('/tmp/up.cc'), + pathlib.Path('/tmp/compiler1/path/to/relative.cc'), + pathlib.Path('/path/to/absolute.cc'), + pathlib.Path('/tmp/compiler1/path with spaces.cc'), + ], + ) + + +if __name__ == '__main__': + unittest.main() diff --git a/naiveproxy/src/build/modules/modularize/config.py b/naiveproxy/src/build/modules/modularize/config.py new file mode 100644 index 0000000000..f93c6d0b2d --- /dev/null +++ b/naiveproxy/src/build/modules/modularize/config.py @@ -0,0 +1,86 @@ +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import collections +import pathlib + +from graph import IncludeDir +from graph import Header +from graph import HeaderRef + + +def fix_graph(graph: dict[HeaderRef, Header], os: str, cpu: str): + """Applies manual augmentation of the header graph.""" + is_apple = os in ['mac', 'ios'] + + # Deal with include_next for modules with modulemaps. + # We were only able to compile the one in the first include dir. + # To solve this, we copy all dependencies except the shadow to the shadowed + # header file. + # eg. If libcxx/stddef.h has deps [builtin/stddef.h, sysroot/stdint.h], we + # set the deps of builtin/stddef.h to [sysroot/stdint.h] + includes = {} + for rel in {header.rel for header in graph.values()}: + order = [] + for d in IncludeDir: + header = graph.get((d, rel), None) + if header is not None: + order.append(header) + for prev, header in zip(order, order[1:]): + header.deps = [(to_kind, to_rel) for (to_kind, to_rel) in order[0].deps + if to_rel != header.rel or to_kind > header.include_dir] + header.prev = prev + prev.next = header + includes[rel] = order + + for header in graph.values(): + header.direct_deps = header.calculate_direct_deps(includes) + + if is_apple: + # From here on out we're modifying which headers are textual. + # This isn't relevant to apple since it has a modulemap. + return + + # Calculate a reverse dependency graph + rdeps = collections.defaultdict(list) + for header in graph.values(): + for dep in header.deps: + rdeps[graph[dep]].append(header) + + sysroot = lambda rel, kind=IncludeDir.Sysroot: graph[(kind, rel)] + + for header in graph.values(): + if header.include_dir != IncludeDir.Sysroot: + continue + + parts = set(pathlib.Path(header.rel).parts) + # We want non-textual, but we don't need to do so if the header including + # you via include_next is non-textual. + if header.prev is not None: + header.textual = not header.prev.textual + # Anything not to be included by the user directly that was only included + # once can be marked as textual. Unfortunately since .d files calculate + # *transitive* dependencies this is not particularly effective. + elif (len(rdeps[header]) < 2 + and parts.intersection(['asm', 'asm-generic', 'bits'])): + header.textual = True + elif '#pragma once' in (header.content or ''): + header.textual = False + elif 'bits' in parts: + header.textual = True + + # Assert is inherently textual. + sysroot('assert.h').textual = True + + # This is included from the std_wchar_h module, but that module is marked as + # textual. Normally that would mean we would mark this as non-textual, but + # wchar.h doesn't play nice being non-textual. + sysroot('wchar.h').textual = True + + if os == 'android': + graph[(IncludeDir.LibCxx, 'wchar.h')].public_configs.append( + '//buildtools/third_party/libc++:wchar_android_fix') + + sysroot('android/legacy_threads_inlines.h').textual = True + sysroot('bits/threads_inlines.h').textual = True diff --git a/naiveproxy/src/build/modules/modularize/graph.py b/naiveproxy/src/build/modules/modularize/graph.py new file mode 100644 index 0000000000..6e18bfc681 --- /dev/null +++ b/naiveproxy/src/build/modules/modularize/graph.py @@ -0,0 +1,224 @@ +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +from __future__ import annotations + +import collections +import dataclasses +import enum +import functools +import itertools +import pathlib +import re + +_INCLUDES = re.compile(r'#\s*include(_next)?\s*<([^>]+)>') + + +class IncludeDir(enum.Enum): + # Ordered by include order for clang + LibCxx = 1 + Builtin = 2 + DarwinBasic = 3 + DarwinFoundation = 4 + CStandardLibrary = 5 + Sysroot = 6 + + def __lt__(self, other): + return self.value < other.value + + +HeaderRef = tuple[IncludeDir, str] + + +@dataclasses.dataclass +class Header: + include_dir: IncludeDir + # The string to use in your #include statement to get this file. + rel: str + # The absolute path to the file + # This should be filled by the time the compiler finishes. + abs: pathlib.Path = None + # Prev and next come from include_next / include_prev + prev: None | Header = None + next: None | Header = None + root_module: None | str = None + textual: bool = False + deps: list[HeaderRef] = dataclasses.field(default_factory=list) + direct_deps: set[Header] = dataclasses.field(default_factory=set) + # Here, None means no exports, and the empty list means 'export *' + # We default to exporting all to preserve the behaviour of includes. + exports: None | list[HeaderRef] = dataclasses.field(default_factory=list) + + # Any configs required to build this file. + public_configs: list[str] = dataclasses.field(default_factory=list) + + def __hash__(self): + return hash((self.include_dir, self.rel)) + + def __eq__(self, other): + return (self.include_dir, self.rel) == (other.include_dir, other.rel) + + def __lt__(self, other): + return (self.include_dir, self.rel) < (other.include_dir, other.rel) + + @property + def pretty_name(self): + return f'{self.include_dir.name}/{self.rel}' + + def __repr__(self): + return self.pretty_name + + @property + def submodule_name(self): + normalized = self.rel.replace('.', '_').replace('/', '_').replace('-', '_') + return 'sysroot_' + normalized + + @functools.cached_property + def content(self) -> None | str: + return self.abs.read_text() + + def calculate_direct_deps(self, includes: dict[str, + list[Header]]) -> set[Header]: + direct = set() + for is_next, include in _INCLUDES.findall(self.content): + header = None + order = includes.get(include, []) + if is_next and self in order[:-1]: + header = order[order.index(self) + 1] + if not is_next and order: + header = order[0] + + # It might have been conditionally included. + if header is not None and (header.include_dir, header.rel) in self.deps: + direct.add(header) + return direct + + def direct_deps_closure(self) -> set[Header]: + closure = set(self.direct_deps) + for dep in self.direct_deps: + if dep.textual: + closure.remove(dep) + closure.update(dep.direct_deps_closure()) + return closure + + +@dataclasses.dataclass +class Target: + """Represents a single clang module / gn target.""" + include_dir: IncludeDir + name: str + headers: list[Header] = dataclasses.field(default_factory=list) + + def __lt__(self, other): + return self.name < other.name + + +def run_build(graph: dict[HeaderRef, Header]) -> list[Target]: + """Calculates the correct way to run a build.""" + unbuilt_modules: dict[str, list[Header]] = collections.defaultdict(list) + unbuilt_headers: set[Header] = set() + + for header in graph.values(): + if not header.textual: + if header.root_module is None: + unbuilt_headers.add(header) + else: + unbuilt_modules[header.root_module].append(header) + header.rdeps = set() + # A group is a set of headers that must be compiled together, because they + # form a dependency loop. + header.group = [header] + header.mod_deps = set() + header.unbuilt_deps = set([ + graph[dep] for dep in header.deps + # Textual headers don't need to be built. + # Also, you don't need to wait for a dependency within the same module. + if not graph[dep].textual and \ + (header.root_module is None or \ + header.root_module != graph[dep].root_module) + ]) + + for header in graph.values(): + for dep in header.unbuilt_deps: + dep.rdeps.add(header) + + # Break dependency loops. + for header in sorted(graph.values()): + for dep in list(header.unbuilt_deps): + # Mark all headers but one in the loop as already having been built. + if header in dep.unbuilt_deps and header.include_dir == IncludeDir.Sysroot and dep.include_dir == IncludeDir.Sysroot: + header.group.append(dep) + dep.group = header.group + for rdep in dep.rdeps: + assert header is rdep or header in rdep.unbuilt_deps + rdep.unbuilt_deps.remove(dep) + unbuilt_headers.remove(dep) + + build_gn = [] + + for i in itertools.count(): + # Try and build any buildable modules from modulemaps. + while True: + n_remaining = len(unbuilt_modules) + for mod, headers in list(unbuilt_modules.items()): + if not any(header.unbuilt_deps for header in headers): + build_gn.append( + Target( + include_dir=headers[0].include_dir, + name=mod, + headers=sorted(headers), + )) + del unbuilt_modules[mod] + for header in headers: + for rdep in header.rdeps: + rdep.mod_deps.add(header.root_module) + rdep.unbuilt_deps.remove(header) + + if n_remaining == len(unbuilt_modules): + break + + # Try and build any builtable sysroot modules + sysroot_mod = f'sys_stage{i + 1}' + build_gn.append(Target( + include_dir=IncludeDir.Sysroot, + name=sysroot_mod, + )) + while True: + n_remaining = len(unbuilt_headers) + for header in list(unbuilt_headers): + if not header.unbuilt_deps: + header.root_module = sysroot_mod + build_gn[-1].headers.append(header) + unbuilt_headers.remove(header) + for rdep in header.rdeps: + rdep.mod_deps.add(header.root_module) + rdep.unbuilt_deps.remove(header) + + if n_remaining == len(unbuilt_headers): + break + + build_gn[-1].headers.sort() + if not build_gn[-1].headers: + break + + build_gn.pop() + + if not unbuilt_modules and not unbuilt_headers: + # Success. Everything is built + return build_gn + else: + print( + "Dependency loop in sysroot. You probably want to make one of them textual." + ) + print("The following headers are in a dependency loop:") + pairs = set() + for header in unbuilt_headers: + for dep in header.unbuilt_deps: + if header in dep.unbuilt_deps: + print(f'{header.pretty_name} -> {dep.pretty_name}') + + # If you get to this point, you probably want a debugger to help understand what the problem is. + sysroot = lambda rel: graph[(IncludeDir.Sysroot, rel)] + breakpoint() + exit(1) diff --git a/naiveproxy/src/build/modules/modularize/modularize.py b/naiveproxy/src/build/modules/modularize/modularize.py new file mode 100755 index 0000000000..575ee911ce --- /dev/null +++ b/naiveproxy/src/build/modules/modularize/modularize.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python + +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""Modularize modularizes a platform.""" + +import argparse +import logging +import pathlib +import shutil +import sys +import tempfile +from config import fix_graph +from graph import run_build +from render import render_build_gn +from render import render_modulemap +from compiler import Compiler + +SOURCE_ROOT = pathlib.Path(__file__).parents[3].resolve() + + +def main(args): + logging.basicConfig(level=logging.getLevelNamesMapping()[args.verbosity]) + + compiler = Compiler( + source_root=SOURCE_ROOT, + gn_out=args.C.resolve(), + error_dir=None if args.error_log is None else args.error_log.resolve(), + use_cache=args.cache, + ) + platform = f'{compiler.os}-{compiler.cpu}' + logging.info('Detected platform %s', platform) + + out_dir = SOURCE_ROOT / f'build/modules/{platform}' + # Otherwise gn will error out because it tries to import a file that doesn't exist. + if not out_dir.is_dir(): + shutil.copytree(out_dir.parent / 'linux-x64', out_dir) + + if args.compile: + with tempfile.TemporaryDirectory() as td: + ps, files = compiler.compile_one(args.compile, pathlib.Path(td, 'source')) + print('stderr:', ps.stderr.decode('utf-8'), file=sys.stderr) + print('Files used:') + print('\n'.join(sorted(map(str, files)))) + print('Setting breakpoint to allow further debugging') + breakpoint() + return + + graph = compiler.compile_all() + fix_graph(graph, compiler.os, compiler.cpu) + targets = run_build(graph) + out_dir.mkdir(exist_ok=True, parents=False) + # Since apple provides a modulemap, we only need to create a BUILD.gn file. + if compiler.os not in ['mac', 'ios']: + render_modulemap(out_dir=out_dir, sysroot=compiler.sysroot, targets=targets) + textual_headers = [hdr for hdr in graph.values() if hdr.textual] + render_build_gn(out_dir=out_dir, + textual_headers=textual_headers, + targets=targets) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('-C', type=pathlib.Path) + + # Make it required so the user understands how compilation works. + cache = parser.add_mutually_exclusive_group(required=True) + cache.add_argument( + '--cache', + action='store_true', + help='Enable caching. Will attempt to reuse the compilation results.') + cache.add_argument( + '--no-cache', + action='store_false', + dest='cache', + help= + 'Disable caching. Will attempt to recompile the whole libcxx, builtins, and sysroot on every invocation' + ) + + parser.add_argument( + '--compile', + help='Compile a single header file', + ) + + parser.add_argument('--error-log', + type=lambda value: pathlib.Path(value) if value else None) + + parser.add_argument( + '--verbosity', + help='Verbosity of logging', + default='INFO', + choices=logging.getLevelNamesMapping().keys(), + type=lambda x: x.upper(), + ) + + main(parser.parse_args()) diff --git a/naiveproxy/src/build/modules/modularize/no_modules.cc b/naiveproxy/src/build/modules/modularize/no_modules.cc new file mode 100644 index 0000000000..2468d36015 --- /dev/null +++ b/naiveproxy/src/build/modules/modularize/no_modules.cc @@ -0,0 +1,6 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// An intentionally empty file so we can retrieve an untouched compilation +// command. diff --git a/naiveproxy/src/build/modules/modularize/no_modules_compile_command.sh b/naiveproxy/src/build/modules/modularize/no_modules_compile_command.sh new file mode 100755 index 0000000000..0f8ddac6ca --- /dev/null +++ b/naiveproxy/src/build/modules/modularize/no_modules_compile_command.sh @@ -0,0 +1,30 @@ +#!/bin/bash -eu + +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +if [[ $# -lt 1 ]]; then + echo "Usage: ./no_modules_compile_command.sh " + exit 1 +fi + +src="../../build/modules/modularize/no_modules.cc" + +# Ensure all the dependencies are present on disk. +autoninja -C "$1" -offline "${src}^" 1>&2 + +# Outputs a generic command to compile an arbitrary cc file. +siso query commands -C "$1" "${src}^" | \ + tail -1 | \ + sed -E 's~ -MMD -MF [^ ]* ~ ~' | \ + sed 's~ /showIncludes:user ~ ~' | \ + sed -E "s~ (-o |/Fo)[^ ]* ~ ~" | \ + sed 's~ /TP ~ ~' | \ + sed "s~ ${src} ~ ~g" | \ + sed 's~ ~ ~g' | \ + tr -d '\n' + +# This specifically needs to go at the end. +# Otherwise Windows attempts to compile to /dev/null.obj +echo " -o /dev/null" diff --git a/naiveproxy/src/build/modules/modularize/render.py b/naiveproxy/src/build/modules/modularize/render.py new file mode 100644 index 0000000000..d74c11e3d4 --- /dev/null +++ b/naiveproxy/src/build/modules/modularize/render.py @@ -0,0 +1,134 @@ +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import contextlib +import io +import pathlib + +from graph import Header +from graph import IncludeDir +from graph import Target + +_HEADER = """# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# AUTOGENERATED FILE. DO NOT EDIT. +# To regenerate, run build/modules/modularize/modularize.py + +""" + + +def _update_content(path: pathlib.Path, content: str): + """Updates the content of a file if changed, thus preventing a siso reload.""" + with contextlib.suppress(FileNotFoundError): + if path.read_text() == content: + return + path.write_text(content) + + +def render_modulemap(out_dir: pathlib.Path, sysroot: pathlib.Path, + targets: list[Target]): + """Writes a modulemap to {out_dir}""" + f = io.StringIO() + f.write(_HEADER.replace('#', '//')) + for target in targets: + if target.include_dir != IncludeDir.Sysroot: + continue + f.write(f'\nmodule {target.name} [system] [extern_c] {{\n') + for header in target.headers: + assert header.include_dir == IncludeDir.Sysroot + f.write(f' module {header.submodule_name} {{\n') + for single in sorted(header.group): + assert single.abs is not None + f.write( + f' header "{single.abs.relative_to(out_dir, walk_up=True)}"\n') + if not header.exports and header.exports is not None: + f.write(' export *\n') + for export in header.exports or []: + f.write(f' export {export.submodule_name}\n') + + f.write(' }\n') + + f.write('}\n') + _update_content(out_dir / 'module.modulemap', f.getvalue()) + + +def _render_string_list(f, + indent: int, + key: str, + values: list[str], + add: str | None = None): + if not values and add is None: + return + indent = " " * indent + f.write(f'{indent}{key} = ') + if add is not None: + f.write(add) + if values: + f.write(' + ') + + if len(values) == 1: + f.write(f'[ "{values[0]}" ]\n') + elif len(values) > 1: + f.write(f'[\n') + for value in values: + f.write(f'{indent} "{value}",\n') + f.write(f'{indent}]\n') + else: + f.write('\n') + + +def render_build_gn(out_dir: pathlib.Path, targets: list[Target], + textual_headers: list[Header]): + """Renders a BUILD.gn file for a specific platform to {out_dir}""" + # textual configs are associated with textual headers, so we just apply them + # indiscriminately since they're not for compiling a specific target. + textual_configs = sorted( + {cfg + for hdr in textual_headers + for cfg in hdr.public_configs}) + + f = io.StringIO() + f.write(_HEADER) + f.write('import("//buildtools/third_party/libc++/modules.gni")\n\n') + if textual_configs: + _render_string_list(f, 0, 'textual_configs', textual_configs) + f.write('\n') + for target in sorted(targets): + direct_deps = set() + for hdr in target.headers: + direct_deps.update(hdr.direct_deps_closure()) + public_deps = sorted({ + f':{hdr.root_module}' + for hdr in direct_deps + if hdr.root_module is not None and hdr.root_module != target.name + }) + + rule = { + IncludeDir.LibCxx: 'libcxx_module', + IncludeDir.Sysroot: 'sysroot_module', + IncludeDir.Builtin: 'builtin_module', + }[target.include_dir] + f.write(f'{rule}("{target.name}") {{\n') + _render_string_list(f, 2, 'public_deps', public_deps) + configs = sorted([ + c for header in target.headers for single in header.group + for c in single.public_configs + ]) + _render_string_list(f, + 2, + 'public_configs', + sorted(configs), + add='textual_configs' if textual_configs else None) + f.write('}\n\n') + + f.write('alias("all_modules") {\n') + f.write(' actual = [\n') + for target in sorted(targets): + f.write(f' ":{target.name}",\n') + f.write(' ]\n') + f.write('}\n') + + _update_content(out_dir / 'BUILD.gn', f.getvalue()) diff --git a/naiveproxy/src/build/modules/modularize/testdata/module.modulemap b/naiveproxy/src/build/modules/modularize/testdata/module.modulemap new file mode 100644 index 0000000000..c94b889b54 --- /dev/null +++ b/naiveproxy/src/build/modules/modularize/testdata/module.modulemap @@ -0,0 +1,17 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module first [system] [extern_c] { + header "first.h" + module submod { + textual header "../first_textual.h" + } +} + +module second [system] [extern_c] { + header "second.h" + module submod { + textual header "../second_textual.h" + } +} \ No newline at end of file diff --git a/naiveproxy/src/build/nocompile.gni b/naiveproxy/src/build/nocompile.gni index 0b70e96dbd..f1ec54cc33 100644 --- a/naiveproxy/src/build/nocompile.gni +++ b/naiveproxy/src/build/nocompile.gni @@ -55,7 +55,7 @@ if (is_win) { } declare_args() { - enable_nocompile_tests = is_clang && !is_nacl + enable_nocompile_tests = is_clang } if (enable_nocompile_tests) { @@ -183,7 +183,10 @@ if (enable_nocompile_tests) { error("Unsupported target_cpu, add it to win_toolchain_data.gni") } args += win_toolchain_data.include_flags_imsvc_list - args += [ "/showIncludes:user" ] + args += [ + "/showIncludes:user", + "/TP", + ] } # Note: for all platforms, the depfile only lists user includes, and not diff --git a/naiveproxy/src/build/rust/allocator/immediate_crash.h b/naiveproxy/src/build/rust/allocator/immediate_crash.h index 9cbf9fd65f..616f55289c 100644 --- a/naiveproxy/src/build/rust/allocator/immediate_crash.h +++ b/naiveproxy/src/build/rust/allocator/immediate_crash.h @@ -44,13 +44,7 @@ #if defined(COMPILER_GCC) -#if BUILDFLAG(IS_NACL) - -// Crash report accuracy is not guaranteed on NaCl. -#define TRAP_SEQUENCE1_() __builtin_trap() -#define TRAP_SEQUENCE2_() asm volatile("") - -#elif defined(ARCH_CPU_X86_FAMILY) +#if defined(ARCH_CPU_X86_FAMILY) // TODO(crbug.com/40625592): In theory, it should be possible to use just // int3. However, there are a number of crashes with SIGILL as the exception diff --git a/naiveproxy/src/build/rust/allocator/lib.rs b/naiveproxy/src/build/rust/allocator/lib.rs index 142c6e6084..29b3af1274 100644 --- a/naiveproxy/src/build/rust/allocator/lib.rs +++ b/naiveproxy/src/build/rust/allocator/lib.rs @@ -90,12 +90,6 @@ mod both_allocators { #[linkage = "weak"] fn __rust_no_alloc_shim_is_unstable_v2() {} - // TODO(crbug.com/422538133) Remove after rolling past - // https://github.com/rust-lang/rust/pull/141061 - #[no_mangle] - #[linkage = "weak"] - static __rust_no_alloc_shim_is_unstable: u8 = 0; - // Mangle the symbol name as rustc expects. #[rustc_std_internal_symbol] #[allow(non_upper_case_globals)] diff --git a/naiveproxy/src/build/rust/cargo_crate.gni b/naiveproxy/src/build/rust/cargo_crate.gni index 0e73b546b3..cb0220af07 100644 --- a/naiveproxy/src/build/rust/cargo_crate.gni +++ b/naiveproxy/src/build/rust/cargo_crate.gni @@ -91,6 +91,7 @@ import("//build/rust/rust_static_library.gni") # cargo_pkg_version # cargo_pkg_name # cargo_pkg_description +# cargo_pkg_repository # Strings as found within 'version' and similar fields within Cargo.toml. # Converted to environment variables passed to rustc, in case the crate # uses clap `crate_version!` or `crate_authors!` macros (fairly common in @@ -154,6 +155,9 @@ template("cargo_crate") { if (defined(invoker.cargo_pkg_description)) { _rustenv += [ "CARGO_PKG_DESCRIPTION=${invoker.cargo_pkg_description}" ] } + if (defined(invoker.cargo_pkg_repository)) { + _rustenv += [ "CARGO_PKG_REPOSITORY=${invoker.cargo_pkg_repository}" ] + } # Try to determine the CARGO_MANIFEST_DIR, preferring the directory # with build.rs and otherwise assuming that the target contains a @@ -195,7 +199,7 @@ template("cargo_crate") { # Proc macros are output to a top level directory (for the host toolchain). # Since multiple versions of the same crate may coexist, the output file # name must include the epoch to disambiguate. - _output_name = "${_crate_name}_${_epochlabel}" + _output_name = "${_crate_name}_${_epochlabel}_${_orig_target_name}" } else if (_crate_type != "bin") { # Note that file names of libraries must start with the crate name in # order for the compiler to find transitive dependencies in the @@ -307,8 +311,7 @@ template("cargo_crate") { if (defined(invoker.allow_unsafe)) { allow_unsafe = invoker.allow_unsafe } - rustflags += - [ "-Awarnings" ] # Suppress other warnings in 3rd-party crates. + configs += [ "//build/rust/gni_impl:allow_all_warnings" ] if (!defined(build_native_rust_unit_tests)) { build_native_rust_unit_tests = _crate_type != "proc-macro" @@ -408,7 +411,7 @@ template("cargo_crate") { action("${_build_script_name}_write_rustflags") { _rustflags_txt = "$_build_script_env_out_dir/rustflags.txt" outputs = [ _rustflags_txt ] - script = rebase_path("//build/rust/write_rustflags.py") + script = rebase_path("//build/rust/gni_impl/write_rustflags.py") args = [ "--output", rebase_path(_rustflags_txt, root_build_dir), @@ -427,7 +430,7 @@ template("cargo_crate") { # Extra targets required to make build script work action("${_build_script_name}_output") { - script = rebase_path("//build/rust/run_build_script.py") + script = rebase_path("//build/rust/gni_impl/run_build_script.py") _write_rustflags_outputs = get_target_outputs(":${_build_script_name}_write_rustflags") _rustflags_txt = _write_rustflags_outputs[0] diff --git a/naiveproxy/src/build/rust/gni_impl/BUILD.gn b/naiveproxy/src/build/rust/gni_impl/BUILD.gn new file mode 100644 index 0000000000..bcbe13d5a9 --- /dev/null +++ b/naiveproxy/src/build/rust/gni_impl/BUILD.gn @@ -0,0 +1,29 @@ +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# The `allow_all_warnings` is meant to be used for suppressing warnings in +# third-party crates coming from crates.io (ones under `//third_party/rust`). +# Note that Chromium still wants to deny most warnings in some notionally +# "third-party" code like `//third_party/skia` or `//third_party/crabbyavif`. +config("allow_all_warnings") { + rustflags = [ "-Awarnings" ] + + # Ideally we would just use `-Awarnings` or `--cap-lints=allow`, but this + # interacts in undesirable ways with other requirements - see + # https://github.com/rust-lang/rust/issues/143108 for more context. + # So, to work around that, we explicitly allow individual warnings + # (because `-Amore-specific-warning` will win over + # the less specific `#![deny(warnings)]`). + # + # `allow_all_warnings.rsp` has been initially generated by taking the output + # of `rustc -W help` and then manually removing entries for warnings + # explicitly controlled by gni templates (e.g. `unsafe_code` warning covered + # by `//build/rust:forbid_unsafe`). + # + # TODO(https://crbug.com/428207407): Stop suppressing individual warnings + # once a single flag can reliably suppress all warnings. + _path = rebase_path("allow_all_warnings.rsp", root_build_dir) + rustflags += [ "@${_path}" ] + inputs = [ "allow_all_warnings.rsp" ] +} diff --git a/naiveproxy/src/build/rust/gni_impl/allow_all_warnings.rsp b/naiveproxy/src/build/rust/gni_impl/allow_all_warnings.rsp new file mode 100644 index 0000000000..fc112c8faa --- /dev/null +++ b/naiveproxy/src/build/rust/gni_impl/allow_all_warnings.rsp @@ -0,0 +1,97 @@ +-Aabsolute_paths_not_starting_with_crate +-Aambiguous_associated_items +-Aambiguous_negative_literals +-Aarithmetic_overflow +-Abinary_asm_labels +-Abindings_with_variant_name +-Aclosure_returning_async_block +-Aconflicting_repr_hints +-Adangerous_implicit_autorefs +-Adefault_overrides_default_fields +-Adeprecated_in_future +-Adeprecated_safe_2024 +-Aderef_into_dyn_supertrait +-Aedition_2024_expr_fragment_specifier +-Aelided_lifetimes_in_associated_constant +-Aelided_lifetimes_in_paths +-Aenum_intrinsics_non_enums +-Aexplicit_builtin_cfgs_in_flags +-Aexplicit_outlives_requirements +-Affi_unwind_calls +-Afuzzy_provenance_casts +-Aif_let_rescope +-Aill_formed_attribute_input +-Aimpl_trait_overcaptures +-Aimpl_trait_redundant_captures +-Aincomplete_include +-Aineffective_unstable_trait_impl +-Ainvalid_atomic_ordering +-Ainvalid_doc_attributes +-Ainvalid_from_utf8_unchecked +-Ainvalid_null_arguments +-Ainvalid_reference_casting +-Ainvalid_type_param_default +-Akeyword_idents_2018 +-Akeyword_idents_2024 +-Alet_underscore_drop +-Alet_underscore_lock +-Alinker_messages +-Along_running_const_eval +-Alossy_provenance_casts +-Amacro_expanded_macro_exports_accessed_by_absolute_paths +-Amacro_use_extern_crate +-Ameta_variable_misuse +-Amismatched_lifetime_syntaxes +-Amissing_copy_implementations +-Amissing_debug_implementations +-Amissing_docs +-Amissing_unsafe_on_extern +-Amultiple_supertrait_upcastable +-Amust_not_suspend +-Amutable_transmutes +-Anamed_asm_labels +-Ano_mangle_const_items +-Anon_ascii_idents +-Anon_exhaustive_omitted_patterns +-Aoverflowing_literals +-Apatterns_in_fns_without_body +-Aproc_macro_derive_resolution_fallback +-Apub_use_of_private_extern_crate +-Aredundant_imports +-Aredundant_lifetimes +-Arust_2021_incompatible_closure_captures +-Arust_2021_incompatible_or_patterns +-Arust_2021_prefixes_incompatible_syntax +-Arust_2021_prelude_collisions +-Arust_2024_guarded_string_incompatible_syntax +-Arust_2024_incompatible_pat +-Arust_2024_prelude_collisions +-Asingle_use_lifetimes +-Asoft_unstable +-Asupertrait_item_shadowing_definition +-Asupertrait_item_shadowing_usage +-Atail_expr_drop_order +-Atest_unstable_lint +-Atext_direction_codepoint_in_comment +-Atext_direction_codepoint_in_literal +-Atrivial_casts +-Atrivial_numeric_casts +-Aunconditional_panic +-Aundropped_manually_drops +-Aunit_bindings +-Aunknown_crate_types +-Aunnameable_types +-Aunqualified_local_imports +-Aunreachable_pub +-Aunsafe_attr_outside_unsafe +-Aunsafe_op_in_unsafe_fn +-Aunstable_features +-Aunused_crate_dependencies +-Aunused_extern_crates +-Aunused_import_braces +-Aunused_lifetimes +-Aunused_macro_rules +-Aunused_qualifications +-Aunused_results +-Auseless_deprecated +-Avariant_size_differences diff --git a/naiveproxy/src/build/rust/filter_clang_args.py b/naiveproxy/src/build/rust/gni_impl/filter_clang_args.py similarity index 99% rename from naiveproxy/src/build/rust/filter_clang_args.py rename to naiveproxy/src/build/rust/gni_impl/filter_clang_args.py index 5a1843c0df..dca4b6a969 100644 --- a/naiveproxy/src/build/rust/filter_clang_args.py +++ b/naiveproxy/src/build/rust/gni_impl/filter_clang_args.py @@ -14,6 +14,7 @@ This function filters them out. def filter_clang_args(clangargs): + def do_filter(args): i = 0 while i < len(args): diff --git a/naiveproxy/src/build/rust/run_bindgen.py b/naiveproxy/src/build/rust/gni_impl/run_bindgen.py similarity index 98% rename from naiveproxy/src/build/rust/run_bindgen.py rename to naiveproxy/src/build/rust/gni_impl/run_bindgen.py index 9a0eead6bb..e35f3ceefe 100755 --- a/naiveproxy/src/build/rust/run_bindgen.py +++ b/naiveproxy/src/build/rust/gni_impl/run_bindgen.py @@ -13,7 +13,7 @@ import sys # Set up path to be able to import action_helpers. sys.path.append( os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir, - os.pardir, 'build')) + os.pardir, os.pardir, 'build')) import action_helpers from filter_clang_args import filter_clang_args diff --git a/naiveproxy/src/build/rust/run_build_script.py b/naiveproxy/src/build/rust/gni_impl/run_build_script.py similarity index 96% rename from naiveproxy/src/build/rust/run_build_script.py rename to naiveproxy/src/build/rust/gni_impl/run_build_script.py index 9d6ca087c0..12c40c678b 100755 --- a/naiveproxy/src/build/rust/run_build_script.py +++ b/naiveproxy/src/build/rust/gni_impl/run_build_script.py @@ -36,10 +36,9 @@ import tempfile # Set up path to be able to import action_helpers sys.path.append( os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir, - os.pardir, 'build')) + os.pardir, os.pardir, 'build')) import action_helpers - RUSTC_VERSION_LINE = re.compile(r"(\w+): (.*)") @@ -72,6 +71,9 @@ def set_cargo_cfg_target_env_variables(rustc_path, env): # (derived from `rustflags` maybe?). args = [rustc_path, "--print=cfg", f"--target={target_triple}"] + # TODO(https://crbug.com/435437947): Ideally `rustc --print=cfg + # --target=...` would only be invoked **once** per build (not once per + # `run_cxxbridge.py` and once per `run_build_script.py`). proc = subprocess.Popen(args, stdout=subprocess.PIPE) for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"): line = line.strip() diff --git a/naiveproxy/src/build/rust/run_rs_bindings_from_cc.py b/naiveproxy/src/build/rust/gni_impl/run_rs_bindings_from_cc.py similarity index 99% rename from naiveproxy/src/build/rust/run_rs_bindings_from_cc.py rename to naiveproxy/src/build/rust/gni_impl/run_rs_bindings_from_cc.py index 41c2228ad9..091a859e5d 100755 --- a/naiveproxy/src/build/rust/run_rs_bindings_from_cc.py +++ b/naiveproxy/src/build/rust/gni_impl/run_rs_bindings_from_cc.py @@ -24,6 +24,7 @@ RS_BINDINGS_FROM_CC_EXE_PATH = os.path.join(RUST_TOOLCHAIN_DIR, "bin", def format_cmdline(args): + def quote_arg(x): if ' ' not in x: return x x = x.replace('"', '\\"') diff --git a/naiveproxy/src/build/rust/rust_target.gni b/naiveproxy/src/build/rust/gni_impl/rust_target.gni similarity index 100% rename from naiveproxy/src/build/rust/rust_target.gni rename to naiveproxy/src/build/rust/gni_impl/rust_target.gni diff --git a/naiveproxy/src/build/rust/rustc_wrapper.py b/naiveproxy/src/build/rust/gni_impl/rustc_wrapper.py similarity index 98% rename from naiveproxy/src/build/rust/rustc_wrapper.py rename to naiveproxy/src/build/rust/gni_impl/rustc_wrapper.py index 8f2096dfe5..1c675000e8 100755 --- a/naiveproxy/src/build/rust/rustc_wrapper.py +++ b/naiveproxy/src/build/rust/gni_impl/rustc_wrapper.py @@ -15,7 +15,7 @@ import re # Set up path to be able to import action_helpers. sys.path.append( os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir, - os.pardir, 'build')) + os.pardir, os.pardir, 'build')) import action_helpers # This script wraps rustc for (currently) these reasons: @@ -55,7 +55,7 @@ import action_helpers # in an RSP file. Unfortunately, they are space-separated variables # but Rust requires a newline-separated input. This script duly makes # the adjustment. This works around a gn issue: -# TODO(https://bugs.chromium.org/p/gn/issues/detail?id=249): fix this +# TODO(https://crbug.com/gn/42440152): fix this # # WORKAROUND WINDOWS BUGS: # diff --git a/naiveproxy/src/build/rust/write_rustflags.py b/naiveproxy/src/build/rust/gni_impl/write_rustflags.py similarity index 95% rename from naiveproxy/src/build/rust/write_rustflags.py rename to naiveproxy/src/build/rust/gni_impl/write_rustflags.py index 0b51df7847..10cba9b2c1 100755 --- a/naiveproxy/src/build/rust/write_rustflags.py +++ b/naiveproxy/src/build/rust/gni_impl/write_rustflags.py @@ -13,7 +13,7 @@ import sys # Set up path to be able to import action_helpers sys.path.append( os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir, - os.pardir, 'build')) + os.pardir, os.pardir, 'build')) import action_helpers diff --git a/naiveproxy/src/build/rust/rs_bindings_from_cc.gni b/naiveproxy/src/build/rust/rs_bindings_from_cc.gni index 54775ea111..10c6487633 100644 --- a/naiveproxy/src/build/rust/rs_bindings_from_cc.gni +++ b/naiveproxy/src/build/rust/rs_bindings_from_cc.gni @@ -247,7 +247,7 @@ template("rs_bindings_from_cc") { visibility = _visibility } - script = "//build/rust/run_rs_bindings_from_cc.py" + script = "//build/rust/gni_impl/run_rs_bindings_from_cc.py" inputs = [ "//third_party/rust-toolchain/bin/rs_bindings_from_cc" ] sources = invoker.public_headers outputs = [ diff --git a/naiveproxy/src/build/rust/rust_bindgen_generator.gni b/naiveproxy/src/build/rust/rust_bindgen_generator.gni index 652c19b326..bc1ad33786 100644 --- a/naiveproxy/src/build/rust/rust_bindgen_generator.gni +++ b/naiveproxy/src/build/rust/rust_bindgen_generator.gni @@ -140,12 +140,12 @@ template("rust_bindgen_generator") { output_file = "$output_dir/${output_name}.rs" - script = rebase_path("//build/rust/run_bindgen.py") + script = rebase_path("//build/rust/gni_impl/run_bindgen.py") inputs = [ _bindgen_path, "//build/action_helpers.py", "//build/gn_helpers.py", - "//build/rust/filter_clang_args.py", + "//build/rust/gni_impl/filter_clang_args.py", ] depfile = "$target_out_dir/${target_name}.d" diff --git a/naiveproxy/src/build/rust/rust_executable.gni b/naiveproxy/src/build/rust/rust_executable.gni index a1f38fdb2d..029a865984 100644 --- a/naiveproxy/src/build/rust/rust_executable.gni +++ b/naiveproxy/src/build/rust/rust_executable.gni @@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/rust/rust_target.gni") +import("//build/rust/gni_impl/rust_target.gni") # Defines a Rust executable. # diff --git a/naiveproxy/src/build/rust/rust_macro.gni b/naiveproxy/src/build/rust/rust_macro.gni index 41d857632c..af862c4383 100644 --- a/naiveproxy/src/build/rust/rust_macro.gni +++ b/naiveproxy/src/build/rust/rust_macro.gni @@ -3,7 +3,7 @@ # found in the LICENSE file. import("//build/config/rust.gni") -import("//build/rust/rust_target.gni") +import("//build/rust/gni_impl/rust_target.gni") # Template for generating a Rust proc-macro library. Such targets produce a # dynamic library that is loaded during compilation and used to generate Rust diff --git a/naiveproxy/src/build/rust/rust_shared_library.gni b/naiveproxy/src/build/rust/rust_shared_library.gni index e1358c5f28..5c699fe5aa 100644 --- a/naiveproxy/src/build/rust/rust_shared_library.gni +++ b/naiveproxy/src/build/rust/rust_shared_library.gni @@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/rust/rust_target.gni") +import("//build/rust/gni_impl/rust_target.gni") # Rust dylibs should not be built outside of component builds. Non-component # builds use build configurations that conflict with the linking of dylibs. diff --git a/naiveproxy/src/build/rust/rust_static_library.gni b/naiveproxy/src/build/rust/rust_static_library.gni index f60ea6ab60..e9c65885ae 100644 --- a/naiveproxy/src/build/rust/rust_static_library.gni +++ b/naiveproxy/src/build/rust/rust_static_library.gni @@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/rust/rust_target.gni") +import("//build/rust/gni_impl/rust_target.gni") # Defines a Rust static library which can be used by downstream Rust or C++ # targets. This is a single Rust compilation unit consisting of potentially diff --git a/naiveproxy/src/build/rust/std/BUILD.gn.hbs b/naiveproxy/src/build/rust/std/BUILD.gn.hbs index 265c8a4618..ee0a8e317d 100644 --- a/naiveproxy/src/build/rust/std/BUILD.gn.hbs +++ b/naiveproxy/src/build/rust/std/BUILD.gn.hbs @@ -41,6 +41,11 @@ cargo_crate("{{../name}}") { cargo_pkg_description = "{{gn_escape this}}" {{/with}} {{/if}} + {{#if cargo_pkg_repository}} + {{#with cargo_pkg_repository}} + cargo_pkg_repository = "{{this}}" + {{/with}} + {{/if}} library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", @@ -88,7 +93,7 @@ cargo_crate("{{../name}}") { {{#if aliased_deps}} aliased_deps = { {{#each aliased_deps}} - {{this.0}} = "{{this.1}}" + {{this.0}} = ":{{this.1.name}}" {{/each}} } {{/if}} diff --git a/naiveproxy/src/build/rust/std/fake_root/Cargo.toml.template b/naiveproxy/src/build/rust/std/fake_root/Cargo.toml.template index 3201d74754..c4e3784434 100644 --- a/naiveproxy/src/build/rust/std/fake_root/Cargo.toml.template +++ b/naiveproxy/src/build/rust/std/fake_root/Cargo.toml.template @@ -17,6 +17,7 @@ features = [ ] [patch.crates-io] +compiler_builtins = { path = "../../../../RUST_SRC_ROOT/library/compiler-builtins/compiler-builtins" } rustc-std-workspace-core = { path = '../../../../RUST_SRC_ROOT/library/rustc-std-workspace-core' } rustc-std-workspace-alloc = { path = '../../../../RUST_SRC_ROOT/library/rustc-std-workspace-alloc' } rustc-std-workspace-std = { path = '../../../../RUST_SRC_ROOT/library/rustc-std-workspace-std' } diff --git a/naiveproxy/src/build/rust/std/gnrt_config.toml b/naiveproxy/src/build/rust/std/gnrt_config.toml index b394cca745..874e53b524 100644 --- a/naiveproxy/src/build/rust/std/gnrt_config.toml +++ b/naiveproxy/src/build/rust/std/gnrt_config.toml @@ -42,13 +42,14 @@ build_file_template = "BUILD.gn.hbs" extra_kv = { include_coverage = true } [crate.compiler_builtins] -# Dependencies of profiler_builtins must have instrumentation disabled -# The build script conditionally generates a file; it's simplest to just paste -# raw GN into the output. (crbug.com/1470653) -extra_kv = { include_coverage = false, raw_gn = 'if (current_cpu == "arm64") { build_script_outputs = ["outlined_atomics.rs"] }' } +# Dependencies of profiler_builtins must have instrumentation disabled. +extra_kv = { include_coverage = false } extra_build_script_src_roots = [ '../configure.rs', ] +extra_src_roots = [ + '../../libm/src', +] [crate.core] # Dependencies of profiler_builtins must have instrumentation disabled diff --git a/naiveproxy/src/build/rust/std/rules/BUILD.gn b/naiveproxy/src/build/rust/std/rules/BUILD.gn index 88068930cd..b51bd50ecd 100644 --- a/naiveproxy/src/build/rust/std/rules/BUILD.gn +++ b/naiveproxy/src/build/rust/std/rules/BUILD.gn @@ -8,18 +8,17 @@ import("//build/rust/cargo_crate.gni") cargo_crate("addr2line") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/addr2line-0.24.2/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/addr2line-0.25.0/src/lib.rs" enabled = !is_win sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/addr2line-0.24.2/src/bin/addr2line.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/addr2line-0.24.2/src/frame.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/addr2line-0.24.2/src/function.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/addr2line-0.24.2/src/lazy.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/addr2line-0.24.2/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/addr2line-0.24.2/src/line.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/addr2line-0.24.2/src/loader.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/addr2line-0.24.2/src/lookup.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/addr2line-0.24.2/src/unit.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/addr2line-0.25.0/src/bin/addr2line.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/addr2line-0.25.0/src/frame.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/addr2line-0.25.0/src/function.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/addr2line-0.25.0/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/addr2line-0.25.0/src/line.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/addr2line-0.25.0/src/loader.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/addr2line-0.25.0/src/lookup.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/addr2line-0.25.0/src/unit.rs", ] inputs = [] no_std = true @@ -27,10 +26,11 @@ 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.24.2" + cargo_pkg_version = "0.25.0" cargo_pkg_name = "addr2line" cargo_pkg_description = "A cross-platform symbolication library written in Rust, using `gimli`" + cargo_pkg_repository = "https://github.com/gimli-rs/addr2line" library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", @@ -47,7 +47,6 @@ cargo_crate("addr2line") { ] if (!is_win) { deps += [ - ":compiler_builtins", ":gimli", ":rustc_std_workspace_alloc", ":rustc_std_workspace_core", @@ -59,7 +58,6 @@ cargo_crate("addr2line") { } features = [ "alloc", - "compiler_builtins", "core", "rustc-dep-of-std", ] @@ -77,11 +75,11 @@ cargo_crate("addr2line") { } cargo_crate("adler2") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/adler2-2.0.0/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/adler2-2.0.1/src/lib.rs" enabled = !is_win sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/adler2-2.0.0/src/algo.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/adler2-2.0.0/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/adler2-2.0.1/src/algo.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/adler2-2.0.1/src/lib.rs", ] inputs = [] no_std = true @@ -89,11 +87,12 @@ cargo_crate("adler2") { # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2021" - cargo_pkg_version = "2.0.0" + cargo_pkg_version = "2.0.1" cargo_pkg_authors = "Jonas Schievink , oyvindln " cargo_pkg_name = "adler2" cargo_pkg_description = "A simple clean-room implementation of the Adler-32 checksum" + cargo_pkg_repository = "https://github.com/oyvindln/adler2" library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", @@ -109,16 +108,12 @@ cargo_crate("adler2") { "//build/rust/std:std_build_deps", ] if (!is_win) { - deps += [ - ":compiler_builtins", - ":rustc_std_workspace_core", - ] + deps += [ ":rustc_std_workspace_core" ] } aliased_deps = { core = ":rustc_std_workspace_core" } features = [ - "compiler_builtins", "core", "rustc-dep-of-std", ] @@ -202,6 +197,7 @@ cargo_crate("alloc") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/alloc/src/vec/is_zero.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/alloc/src/vec/partial_eq.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/alloc/src/vec/peek_mut.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/alloc/src/vec/set_len_on_drop.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/alloc/src/vec/spec_extend.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/alloc/src/vec/spec_from_elem.rs", @@ -218,6 +214,7 @@ cargo_crate("alloc") { cargo_pkg_version = "0.0.0" cargo_pkg_name = "alloc" cargo_pkg_description = "The Rust core allocation and collections library" + cargo_pkg_repository = "https://github.com/rust-lang/rust.git" library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", @@ -248,18 +245,19 @@ cargo_crate("alloc") { } cargo_crate("cfg_if") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/cfg-if-1.0.0/src/lib.rs" - sources = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/cfg-if-1.0.0/src/lib.rs" ] + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/cfg-if-1.0.1/src/lib.rs" + sources = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/cfg-if-1.0.1/src/lib.rs" ] inputs = [] no_std = true # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2018" - cargo_pkg_version = "1.0.0" + cargo_pkg_version = "1.0.1" cargo_pkg_authors = "Alex Crichton " cargo_pkg_name = "cfg-if" cargo_pkg_description = "A macro to ergonomically define an item depending on a large number of #[cfg] parameters. Structured like an if-else chain, the first matching branch is the item that gets emitted." + cargo_pkg_repository = "https://github.com/rust-lang/cfg-if" library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", @@ -271,7 +269,6 @@ cargo_crate("cfg_if") { ] executable_configs += [ "//build/config/compiler:no_chromium_code" ] deps = [ - ":compiler_builtins", ":rustc_std_workspace_core", "//build/rust/std:profiler_builtins_group", "//build/rust/std:std_build_deps", @@ -280,7 +277,6 @@ cargo_crate("cfg_if") { core = ":rustc_std_workspace_core" } features = [ - "compiler_builtins", "core", "rustc-dep-of-std", ] @@ -298,236 +294,210 @@ cargo_crate("cfg_if") { } cargo_crate("compiler_builtins") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/aarch64_linux.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/arm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/arm_linux.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/avr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/add.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/cmp.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/conv.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/div.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/extend.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/mul.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/pow.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/sub.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/traits.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/trunc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/hexagon.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/addsub.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/big.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/bswap.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/leading_zeros.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/mul.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/sdiv.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/shift.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/specialized_div_rem/asymmetric.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/specialized_div_rem/binary_long.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/specialized_div_rem/delegate.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/specialized_div_rem/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/specialized_div_rem/norm_shift.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/specialized_div_rem/trifecta.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/trailing_zeros.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/traits.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/udiv.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/lib.miri.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/macros.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/acos.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/acosf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/acosh.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/acoshf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/arch/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/arch/i586.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/arch/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/arch/wasm32.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/arch/x86.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/arch/x86/detect.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/arch/x86/fma.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/asin.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/asinf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/asinh.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/asinhf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/atan.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/atan2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/atan2f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/atanf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/atanh.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/atanhf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/cbrt.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/cbrtf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/ceil.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/copysign.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/copysignf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/copysignf128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/copysignf16.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/cos.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/cosf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/cosh.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/coshf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/erf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/erff.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/exp.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/exp10.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/exp10f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/exp2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/exp2f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/expf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/expm1.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/expm1f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/expo2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fabs.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fabsf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fabsf128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fabsf16.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fdim.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fdimf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fdimf128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fdimf16.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/floor.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/floorf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/floorf128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/floorf16.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fma.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fmin_fmax.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fminimum_fmaximum.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fminimum_fmaximum_num.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fmod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fmodf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fmodf128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fmodf16.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/frexp.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/frexpf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/ceil.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/copysign.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fabs.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fdim.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/floor.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fma.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fma_wide.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fmax.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fmaximum.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fmaximum_num.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fmin.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fminimum.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fminimum_num.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fmod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/rint.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/round.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/scalbn.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/sqrt.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/trunc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/hypot.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/hypotf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/ilogb.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/ilogbf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/j0.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/j0f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/j1.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/j1f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/jn.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/jnf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/k_cos.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/k_cosf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/k_expo2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/k_expo2f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/k_sin.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/k_sinf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/k_tan.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/k_tanf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/ldexp.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/ldexpf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/ldexpf128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/ldexpf16.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/lgamma.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/lgamma_r.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/lgammaf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/lgammaf_r.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/log.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/log10.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/log10f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/log1p.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/log1pf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/log2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/log2f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/logf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/modf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/modff.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/nextafter.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/nextafterf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/pow.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/powf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/rem_pio2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/rem_pio2_large.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/rem_pio2f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/remainder.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/remainderf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/remquo.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/remquof.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/rint.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/round.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/roundeven.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/roundf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/roundf128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/roundf16.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/scalbn.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/scalbnf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/scalbnf128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/scalbnf16.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/sin.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/sincos.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/sincosf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/sinf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/sinh.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/sinhf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/sqrt.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/sqrtf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/sqrtf128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/sqrtf16.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/support/big.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/support/big/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/support/env.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/support/feature_detect.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/support/float_traits.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/support/hex_float.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/support/int_traits.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/support/macros.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/support/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/tan.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/tanf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/tanh.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/tanhf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/tgamma.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/tgammaf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/trunc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/truncf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/truncf128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/truncf16.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/mem/impls.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/mem/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/mem/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/probestack.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/riscv.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/x86.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/aarch64_linux.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/arm_linux.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/avr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/float/add.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/float/cmp.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/float/conv.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/float/div.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/float/extend.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/float/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/float/mul.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/float/pow.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/float/sub.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/float/traits.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/float/trunc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/hexagon.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/int/addsub.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/int/big.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/int/bswap.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/int/leading_zeros.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/int/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/int/mul.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/int/sdiv.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/int/shift.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/int/specialized_div_rem/asymmetric.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/int/specialized_div_rem/binary_long.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/int/specialized_div_rem/delegate.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/int/specialized_div_rem/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/int/specialized_div_rem/norm_shift.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/int/specialized_div_rem/trifecta.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/int/trailing_zeros.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/int/traits.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/int/udiv.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/lib.miri.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/macros.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/math/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/mem/impls.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/mem/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/mem/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/probestack.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/riscv.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/x86.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/x86_64.rs", + ] + inputs = [ + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/libm_helper.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/acos.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/acosf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/acosh.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/acoshf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/arch/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/arch/i586.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/arch/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/arch/wasm32.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/arch/x86/detect.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/arch/x86/fma.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/arch/x86.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/asin.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/asinf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/asinh.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/asinhf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/atan.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/atan2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/atan2f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/atanf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/atanh.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/atanhf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/cbrt.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/cbrtf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/ceil.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/copysign.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/cos.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/cosf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/cosh.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/coshf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/erf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/erff.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/exp.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/exp10.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/exp10f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/exp2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/exp2f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/expf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/expm1.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/expm1f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/expo2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/fabs.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/fdim.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/floor.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/fma.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/fmin_fmax.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/fminimum_fmaximum.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/fminimum_fmaximum_num.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/fmod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/frexp.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/frexpf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/generic/ceil.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/generic/copysign.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/generic/fabs.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/generic/fdim.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/generic/floor.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/generic/fma.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/generic/fma_wide.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/generic/fmax.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/generic/fmaximum.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/generic/fmaximum_num.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/generic/fmin.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/generic/fminimum.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/generic/fminimum_num.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/generic/fmod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/generic/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/generic/rint.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/generic/round.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/generic/scalbn.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/generic/sqrt.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/generic/trunc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/hypot.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/hypotf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/ilogb.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/ilogbf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/j0.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/j0f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/j1.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/j1f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/jn.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/jnf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/k_cos.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/k_cosf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/k_expo2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/k_expo2f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/k_sin.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/k_sinf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/k_tan.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/k_tanf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/ldexp.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/lgamma.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/lgamma_r.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/lgammaf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/lgammaf_r.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/log.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/log10.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/log10f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/log1p.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/log1pf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/log2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/log2f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/logf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/modf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/modff.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/nextafter.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/nextafterf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/pow.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/powf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/rem_pio2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/rem_pio2_large.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/rem_pio2f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/remainder.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/remainderf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/remquo.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/remquof.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/rint.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/round.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/roundeven.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/scalbn.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/sin.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/sincos.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/sincosf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/sinf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/sinh.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/sinhf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/sqrt.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/support/big/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/support/big.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/support/env.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/support/feature_detect.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/support/float_traits.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/support/hex_float.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/support/int_traits.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/support/macros.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/support/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/tan.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/tanf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/tanh.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/tanhf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/tgamma.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/tgammaf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../../libm/src/math/trunc.rs", ] - inputs = [] no_std = true # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false - edition = "2021" - cargo_pkg_version = "0.1.157" + edition = "2024" + cargo_pkg_version = "0.1.160" cargo_pkg_authors = "Jorge Aparicio " cargo_pkg_name = "compiler_builtins" cargo_pkg_description = "Compiler intrinsics used by the Rust compiler." + cargo_pkg_repository = "https://github.com/rust-lang/compiler-builtins" library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", @@ -540,20 +510,17 @@ cargo_crate("compiler_builtins") { ] executable_configs += [ "//build/config/compiler:no_chromium_code" ] deps = [ - ":rustc_std_workspace_core", + ":core", "//build/rust/std:std_build_deps", ] - aliased_deps = { - core = ":rustc_std_workspace_core" - } features = [ "compiler-builtins", "default", "rustc-dep-of-std", ] - build_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/build.rs" - build_sources = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/build.rs" ] - build_script_inputs = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/../configure.rs" ] + build_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/build.rs" + build_sources = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/build.rs" ] + build_script_inputs = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/../configure.rs" ] rustenv = [ "CFG_DISABLE_UNSTABLE_FEATURES=0", "STD_ENV_ARCH=$rust_target_arch", @@ -565,10 +532,6 @@ cargo_crate("compiler_builtins") { ] output_dir = "$root_out_dir/local_rustc_sysroot/lib/rustlib/$rust_abi_target/lib/" - - if (current_cpu == "arm64") { - build_script_outputs = [ "outlined_atomics.rs" ] - } } cargo_crate("core") { crate_type = "rlib" @@ -634,6 +597,7 @@ cargo_crate("core") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/hash/sip.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/hint.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/internal_macros.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/intrinsics/bounds.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/intrinsics/fallback.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/intrinsics/mir.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/intrinsics/mod.rs", @@ -672,6 +636,7 @@ cargo_crate("core") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/iter/sources/empty.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/iter/sources/from_coroutine.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/iter/sources/from_fn.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/iter/sources/generator.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/iter/sources/once.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/iter/sources/once_with.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/iter/sources/repeat.rs", @@ -726,6 +691,7 @@ cargo_crate("core") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/num/int_log10.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/num/int_macros.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/num/int_sqrt.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/num/libm.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/num/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/num/niche_types.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/num/nonzero.rs", @@ -1066,6 +1032,10 @@ cargo_crate("core") { "//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", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/ptr/docs/add.md", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/ptr/docs/as_uninit_slice.md", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/ptr/docs/is_null.md", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/ptr/docs/offset.md", ] no_std = true @@ -1075,6 +1045,7 @@ cargo_crate("core") { cargo_pkg_version = "0.0.0" cargo_pkg_name = "core" cargo_pkg_description = "The Rust Core Library" + cargo_pkg_repository = "https://github.com/rust-lang/rust.git" library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", @@ -1104,21 +1075,22 @@ cargo_crate("core") { } cargo_crate("getopts") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/getopts-0.2.21/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/getopts-0.2.23/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/getopts-0.2.21/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/getopts-0.2.21/src/tests/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/getopts-0.2.23/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/getopts-0.2.23/src/tests/mod.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.2.21" + edition = "2021" + cargo_pkg_version = "0.2.23" cargo_pkg_authors = "The Rust Project Developers" cargo_pkg_name = "getopts" - cargo_pkg_description = "getopts-like option parsing." + cargo_pkg_description = "getopts-like option parsing" + cargo_pkg_repository = "https://github.com/rust-lang/getopts" library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", @@ -1159,53 +1131,54 @@ cargo_crate("getopts") { } cargo_crate("gimli") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/lib.rs" enabled = !is_win sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/arch.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/common.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/constants.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/endianity.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/leb128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/abbrev.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/addr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/aranges.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/cfi.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/dwarf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/endian_reader.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/endian_slice.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/index.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/line.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/lists.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/loclists.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/lookup.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/op.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/pubnames.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/pubtypes.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/reader.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/relocate.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/rnglists.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/str.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/unit.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/util.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/read/value.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/test_util.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/write/abbrev.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/write/cfi.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/write/dwarf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/write/endian_vec.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/write/line.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/write/loc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/write/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/write/op.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/write/range.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/write/relocate.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/write/section.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/write/str.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/write/unit.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.31.1/src/write/writer.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/arch.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/common.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/constants.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/endianity.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/leb128.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/abbrev.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/addr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/aranges.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/cfi.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/dwarf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/endian_reader.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/endian_slice.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/index.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/line.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/lists.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/loclists.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/lookup.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/macros.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/op.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/pubnames.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/pubtypes.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/reader.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/relocate.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/rnglists.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/str.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/unit.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/util.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/read/value.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/test_util.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/write/abbrev.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/write/cfi.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/write/dwarf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/write/endian_vec.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/write/line.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/write/loc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/write/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/write/op.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/write/range.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/write/relocate.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/write/section.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/write/str.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/write/unit.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/gimli-0.32.0/src/write/writer.rs", ] inputs = [] no_std = true @@ -1213,10 +1186,11 @@ 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.31.1" + cargo_pkg_version = "0.32.0" cargo_pkg_name = "gimli" cargo_pkg_description = "A library for reading and writing the DWARF debugging format." + cargo_pkg_repository = "https://github.com/gimli-rs/gimli" library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", @@ -1233,7 +1207,6 @@ cargo_crate("gimli") { ] if (!is_win) { deps += [ - ":compiler_builtins", ":rustc_std_workspace_alloc", ":rustc_std_workspace_core", ] @@ -1261,35 +1234,35 @@ cargo_crate("gimli") { } cargo_crate("hashbrown") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/control/bitmask.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/control/group/generic.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/control/group/lsx.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/control/group/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/control/group/neon.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/control/group/sse2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/control/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/control/tag.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/external_trait_impls/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/external_trait_impls/rayon/helpers.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/external_trait_impls/rayon/map.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/external_trait_impls/rayon/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/external_trait_impls/rayon/raw.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/external_trait_impls/rayon/set.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/external_trait_impls/rayon/table.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/external_trait_impls/serde.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/macros.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/map.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/raw/alloc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/raw/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/raw_entry.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/rustc_entry.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/scopeguard.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/set.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/table.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/util.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/control/bitmask.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/control/group/generic.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/control/group/lsx.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/control/group/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/control/group/neon.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/control/group/sse2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/control/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/control/tag.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/external_trait_impls/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/external_trait_impls/rayon/helpers.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/external_trait_impls/rayon/map.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/external_trait_impls/rayon/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/external_trait_impls/rayon/raw.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/external_trait_impls/rayon/set.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/external_trait_impls/rayon/table.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/external_trait_impls/serde.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/macros.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/map.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/raw/alloc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/raw/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/raw_entry.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/rustc_entry.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/scopeguard.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/set.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/table.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.4/src/util.rs", ] inputs = [] no_std = true @@ -1297,10 +1270,11 @@ 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.15.3" + cargo_pkg_version = "0.15.4" cargo_pkg_authors = "Amanieu d'Antras " cargo_pkg_name = "hashbrown" cargo_pkg_description = "A Rust port of Google's SwissTable hash map" + cargo_pkg_repository = "https://github.com/rust-lang/hashbrown" library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", @@ -1312,7 +1286,6 @@ cargo_crate("hashbrown") { ] executable_configs += [ "//build/config/compiler:no_chromium_code" ] deps = [ - ":compiler_builtins", ":rustc_std_workspace_alloc", ":rustc_std_workspace_core", "//build/rust/std:profiler_builtins_group", @@ -1324,7 +1297,6 @@ cargo_crate("hashbrown") { } features = [ "alloc", - "compiler_builtins", "core", "nightly", "rustc-dep-of-std", @@ -1344,189 +1316,189 @@ cargo_crate("hashbrown") { } cargo_crate("libc") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/lib.rs" enabled = !is_win sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/fuchsia/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/fuchsia/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/fuchsia/riscv64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/fuchsia/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/hermit.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/macros.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/primitives.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/psp.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/sgx.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/solid/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/solid/arm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/solid/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/switch.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/teeos/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/trusty.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/aix/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/aix/powerpc64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/apple/b32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/apple/b64/aarch64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/apple/b64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/apple/b64/x86_64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/apple/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/dragonfly/errno.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/dragonfly/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/freebsd/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/freebsd/arm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/freebsd/freebsd11/b32.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/freebsd/freebsd15/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/freebsd/freebsd15/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/freebsd/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/freebsd/powerpc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/freebsd/powerpc64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/freebsd/riscv64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/freebsd/x86.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/freebsdlike/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/netbsdlike/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/netbsdlike/netbsd/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/netbsdlike/netbsd/arm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/netbsdlike/netbsd/mips.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/netbsdlike/netbsd/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/netbsdlike/netbsd/powerpc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/netbsdlike/netbsd/riscv64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/netbsdlike/netbsd/sparc64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/netbsdlike/netbsd/x86.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/netbsdlike/netbsd/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/netbsdlike/openbsd/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/netbsdlike/openbsd/arm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/netbsdlike/openbsd/mips64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/netbsdlike/openbsd/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/netbsdlike/openbsd/powerpc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/netbsdlike/openbsd/powerpc64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/netbsdlike/openbsd/riscv64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/netbsdlike/openbsd/sparc64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/netbsdlike/openbsd/x86.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/bsd/netbsdlike/openbsd/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/cygwin/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/haiku/b32.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/haiku/b64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/haiku/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/haiku/native.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/haiku/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/hurd/b32.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/hurd/b64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/hurd/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/android/b32/arm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/android/b32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/android/b32/x86/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/android/b64/aarch64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/android/b64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/android/b64/riscv64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/android/b64/x86_64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/android/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/emscripten/lfs64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/emscripten/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/arch/generic/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/arch/mips/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/arch/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/arch/powerpc/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/arch/sparc/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b32/arm/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b32/csky/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b32/m68k/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b32/mips/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b32/powerpc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b32/sparc/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b32/x86/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b64/mips64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b64/s390x.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/gnu/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/musl/b32/arm/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/musl/b32/hexagon.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/musl/b32/mips/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/musl/b32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/musl/b32/powerpc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/musl/b32/riscv32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/musl/b32/x86/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/musl/b64/aarch64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/musl/b64/loongarch64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/musl/b64/mips64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/musl/b64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/musl/b64/powerpc64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/musl/b64/riscv64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/musl/b64/s390x.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/musl/b64/wasm32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/musl/b64/wasm32/wali.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/musl/b64/x86_64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/musl/lfs64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/musl/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/uclibc/arm/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/uclibc/mips/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/uclibc/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/uclibc/x86_64/l4re.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/uclibc/x86_64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/linux/uclibc/x86_64/other.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/linux_like/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/newlib/aarch64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/newlib/arm/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/newlib/espidf/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/newlib/generic.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/newlib/horizon/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/newlib/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/newlib/powerpc/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/newlib/rtems/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/newlib/vita/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/nto/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/nto/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/nto/neutrino.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/nto/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/nuttx/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/redox/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/solarish/compat.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/solarish/illumos.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/solarish/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/solarish/solaris.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/solarish/x86.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/solarish/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/unix/solarish/x86_common.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/vxworks/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/vxworks/arm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/vxworks/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/vxworks/powerpc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/vxworks/powerpc64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/vxworks/riscv32.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/vxworks/riscv64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/vxworks/x86.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/vxworks/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/wasi/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/wasi/p2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/windows/gnu/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/windows/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/windows/msvc/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/src/xous.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/fuchsia/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/fuchsia/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/fuchsia/riscv64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/fuchsia/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/hermit.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/macros.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/primitives.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/psp.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/sgx.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/solid/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/solid/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/solid/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/switch.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/teeos/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/trusty.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/aix/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/aix/powerpc64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/apple/b32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/apple/b64/aarch64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/apple/b64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/apple/b64/x86_64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/apple/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/dragonfly/errno.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/dragonfly/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/freebsd/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/freebsd/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/freebsd/freebsd11/b32.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/freebsd/freebsd15/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/freebsd/freebsd15/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/freebsd/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/freebsd/powerpc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/freebsd/powerpc64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/freebsd/riscv64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/freebsd/x86.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/freebsdlike/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/netbsdlike/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/netbsdlike/netbsd/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/netbsdlike/netbsd/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/netbsdlike/netbsd/mips.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/netbsdlike/netbsd/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/netbsdlike/netbsd/powerpc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/netbsdlike/netbsd/riscv64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/netbsdlike/netbsd/sparc64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/netbsdlike/netbsd/x86.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/netbsdlike/netbsd/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/netbsdlike/openbsd/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/netbsdlike/openbsd/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/netbsdlike/openbsd/mips64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/netbsdlike/openbsd/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/netbsdlike/openbsd/powerpc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/netbsdlike/openbsd/powerpc64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/netbsdlike/openbsd/riscv64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/netbsdlike/openbsd/sparc64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/netbsdlike/openbsd/x86.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/bsd/netbsdlike/openbsd/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/cygwin/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/haiku/b32.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/haiku/b64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/haiku/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/haiku/native.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/haiku/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/hurd/b32.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/hurd/b64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/hurd/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/android/b32/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/android/b32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/android/b32/x86/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/android/b64/aarch64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/android/b64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/android/b64/riscv64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/android/b64/x86_64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/android/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/emscripten/lfs64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/emscripten/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/arch/generic/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/arch/mips/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/arch/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/arch/powerpc/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/arch/sparc/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b32/arm/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b32/csky/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b32/m68k/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b32/mips/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b32/powerpc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b32/sparc/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b32/x86/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b64/mips64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b64/s390x.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/gnu/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/musl/b32/arm/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/musl/b32/hexagon.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/musl/b32/mips/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/musl/b32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/musl/b32/powerpc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/musl/b32/riscv32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/musl/b32/x86/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/musl/b64/aarch64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/musl/b64/loongarch64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/musl/b64/mips64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/musl/b64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/musl/b64/powerpc64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/musl/b64/riscv64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/musl/b64/s390x.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/musl/b64/wasm32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/musl/b64/wasm32/wali.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/musl/b64/x86_64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/musl/lfs64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/musl/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/uclibc/arm/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/uclibc/mips/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/uclibc/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/uclibc/x86_64/l4re.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/uclibc/x86_64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/linux/uclibc/x86_64/other.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/linux_like/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/newlib/aarch64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/newlib/arm/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/newlib/espidf/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/newlib/generic.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/newlib/horizon/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/newlib/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/newlib/powerpc/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/newlib/rtems/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/newlib/vita/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/nto/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/nto/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/nto/neutrino.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/nto/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/nuttx/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/redox/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/solarish/compat.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/solarish/illumos.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/solarish/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/solarish/solaris.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/solarish/x86.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/solarish/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/unix/solarish/x86_common.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/vxworks/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/vxworks/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/vxworks/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/vxworks/powerpc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/vxworks/powerpc64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/vxworks/riscv32.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/vxworks/riscv64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/vxworks/x86.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/vxworks/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/wasi/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/wasi/p2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/windows/gnu/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/windows/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/windows/msvc/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/src/xous.rs", ] inputs = [] no_std = true @@ -1534,10 +1506,11 @@ cargo_crate("libc") { # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2021" - cargo_pkg_version = "0.2.172" + cargo_pkg_version = "0.2.174" cargo_pkg_authors = "The Rust Project Developers" cargo_pkg_name = "libc" cargo_pkg_description = "Raw FFI bindings to platform libraries like libc." + cargo_pkg_repository = "https://github.com/rust-lang/libc" library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", @@ -1558,8 +1531,8 @@ cargo_crate("libc") { "rustc-dep-of-std", "rustc-std-workspace-core", ] - build_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/build.rs" - build_sources = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.172/build.rs" ] + build_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/build.rs" + build_sources = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/libc-0.2.174/build.rs" ] rustenv = [ "CFG_DISABLE_UNSTABLE_FEATURES=0", "STD_ENV_ARCH=$rust_target_arch", @@ -1574,54 +1547,54 @@ cargo_crate("libc") { } cargo_crate("memchr") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/lib.rs" enabled = !is_win sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/aarch64/memchr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/aarch64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/aarch64/neon/memchr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/aarch64/neon/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/aarch64/neon/packedpair.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/all/memchr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/all/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/all/packedpair/default_rank.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/all/packedpair/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/all/rabinkarp.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/all/shiftor.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/all/twoway.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/generic/memchr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/generic/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/generic/packedpair.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/wasm32/memchr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/wasm32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/wasm32/simd128/memchr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/wasm32/simd128/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/wasm32/simd128/packedpair.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/x86_64/avx2/memchr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/x86_64/avx2/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/x86_64/avx2/packedpair.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/x86_64/memchr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/x86_64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/x86_64/sse2/memchr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/x86_64/sse2/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/arch/x86_64/sse2/packedpair.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/cow.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/ext.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/macros.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/memchr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/memmem/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/memmem/searcher.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/tests/memchr/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/tests/memchr/naive.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/tests/memchr/prop.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/tests/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/tests/packedpair.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/tests/substring/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/tests/substring/naive.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/tests/substring/prop.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.4/src/vector.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/aarch64/memchr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/aarch64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/aarch64/neon/memchr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/aarch64/neon/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/aarch64/neon/packedpair.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/all/memchr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/all/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/all/packedpair/default_rank.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/all/packedpair/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/all/rabinkarp.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/all/shiftor.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/all/twoway.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/generic/memchr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/generic/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/generic/packedpair.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/wasm32/memchr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/wasm32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/wasm32/simd128/memchr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/wasm32/simd128/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/wasm32/simd128/packedpair.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/x86_64/avx2/memchr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/x86_64/avx2/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/x86_64/avx2/packedpair.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/x86_64/memchr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/x86_64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/x86_64/sse2/memchr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/x86_64/sse2/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/arch/x86_64/sse2/packedpair.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/cow.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/ext.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/macros.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/memchr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/memmem/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/memmem/searcher.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/tests/memchr/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/tests/memchr/naive.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/tests/memchr/prop.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/tests/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/tests/packedpair.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/tests/substring/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/tests/substring/naive.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/tests/substring/prop.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/memchr-2.7.5/src/vector.rs", ] inputs = [] no_std = true @@ -1629,10 +1602,11 @@ cargo_crate("memchr") { # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2021" - cargo_pkg_version = "2.7.4" + cargo_pkg_version = "2.7.5" cargo_pkg_authors = "Andrew Gallant , bluss" cargo_pkg_name = "memchr" cargo_pkg_description = "Provides extremely fast (uses SIMD on x86_64, aarch64 and wasm32) routines for 1, 2 or 3 byte search and single substring search." + cargo_pkg_repository = "https://github.com/BurntSushi/memchr" library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", @@ -1648,16 +1622,12 @@ cargo_crate("memchr") { "//build/rust/std:std_build_deps", ] if (!is_win) { - deps += [ - ":compiler_builtins", - ":rustc_std_workspace_core", - ] + deps += [ ":rustc_std_workspace_core" ] } aliased_deps = { core = ":rustc_std_workspace_core" } features = [ - "compiler_builtins", "core", "rustc-dep-of-std", ] @@ -1675,23 +1645,23 @@ cargo_crate("memchr") { } cargo_crate("miniz_oxide") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.9/src/lib.rs" enabled = !is_win sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/deflate/buffer.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/deflate/core.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/deflate/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/deflate/stored.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/deflate/stream.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/deflate/zlib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/inflate/core.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/inflate/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/inflate/output_buffer.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/inflate/stream.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/serde/big_array.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/serde/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/shared.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.9/src/deflate/buffer.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.9/src/deflate/core.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.9/src/deflate/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.9/src/deflate/stored.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.9/src/deflate/stream.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.9/src/deflate/zlib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.9/src/inflate/core.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.9/src/inflate/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.9/src/inflate/output_buffer.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.9/src/inflate/stream.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.9/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.9/src/serde/big_array.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.9/src/serde/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.9/src/shared.rs", ] inputs = [] no_std = true @@ -1699,10 +1669,12 @@ cargo_crate("miniz_oxide") { # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2021" - cargo_pkg_version = "0.8.8" + cargo_pkg_version = "0.8.9" cargo_pkg_authors = "Frommi , oyvindln , Rich Geldreich richgel99@gmail.com" cargo_pkg_name = "miniz_oxide" cargo_pkg_description = "DEFLATE compression and decompression library rewritten in Rust based on miniz" + cargo_pkg_repository = + "https://github.com/Frommi/miniz_oxide/tree/master/miniz_oxide" library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", @@ -1720,7 +1692,6 @@ cargo_crate("miniz_oxide") { if (!is_win) { deps += [ ":adler2", - ":compiler_builtins", ":rustc_std_workspace_alloc", ":rustc_std_workspace_core", ] @@ -1731,7 +1702,6 @@ cargo_crate("miniz_oxide") { } features = [ "alloc", - "compiler_builtins", "core", "rustc-dep-of-std", ] @@ -1749,89 +1719,89 @@ cargo_crate("miniz_oxide") { } cargo_crate("object") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/lib.rs" enabled = !is_win sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/archive.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/build/bytes.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/build/elf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/build/error.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/build/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/build/table.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/common.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/elf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/endian.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/macho.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/pe.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/pod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/any.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/archive.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/coff/comdat.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/coff/file.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/coff/import.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/coff/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/coff/relocation.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/coff/section.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/coff/symbol.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/elf/attributes.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/elf/comdat.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/elf/compression.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/elf/dynamic.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/elf/file.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/elf/hash.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/elf/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/elf/note.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/elf/relocation.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/elf/section.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/elf/segment.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/elf/symbol.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/elf/version.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/gnu_compression.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/macho/dyld_cache.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/macho/fat.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/macho/file.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/macho/load_command.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/macho/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/macho/relocation.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/macho/section.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/macho/segment.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/macho/symbol.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/pe/data_directory.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/pe/export.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/pe/file.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/pe/import.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/pe/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/pe/relocation.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/pe/resource.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/pe/rich.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/pe/section.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/read_cache.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/read_ref.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/traits.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/util.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/wasm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/xcoff/comdat.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/xcoff/file.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/xcoff/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/xcoff/relocation.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/xcoff/section.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/xcoff/segment.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/read/xcoff/symbol.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/write/coff/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/write/coff/object.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/write/coff/writer.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/write/elf/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/write/elf/object.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/write/elf/writer.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/write/macho.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/write/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/write/pe.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/write/string.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/write/util.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/write/xcoff.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/src/xcoff.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/archive.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/build/bytes.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/build/elf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/build/error.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/build/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/build/table.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/common.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/elf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/endian.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/macho.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/pe.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/pod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/any.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/archive.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/coff/comdat.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/coff/file.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/coff/import.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/coff/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/coff/relocation.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/coff/section.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/coff/symbol.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/elf/attributes.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/elf/comdat.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/elf/compression.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/elf/dynamic.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/elf/file.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/elf/hash.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/elf/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/elf/note.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/elf/relocation.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/elf/section.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/elf/segment.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/elf/symbol.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/elf/version.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/gnu_compression.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/macho/dyld_cache.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/macho/fat.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/macho/file.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/macho/load_command.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/macho/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/macho/relocation.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/macho/section.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/macho/segment.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/macho/symbol.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/pe/data_directory.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/pe/export.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/pe/file.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/pe/import.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/pe/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/pe/relocation.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/pe/resource.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/pe/rich.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/pe/section.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/read_cache.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/read_ref.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/traits.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/util.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/wasm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/xcoff/comdat.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/xcoff/file.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/xcoff/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/xcoff/relocation.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/xcoff/section.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/xcoff/segment.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/read/xcoff/symbol.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/write/coff/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/write/coff/object.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/write/coff/writer.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/write/elf/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/write/elf/object.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/write/elf/writer.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/write/macho.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/write/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/write/pe.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/write/string.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/write/util.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/write/xcoff.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/src/xcoff.rs", ] inputs = [] no_std = true @@ -1839,10 +1809,11 @@ 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.36.7" + cargo_pkg_version = "0.37.1" cargo_pkg_name = "object" cargo_pkg_description = "A unified interface for reading and writing object file formats." + cargo_pkg_repository = "https://github.com/gimli-rs/object" library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", @@ -1859,7 +1830,6 @@ cargo_crate("object") { ] if (!is_win) { deps += [ - ":compiler_builtins", ":memchr", ":rustc_std_workspace_alloc", ":rustc_std_workspace_core", @@ -1873,7 +1843,6 @@ cargo_crate("object") { "alloc", "archive", "coff", - "compiler_builtins", "core", "elf", "macho", @@ -1883,8 +1852,8 @@ cargo_crate("object") { "unaligned", "xcoff", ] - build_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/build.rs" - build_sources = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.36.7/build.rs" ] + build_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/build.rs" + build_sources = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/object-0.37.1/build.rs" ] rustenv = [ "CFG_DISABLE_UNSTABLE_FEATURES=0", "STD_ENV_ARCH=$rust_target_arch", @@ -1914,6 +1883,7 @@ cargo_crate("panic_abort") { cargo_pkg_version = "0.0.0" cargo_pkg_name = "panic_abort" cargo_pkg_description = "Implementation of Rust panics via process aborts" + cargo_pkg_repository = "https://github.com/rust-lang/rust.git" library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", @@ -1925,15 +1895,16 @@ cargo_crate("panic_abort") { ] executable_configs += [ "//build/config/compiler:no_chromium_code" ] deps = [ - ":alloc", - ":cfg_if", ":compiler_builtins", ":core", "//build/rust/std:profiler_builtins_group", "//build/rust/std:std_build_deps", ] - if (!is_win) { - deps += [ ":libc" ] + if (is_android) { + deps += [ + ":alloc", + ":libc", + ] } rustenv = [ "CFG_DISABLE_UNSTABLE_FEATURES=0", @@ -1968,6 +1939,7 @@ cargo_crate("panic_unwind") { cargo_pkg_version = "0.0.0" cargo_pkg_name = "panic_unwind" cargo_pkg_description = "Implementation of Rust panics via stack unwinding" + cargo_pkg_repository = "https://github.com/rust-lang/rust.git" library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", @@ -2048,6 +2020,10 @@ cargo_crate("proc_macro") { "//build/rust/std:profiler_builtins_group", "//build/rust/std:std_build_deps", ] + features = [ + "default", + "rustc-dep-of-std", + ] rustenv = [ "CFG_DISABLE_UNSTABLE_FEATURES=0", "STD_ENV_ARCH=$rust_target_arch", @@ -2098,11 +2074,11 @@ cargo_crate("profiler_builtins") { } cargo_crate("rustc_demangle") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/rustc-demangle-0.1.24/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/rustc-demangle-0.1.25/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/rustc-demangle-0.1.24/src/legacy.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/rustc-demangle-0.1.24/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/rustc-demangle-0.1.24/src/v0.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/rustc-demangle-0.1.25/src/legacy.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/rustc-demangle-0.1.25/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/rustc-demangle-0.1.25/src/v0.rs", ] inputs = [] no_std = true @@ -2110,10 +2086,11 @@ 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.24" + cargo_pkg_version = "0.1.25" cargo_pkg_authors = "Alex Crichton " cargo_pkg_name = "rustc-demangle" cargo_pkg_description = "Rust compiler symbol demangling." + cargo_pkg_repository = "https://github.com/rust-lang/rustc-demangle" library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", @@ -2125,7 +2102,6 @@ cargo_crate("rustc_demangle") { ] executable_configs += [ "//build/config/compiler:no_chromium_code" ] deps = [ - ":compiler_builtins", ":rustc_std_workspace_core", "//build/rust/std:profiler_builtins_group", "//build/rust/std:std_build_deps", @@ -2134,7 +2110,6 @@ cargo_crate("rustc_demangle") { core = ":rustc_std_workspace_core" } features = [ - "compiler_builtins", "core", "rustc-dep-of-std", ] @@ -2166,6 +2141,7 @@ cargo_crate("rustc_literal_escaper") { cargo_pkg_version = "0.0.2" cargo_pkg_name = "rustc-literal-escaper" cargo_pkg_description = "Provides code to unescape string literals" + cargo_pkg_repository = "https://github.com/rust-lang/literal-escaper" library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", @@ -2262,6 +2238,7 @@ cargo_crate("rustc_std_workspace_core") { ] executable_configs += [ "//build/config/compiler:no_chromium_code" ] deps = [ + ":compiler_builtins", ":core", "//build/rust/std:std_build_deps", ] @@ -2335,10 +2312,6 @@ cargo_crate("std") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/collections/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/env.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/error.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/f128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/f16.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/f32.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/f64.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/ffi/c_str.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/ffi/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/ffi/os_str.rs", @@ -2387,7 +2360,11 @@ cargo_crate("std") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/net/test.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/net/udp.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/net/udp/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/num.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/num/f128.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/num/f16.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/num/f32.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/num/f64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/num/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/os/aix/fs.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/os/aix/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/os/aix/raw.rs", @@ -2653,6 +2630,8 @@ cargo_crate("std") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/net/connection/socket/wasip2.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/net/connection/socket/windows.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/net/connection/uefi/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/net/connection/uefi/tcp.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/net/connection/uefi/tcp4.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/net/connection/unsupported.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/net/connection/wasip1.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/net/connection/xous/dns.rs", @@ -2735,6 +2714,7 @@ cargo_crate("std") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/os/tests.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/pipe.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/stack_overflow.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/stack_overflow/thread_info.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/sync/condvar.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/sync/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/sync/mutex.rs", @@ -2783,6 +2763,7 @@ cargo_crate("std") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/zkvm/abi.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/zkvm/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/zkvm/os.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/path/cygwin.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/path/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/path/sgx.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/path/uefi.rs", @@ -2790,15 +2771,18 @@ cargo_crate("std") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/path/unsupported_backslash.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/path/windows.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/path/windows/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/path/windows_prefix.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/personality/dwarf/eh.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/personality/dwarf/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/personality/dwarf/tests.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/personality/emcc.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/personality/gcc.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/personality/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/process/env.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/process/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/process/uefi.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/process/unix/common.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/process/unix/common/cstring_array.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/process/unix/common/tests.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/process/unix/fuchsia.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/process/unix/mod.rs", @@ -2901,7 +2885,6 @@ cargo_crate("std") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/thread_local/no_threads.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/thread_local/os.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys_common/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys_common/process.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys_common/tests.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys_common/wstr.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys_common/wtf8.rs", @@ -2970,6 +2953,10 @@ cargo_crate("std") { "//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/../../core/src/ptr/docs/add.md", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/../../core/src/ptr/docs/as_uninit_slice.md", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/../../core/src/ptr/docs/is_null.md", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/../../core/src/ptr/docs/offset.md", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/../../portable-simd/crates/core_simd/src/core_simd_docs.md", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/../../portable-simd/crates/std_float/src/lib.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/../../stdarch/crates/core_arch/src/core_arch_docs.md", @@ -2983,6 +2970,7 @@ cargo_crate("std") { cargo_pkg_version = "0.0.0" cargo_pkg_name = "std" cargo_pkg_description = "The Rust Standard Library" + cargo_pkg_repository = "https://github.com/rust-lang/rust.git" library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", @@ -3100,6 +3088,7 @@ cargo_crate("std_detect") { cargo_pkg_name = "std_detect" cargo_pkg_description = "`std::detect` - Rust's standard library run-time CPU feature detection." + cargo_pkg_repository = "https://github.com/rust-lang/stdarch" library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", @@ -3112,7 +3101,6 @@ cargo_crate("std_detect") { executable_configs += [ "//build/config/compiler:no_chromium_code" ] deps = [ ":cfg_if", - ":compiler_builtins", ":rustc_std_workspace_alloc", ":rustc_std_workspace_core", "//build/rust/std:profiler_builtins_group", @@ -3127,7 +3115,6 @@ cargo_crate("std_detect") { } features = [ "alloc", - "compiler_builtins", "core", "libc", "rustc-dep-of-std", @@ -3272,10 +3259,10 @@ cargo_crate("test") { } cargo_crate("unicode_width") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/unicode-width-0.1.14/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/unicode-width-0.2.1/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/unicode-width-0.1.14/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/unicode-width-0.1.14/src/tables.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/unicode-width-0.2.1/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/unicode-width-0.2.1/src/tables.rs", ] inputs = [] no_std = true @@ -3283,11 +3270,12 @@ cargo_crate("unicode_width") { # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2021" - cargo_pkg_version = "0.1.14" + cargo_pkg_version = "0.2.1" cargo_pkg_authors = "kwantam , Manish Goregaokar " cargo_pkg_name = "unicode-width" cargo_pkg_description = "Determine displayed width of `char` and `str` types according to Unicode Standard Annex #11 rules." + cargo_pkg_repository = "https://github.com/unicode-rs/unicode-width" library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", @@ -3299,7 +3287,6 @@ cargo_crate("unicode_width") { ] executable_configs += [ "//build/config/compiler:no_chromium_code" ] deps = [ - ":compiler_builtins", ":rustc_std_workspace_core", ":rustc_std_workspace_std", "//build/rust/std:profiler_builtins_group", @@ -3311,7 +3298,6 @@ cargo_crate("unicode_width") { } features = [ "cjk", - "compiler_builtins", "core", "default", "rustc-dep-of-std", @@ -3346,6 +3332,7 @@ cargo_crate("unwind") { edition = "2024" cargo_pkg_version = "0.0.0" cargo_pkg_name = "unwind" + cargo_pkg_repository = "https://github.com/rust-lang/rust.git" library_configs -= [ "//build/config/compiler:chromium_code", "//build/config/compiler:disallow_unstable_features", diff --git a/naiveproxy/src/build/rust/tests/BUILD.gn b/naiveproxy/src/build/rust/tests/BUILD.gn index 5a2c262e0d..4ca86cbc54 100644 --- a/naiveproxy/src/build/rust/tests/BUILD.gn +++ b/naiveproxy/src/build/rust/tests/BUILD.gn @@ -29,6 +29,7 @@ group("deps") { "//build/rust/tests/test_aliased_deps", "//build/rust/tests/test_aliased_deps:test_aliased_deps_exe", "//build/rust/tests/test_bin_crate", + "//build/rust/tests/test_cxx_cfg", "//build/rust/tests/test_rlib_crate:target1", "//build/rust/tests/test_rlib_crate:target2", "//build/rust/tests/test_rlib_crate:test_rlib_crate_associated_bin", @@ -42,7 +43,7 @@ group("deps") { # TODO(crbug.com/40226863): Enable the additional target below # once `rs_bindings_from_cc` is distributed via `gclient sync`. In the # meantime see the instructions in - # `//build/rust/run_rs_bindings_from_cc.py`. + # `//build/rust/gni_impl/run_rs_bindings_from_cc.py`. #"test_rs_bindings_from_cc:test_rs_bindings_from_cc", ] @@ -93,7 +94,7 @@ group("deps") { # TODO(crbug.com/40226863): Enable the additional target below # once `rs_bindings_from_cc` is distributed via `gclient sync`. In the # meantime see the instructions in - # `//build/rust/run_rs_bindings_from_cc.py`. + # `//build/rust/gni_impl/run_rs_bindings_from_cc.py`. #"test_rs_bindings_from_cc:test_rs_bindings_from_cc_unittests", ] diff --git a/naiveproxy/src/build/rust/tests/test_cpp_including_rust/BUILD.gn b/naiveproxy/src/build/rust/tests/test_cpp_including_rust/BUILD.gn index 3e974fc4a7..42f3541989 100644 --- a/naiveproxy/src/build/rust/tests/test_cpp_including_rust/BUILD.gn +++ b/naiveproxy/src/build/rust/tests/test_cpp_including_rust/BUILD.gn @@ -16,6 +16,7 @@ test("test_cpp_including_rust_unittests") { "//base", "//base/allocator:buildflags", "//base/test:run_all_unittests", + "//build/rust/tests/test_cxx_cfg", "//build/rust/tests/test_rust_static_library", "//testing/gmock", "//testing/gtest", diff --git a/naiveproxy/src/build/rust/tests/test_cxx_cfg/BUILD.gn b/naiveproxy/src/build/rust/tests/test_cxx_cfg/BUILD.gn new file mode 100644 index 0000000000..a36c320800 --- /dev/null +++ b/naiveproxy/src/build/rust/tests/test_cxx_cfg/BUILD.gn @@ -0,0 +1,23 @@ +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/rust/rust_static_library.gni") +import("//testing/test.gni") + +source_set("test_cxx_cfg") { + testonly = true + sources = [ "cxx_cfg_unittests.cc" ] + deps = [ + ":rust_lib", + "//testing/gtest", + ] +} + +rust_static_library("rust_lib") { + crate_root = "cxx_cfg_lib.rs" + sources = [ crate_root ] + cxx_bindings = [ crate_root ] + allow_unsafe = true + visibility = [ ":*" ] +} diff --git a/naiveproxy/src/build/rust/tests/test_cxx_cfg/cxx_cfg_lib.rs b/naiveproxy/src/build/rust/tests/test_cxx_cfg/cxx_cfg_lib.rs new file mode 100644 index 0000000000..13f2c8cd87 --- /dev/null +++ b/naiveproxy/src/build/rust/tests/test_cxx_cfg/cxx_cfg_lib.rs @@ -0,0 +1,39 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +//! This focuses on testing if `#[cfg(...)]` works inside `#[cxx::bridge]`. +//! For that to work, the appropriate `--cfg=foo=bar` configuration values +//! have to be passed into `cxxbridge-cmd` invocation. + +// TODO(https://crbug.com/435437947): This should also cover additional configuration conditions: +// +// * Ones without `=` like `unix` +// * Ones associated with crate features (maybe; we don't provide `cxx` +// integration for `cargo_crate` targets...) +// * Ones associated with plain-vanilla `--cfg=...` set via `rustflags` of +// `rust_static_library` or of `config`. + +#[cxx::bridge(namespace = "rust_test")] +mod ffi { + extern "Rust" { + // TODO(https://crbug.com/435437947): Also handle + test the spelling of + // `#[cfg(unix)]`. This requires knowing somehow (?) that `unix=false` + // for Windows target triples :-/ + #[cfg(target_family = "unix")] + fn double_unix_value(x: u32) -> u32; + + #[cfg(not(target_family = "unix"))] + fn double_non_unix_value(x: u32) -> u32; + } +} + +#[cfg(target_family = "unix")] +fn double_unix_value(x: u32) -> u32 { + x * 2 +} + +#[cfg(not(target_family = "unix"))] +fn double_non_unix_value(x: u32) -> u32 { + x + x +} diff --git a/naiveproxy/src/build/rust/tests/test_cxx_cfg/cxx_cfg_unittests.cc b/naiveproxy/src/build/rust/tests/test_cxx_cfg/cxx_cfg_unittests.cc new file mode 100644 index 0000000000..52e5839e7e --- /dev/null +++ b/naiveproxy/src/build/rust/tests/test_cxx_cfg/cxx_cfg_unittests.cc @@ -0,0 +1,27 @@ +// Copyright 2025 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 "build/build_config.h" +#include "build/rust/tests/test_cxx_cfg/cxx_cfg_lib.rs.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +TEST(RustCxxCfgTest, MainTest) { +// `#[cfg(target_family = "unix")]` covers Fuchsia, but +// `BUILD_FLAG(IS_POSIX)` does not cover Fuchsia. +// +// So we need to `||` two conditions together to get an equivalent of Rust-side +// `#[cfg(target_family = "unix")]` from `cxx_cfg_lib.rs`. +#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) + uint32_t actual = rust_test::double_unix_value(123); +#else + uint32_t actual = rust_test::double_non_unix_value(123); +#endif + EXPECT_EQ(actual, 123u * 2u); +} + +} // namespace diff --git a/naiveproxy/src/build/toolchain/apple/compile_xcassets.py b/naiveproxy/src/build/toolchain/apple/compile_xcassets.py index 3fe9bbbde6..f99192129b 100644 --- a/naiveproxy/src/build/toolchain/apple/compile_xcassets.py +++ b/naiveproxy/src/build/toolchain/apple/compile_xcassets.py @@ -41,16 +41,16 @@ ACTOOL_FLAG_FOR_ASSET_TYPE = { } def FixAbsolutePathInLine(line, relative_paths): - """Fix absolute paths present in |line| to relative paths.""" - absolute_path = line.split(':')[0] - relative_path = relative_paths.get(absolute_path, absolute_path) - if absolute_path == relative_path: - return line - return relative_path + line[len(absolute_path):] + """Fix absolute paths present in |line| to relative paths.""" + absolute_path = line.split(':')[0] + relative_path = relative_paths.get(absolute_path, absolute_path) + if absolute_path == relative_path: + return line + return relative_path + line[len(absolute_path):] def FilterCompilerOutput(compiler_output, relative_paths): - """Filers actool compilation output. + """Filers actool compilation output. The compiler output is composed of multiple sections for each different level of output (error, warning, notices, ...). Each section starts with @@ -77,31 +77,31 @@ def FilterCompilerOutput(compiler_output, relative_paths): relative path and omit any irrelevant output. """ - filtered_output = [] - current_section = None - data_in_section = False - for line in compiler_output.splitlines(): - match = SECTION_HEADER.search(line) - if match is not None: - data_in_section = False - current_section = match.group(1) - continue - if current_section and current_section != NOTICE_SECTION: - if not data_in_section: - data_in_section = True - filtered_output.append('/* %s */\n' % current_section) + filtered_output = [] + current_section = None + data_in_section = False + for line in compiler_output.splitlines(): + match = SECTION_HEADER.search(line) + if match is not None: + data_in_section = False + current_section = match.group(1) + continue + if current_section and current_section != NOTICE_SECTION: + if not data_in_section: + data_in_section = True + filtered_output.append('/* %s */\n' % current_section) - fixed_line = FixAbsolutePathInLine(line, relative_paths) - filtered_output.append(fixed_line + '\n') + fixed_line = FixAbsolutePathInLine(line, relative_paths) + filtered_output.append(fixed_line + '\n') - return ''.join(filtered_output) + return ''.join(filtered_output) def CompileAssetCatalog(output, target_os, target_environment, product_type, min_deployment_target, possibly_zipped_inputs, compress_pngs, target_platform, partial_info_plist, app_icon, include_all_app_icons, temporary_dir): - """Compile the .xcassets bundles to an asset catalog using actool. + """Compile the .xcassets bundles to an asset catalog using actool. Args: output: absolute path to the containing bundle @@ -114,280 +114,290 @@ def CompileAssetCatalog(output, target_os, target_environment, product_type, partial_info_plist: path to partial Info.plist to generate temporary_dir: path to directory for storing temp data """ - command = [ - 'xcrun', - 'actool', - '--output-format=human-readable-text', - '--notices', - '--warnings', - '--errors', - '--minimum-deployment-target', - min_deployment_target, - ] + command = [ + 'xcrun', + 'actool', + '--output-format=human-readable-text', + '--notices', + '--warnings', + '--errors', + '--minimum-deployment-target', + min_deployment_target, + ] - if compress_pngs: - command.extend(['--compress-pngs']) + if compress_pngs: + command.extend(['--compress-pngs']) - if product_type != '': - command.extend(['--product-type', product_type]) + if product_type != '': + command.extend(['--product-type', product_type]) - if target_os == 'mac': - command.extend([ - '--platform', - 'macosx', - '--target-device', - 'mac', - ]) - elif target_os == 'ios': - if target_platform == 'tvos': - if target_environment == 'simulator': - command.extend([ - '--platform', - 'appletvsimulator', - '--target-device', - 'tv', - ]) - elif target_environment == 'device': - command.extend([ - '--platform', - 'appletvos', - '--target-device', - 'tv', - ]) - else: - sys.stderr.write( - 'Unsupported tvos environment: %s' % target_environment) - sys.exit(1) - else: - if target_environment == 'simulator': - command.extend([ - '--platform', - 'iphonesimulator', - '--target-device', - 'iphone', - '--target-device', - 'ipad', - ]) - elif target_environment == 'device': - command.extend([ - '--platform', - 'iphoneos', - '--target-device', - 'iphone', - '--target-device', - 'ipad', - ]) - elif target_environment == 'catalyst': + if target_os == 'mac': command.extend([ '--platform', 'macosx', '--target-device', - 'ipad', - '--ui-framework-family', - 'uikit', + 'mac', ]) - else: - sys.stderr.write( - 'Unsupported iphoneos environment: %s' % target_environment) - sys.exit(1) - elif target_os == 'watchos': - if target_environment == 'simulator': - command.extend([ - '--platform', - 'watchsimulator', - '--target-device', - 'watch', - ]) - elif target_environment == 'device': - command.extend([ - '--platform', - 'watchos', - '--target-device', - 'watch', - ]) - else: - sys.stderr.write( - 'Unsupported watchos environment: %s' % target_environment) - sys.exit(1) - - # Unzip any input zipfiles to a temporary directory. - inputs = [] - for relative_path in possibly_zipped_inputs: - if os.path.isfile(relative_path) and zipfile.is_zipfile(relative_path): - catalog_name = os.path.basename(relative_path) - unzip_path = os.path.join(temporary_dir, os.path.dirname(relative_path)) - with zipfile.ZipFile(relative_path) as z: - invalid_files = [ - x for x in z.namelist() - if '..' in x or not x.startswith(catalog_name) - ] - if invalid_files: - sys.stderr.write('Invalid files in zip: %s' % invalid_files) - sys.exit(1) - z.extractall(unzip_path) - inputs.append(os.path.join(unzip_path, catalog_name)) - else: - inputs.append(relative_path) - - # Scan the input directories for the presence of asset catalog types that - # require special treatment, and if so, add them to the actool command-line. - for relative_path in inputs: - - if not os.path.isdir(relative_path): - continue - - for file_or_dir_name in os.listdir(relative_path): - if not os.path.isdir(os.path.join(relative_path, file_or_dir_name)): - continue - - asset_name, asset_type = os.path.splitext(file_or_dir_name) - - # If the asset is an app icon, and the caller has specified an app icon - # to use, then skip this asset as it will be included in the app icon - # set. Otherwise, add the asset to the command-line. - if asset_type == APP_ICON_ASSET_TYPE: - if app_icon: - continue + elif target_os == 'ios': + if target_platform == 'tvos': + if target_environment == 'simulator': + command.extend([ + '--platform', + 'appletvsimulator', + '--target-device', + 'tv', + ]) + elif target_environment == 'device': + command.extend([ + '--platform', + 'appletvos', + '--target-device', + 'tv', + ]) + else: + sys.stderr.write('Unsupported tvos environment: %s' % + target_environment) + sys.exit(1) else: - command.extend(['--app-icon', asset_name]) + if target_environment == 'simulator': + command.extend([ + '--platform', + 'iphonesimulator', + '--target-device', + 'iphone', + '--target-device', + 'ipad', + ]) + elif target_environment == 'device': + command.extend([ + '--platform', + 'iphoneos', + '--target-device', + 'iphone', + '--target-device', + 'ipad', + ]) + elif target_environment == 'catalyst': + command.extend([ + '--platform', + 'macosx', + '--target-device', + 'ipad', + '--ui-framework-family', + 'uikit', + ]) + else: + sys.stderr.write('Unsupported iphoneos environment: %s' % + target_environment) + sys.exit(1) + elif target_os == 'watchos': + if target_environment == 'simulator': + command.extend([ + '--platform', + 'watchsimulator', + '--target-device', + 'watch', + ]) + elif target_environment == 'device': + command.extend([ + '--platform', + 'watchos', + '--target-device', + 'watch', + ]) + else: + sys.stderr.write('Unsupported watchos environment: %s' % + target_environment) + sys.exit(1) - if asset_type not in ACTOOL_FLAG_FOR_ASSET_TYPE: - continue + # Unzip any input zipfiles to a temporary directory. + inputs = [] + for relative_path in possibly_zipped_inputs: + if os.path.isfile(relative_path) and zipfile.is_zipfile(relative_path): + catalog_name = os.path.basename(relative_path) + unzip_path = os.path.join(temporary_dir, + os.path.dirname(relative_path)) + with zipfile.ZipFile(relative_path) as z: + invalid_files = [ + x for x in z.namelist() + if '..' in x or not x.startswith(catalog_name) + ] + if invalid_files: + sys.stderr.write('Invalid files in zip: %s' % + invalid_files) + sys.exit(1) + z.extractall(unzip_path) + inputs.append(os.path.join(unzip_path, catalog_name)) + else: + inputs.append(relative_path) - command.extend([ACTOOL_FLAG_FOR_ASSET_TYPE[asset_type], asset_name]) + # Scan the input directories for the presence of asset catalog types that + # require special treatment, and if so, add them to the actool command-line. + for relative_path in inputs: - if app_icon: - command.extend(['--app-icon', app_icon]) + if not os.path.isdir(relative_path): + continue - if include_all_app_icons: - command.extend(['--include-all-app-icons']) + for file_or_dir_name in os.listdir(relative_path): + if not os.path.isdir(os.path.join(relative_path, + file_or_dir_name)): + continue - # Always ask actool to generate a partial Info.plist file. If no path - # has been given by the caller, use a temporary file name. - temporary_file = None - if not partial_info_plist: - temporary_file = tempfile.NamedTemporaryFile(suffix='.plist') - partial_info_plist = temporary_file.name + asset_name, asset_type = os.path.splitext(file_or_dir_name) - command.extend(['--output-partial-info-plist', partial_info_plist]) + # If the asset is an app icon, and the caller has specified an app + # icon to use, then skip this asset as it will be included in the + # app icon set. Otherwise, add the asset to the command-line. + if asset_type == APP_ICON_ASSET_TYPE: + if app_icon: + continue + else: + command.extend(['--app-icon', asset_name]) - # Dictionary used to convert absolute paths back to their relative form - # in the output of actool. - relative_paths = {} + if asset_type not in ACTOOL_FLAG_FOR_ASSET_TYPE: + continue - # actool crashes if paths are relative, so convert input and output paths - # to absolute paths, and record the relative paths to fix them back when - # filtering the output. - absolute_output = os.path.abspath(output) - relative_paths[output] = absolute_output - relative_paths[os.path.dirname(output)] = os.path.dirname(absolute_output) - command.extend(['--compile', os.path.dirname(os.path.abspath(output))]) + command.extend( + [ACTOOL_FLAG_FOR_ASSET_TYPE[asset_type], asset_name]) - for relative_path in inputs: - absolute_path = os.path.abspath(relative_path) - relative_paths[absolute_path] = relative_path - command.append(absolute_path) + if app_icon: + command.extend(['--app-icon', app_icon]) - try: - # Run actool and redirect stdout and stderr to the same pipe (as actool - # is confused about what should go to stderr/stdout). - process = subprocess.Popen(command, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - stdout = process.communicate()[0].decode('utf-8') + if include_all_app_icons: + command.extend(['--include-all-app-icons']) - # If the invocation of `actool` failed, copy all the compiler output to - # the standard error stream and exit. See https://crbug.com/1205775 for - # example of compilation that failed with no error message due to filter. - if process.returncode: - for line in stdout.splitlines(): - fixed_line = FixAbsolutePathInLine(line, relative_paths) - sys.stderr.write(fixed_line + '\n') - sys.exit(1) + # Always ask actool to generate a partial Info.plist file. If no path + # has been given by the caller, use a temporary file name. + temporary_file = None + if not partial_info_plist: + temporary_file = tempfile.NamedTemporaryFile(suffix='.plist') + partial_info_plist = temporary_file.name - # Filter the output to remove all garbage and to fix the paths. If the - # output is not empty after filtering, then report the compilation as a - # failure (as some version of `actool` report error to stdout, yet exit - # with an return code of zero). - stdout = FilterCompilerOutput(stdout, relative_paths) - if stdout: - sys.stderr.write(stdout) - sys.exit(1) + command.extend(['--output-partial-info-plist', partial_info_plist]) - finally: - if temporary_file: - temporary_file.close() + # Dictionary used to convert absolute paths back to their relative form + # in the output of actool. + relative_paths = {} + + # actool crashes if paths are relative, so convert input and output paths + # to absolute paths, and record the relative paths to fix them back when + # filtering the output. + absolute_output = os.path.abspath(output) + relative_paths[output] = absolute_output + relative_paths[os.path.dirname(output)] = os.path.dirname(absolute_output) + command.extend(['--compile', os.path.dirname(os.path.abspath(output))]) + + for relative_path in inputs: + absolute_path = os.path.abspath(relative_path) + relative_paths[absolute_path] = relative_path + command.append(absolute_path) + + try: + # Run actool and redirect stdout and stderr to the same pipe (as actool + # is confused about what should go to stderr/stdout). + process = subprocess.Popen(command, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + stdout = process.communicate()[0].decode('utf-8') + + # If the invocation of `actool` failed, copy all the compiler output to + # the standard error stream and exit. See https://crbug.com/1205775 for + # example of compilation that failed with no error message due to + # filter. + if process.returncode: + for line in stdout.splitlines(): + fixed_line = FixAbsolutePathInLine(line, relative_paths) + sys.stderr.write(fixed_line + '\n') + sys.exit(1) + + # Filter the output to remove all garbage and to fix the paths. If the + # output is not empty after filtering, then report the compilation as a + # failure (as some version of `actool` report error to stdout, yet exit + # with an return code of zero). + stdout = FilterCompilerOutput(stdout, relative_paths) + if stdout: + sys.stderr.write(stdout) + sys.exit(1) + + finally: + if temporary_file: + temporary_file.close() def Main(): - parser = argparse.ArgumentParser( - description='compile assets catalog for a bundle') - parser.add_argument('--target_os', - '-O', - required=True, - choices=('mac', 'ios', 'watchos'), - help='target os for the compiled assets catalog') - parser.add_argument('--target-platform', - '-p', - default='', - choices=('iphoneos', 'tvos'), - help='target platform for the compiled assets catalog') - parser.add_argument('--target-environment', - '-e', - default='', - choices=('simulator', 'device', 'catalyst'), - help='target environment for the compiled assets catalog') - parser.add_argument( - '--minimum-deployment-target', - '-t', - required=True, - help='minimum deployment target for the compiled assets catalog') - parser.add_argument('--output', - '-o', - required=True, - help='path to the compiled assets catalog') - parser.add_argument('--compress-pngs', - '-c', - action='store_true', - default=False, - help='recompress PNGs while compiling assets catalog') - parser.add_argument('--product-type', - '-T', - help='type of the containing bundle') - parser.add_argument('--partial-info-plist', - '-P', - help='path to partial info plist to create') - parser.add_argument('--app-icon', - '-A', - help='name of an app icon set for the target’s default app icon') - parser.add_argument('--include-all-app-icons', - '-I', - action='store_true', - default=False, - help='include all app icons in the compiled assets catalog') - parser.add_argument('inputs', - nargs='+', - help='path to input assets catalog sources') - args = parser.parse_args() + parser = argparse.ArgumentParser( + description='compile assets catalog for a bundle') + parser.add_argument('--target_os', + '-O', + required=True, + choices=('mac', 'ios', 'watchos'), + help='target os for the compiled assets catalog') + parser.add_argument('--target-platform', + '-p', + default='', + choices=('iphoneos', 'tvos'), + help='target platform for the compiled assets catalog') + parser.add_argument( + '--target-environment', + '-e', + default='', + choices=('simulator', 'device', 'catalyst'), + help='target environment for the compiled assets catalog') + parser.add_argument( + '--minimum-deployment-target', + '-t', + required=True, + help='minimum deployment target for the compiled assets catalog') + parser.add_argument('--output', + '-o', + required=True, + help='path to the compiled assets catalog') + parser.add_argument('--compress-pngs', + '-c', + action='store_true', + default=False, + help='recompress PNGs while compiling assets catalog') + parser.add_argument('--product-type', + '-T', + help='type of the containing bundle') + parser.add_argument('--partial-info-plist', + '-P', + help='path to partial info plist to create') + parser.add_argument( + '--app-icon', + '-A', + help='name of an app icon set for the target’s default app icon') + parser.add_argument( + '--include-all-app-icons', + '-I', + action='store_true', + default=False, + help='include all app icons in the compiled assets catalog') + parser.add_argument('inputs', + nargs='+', + help='path to input assets catalog sources') + args = parser.parse_args() - if os.path.basename(args.output) != 'Assets.car': - sys.stderr.write('output should be path to compiled asset catalog, not ' - 'to the containing bundle: %s\n' % (args.output, )) - sys.exit(1) + if os.path.basename(args.output) != 'Assets.car': + sys.stderr.write( + 'output should be path to compiled asset catalog, not ' + 'to the containing bundle: %s\n' % (args.output, )) + sys.exit(1) - if os.path.exists(args.output): - if os.path.isfile(args.output): - os.unlink(args.output) - else: - shutil.rmtree(args.output) + if os.path.exists(args.output): + if os.path.isfile(args.output): + os.unlink(args.output) + else: + shutil.rmtree(args.output) - with tempfile.TemporaryDirectory() as temporary_dir: - CompileAssetCatalog(args.output, args.target_os, args.target_environment, - args.product_type, args.minimum_deployment_target, - args.inputs, args.compress_pngs, args.target_platform, - args.partial_info_plist, args.app_icon, - args.include_all_app_icons, temporary_dir) + with tempfile.TemporaryDirectory() as temporary_dir: + CompileAssetCatalog(args.output, args.target_os, + args.target_environment, args.product_type, + args.minimum_deployment_target, args.inputs, + args.compress_pngs, args.target_platform, + args.partial_info_plist, args.app_icon, + args.include_all_app_icons, temporary_dir) if __name__ == '__main__': - sys.exit(Main()) + sys.exit(Main()) diff --git a/naiveproxy/src/build/toolchain/apple/swiftc.py b/naiveproxy/src/build/toolchain/apple/swiftc.py index b7e3802add..b030a73add 100644 --- a/naiveproxy/src/build/toolchain/apple/swiftc.py +++ b/naiveproxy/src/build/toolchain/apple/swiftc.py @@ -633,7 +633,7 @@ def main(args): help='add preprocessor define') parser.add_argument('-swift-version', - default='5', + default='6', help='version of the Swift language') parser.add_argument( diff --git a/naiveproxy/src/build/toolchain/apple/toolchain.gni b/naiveproxy/src/build/toolchain/apple/toolchain.gni index d5210da1aa..8eeccf0b9c 100644 --- a/naiveproxy/src/build/toolchain/apple/toolchain.gni +++ b/naiveproxy/src/build/toolchain/apple/toolchain.gni @@ -115,6 +115,9 @@ template("single_apple_toolchain") { host_toolchain = host_toolchain } + # bin_path is only used in some builds. + not_needed(invoker, [ "bin_path" ]) + # When the invoker has explicitly overridden cc_wrapper in the # toolchain args, use those values, otherwise default to the global one. # This works because the only reasonable override that toolchains might @@ -185,6 +188,7 @@ template("single_apple_toolchain") { ld += " -B " + invoker.bin_path } + coverage_wrapper = "" if (defined(toolchain_args.coverage_instrumentation_input_file)) { toolchain_coverage_instrumentation_input_file = toolchain_args.coverage_instrumentation_input_file @@ -200,8 +204,7 @@ template("single_apple_toolchain") { root_build_dir) + " --files-to-instrument=" + rebase_path(toolchain_coverage_instrumentation_input_file, root_build_dir) + " --target-os=" + target_os - cc = "\"$python_path\" $_coverage_wrapper ${cc}" - cxx = "\"$python_path\" $_coverage_wrapper ${cxx}" + coverage_wrapper = "\"$python_path\" ${_coverage_wrapper} " } linker_driver_env = "TOOL_VERSION=${tool_versions.linker_driver}" @@ -210,7 +213,7 @@ template("single_apple_toolchain") { linker_driver_args = "-Wcrl,driver,$ld" # Specify an explicit path for the strip binary. - _strippath = invoker.bin_path + "strip" + _strippath = "${prefix}llvm-strip" _installnametoolpath = "${prefix}llvm-install-name-tool" linker_driver_args += " -Wcrl,strippath,${_strippath} -Wcrl,installnametoolpath,${_installnametoolpath}" _enable_dsyms = enable_dsyms @@ -255,7 +258,7 @@ template("single_apple_toolchain") { rustc_bin = "$rust_sysroot_relative/bin/rustc" rustc = "$rust_compiler_prefix${rustc_bin}" rustc_wrapper = - rebase_path("//build/rust/rustc_wrapper.py", root_build_dir) + rebase_path("//build/rust/gni_impl/rustc_wrapper.py", root_build_dir) tool("rust_staticlib") { libname = "{{output_dir}}/{{target_output_name}}{{output_extension}}" @@ -395,7 +398,7 @@ template("single_apple_toolchain") { tool("cc") { depfile = "{{output}}.d" precompiled_header_type = "gcc" - command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}" + command = "$coverage_wrapper$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}" depsformat = "gcc" description = "CC {{output}}" outputs = [ "$object_subdir/{{source_name_part}}.o" ] @@ -404,7 +407,7 @@ template("single_apple_toolchain") { tool("cxx") { depfile = "{{output}}.d" precompiled_header_type = "gcc" - command = "$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} {{module_deps_no_self}} -c {{source}} -o {{output}}" + command = "$coverage_wrapper$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} {{module_deps_no_self}} -c {{source}} -o {{output}}" depsformat = "gcc" description = "CXX {{output}}" outputs = [ "$object_subdir/{{source_name_part}}.o" ] @@ -413,6 +416,9 @@ template("single_apple_toolchain") { tool("cxx_module") { depfile = "{{output}}.d" precompiled_header_type = "gcc" + + # Module file doesn't need coverage instrumentation because module files + # represent interfaces rather than implementations. command = "$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} {{module_deps_no_self}} -fmodule-name={{label_name}} -c -x c++ -Xclang -emit-module {{source}} -o {{output}}" depsformat = "gcc" description = "CXX_MODULE {{output}}" @@ -431,7 +437,7 @@ template("single_apple_toolchain") { tool("objc") { depfile = "{{output}}.d" precompiled_header_type = "gcc" - command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{framework_dirs}} {{cflags}} {{cflags_objc}} -c {{source}} -o {{output}}" + command = "$coverage_wrapper$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{framework_dirs}} {{cflags}} {{cflags_objc}} -c {{source}} -o {{output}}" depsformat = "gcc" description = "OBJC {{output}}" outputs = [ "$object_subdir/{{source_name_part}}.o" ] @@ -440,7 +446,7 @@ template("single_apple_toolchain") { tool("objcxx") { depfile = "{{output}}.d" precompiled_header_type = "gcc" - command = "$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{framework_dirs}} {{cflags}} {{cflags_objcc}} -c {{source}} -o {{output}}" + command = "$coverage_wrapper$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{framework_dirs}} {{cflags}} {{cflags_objcc}} -c {{source}} -o {{output}}" depsformat = "gcc" description = "OBJCXX {{output}}" outputs = [ "$object_subdir/{{source_name_part}}.o" ] @@ -493,13 +499,8 @@ template("single_apple_toolchain") { # search path in /usr/bin are thin wrappers around xcrun, which requires a # full CommandLineTools or Xcode install, and still may not choose the # appropriate binary if there are multiple installs. - if (host_os == "mac") { - nm = invoker.bin_path + "nm" - otool = invoker.bin_path + "otool" - } else { - nm = "${prefix}llvm-nm" - otool = "${prefix}llvm-otool" - } + nm = "${prefix}llvm-nm" + otool = "${prefix}llvm-otool" link_command = "$linker_driver_env $linker_driver" link_command += " -Wcrl,otoolpath,$otool -Wcrl,nmpath,$nm" @@ -660,19 +661,14 @@ template("single_apple_toolchain") { # The list of outputs and partial_outputs change whether the whole # module optimization is enabled or not. if (swift_whole_module_optimization) { - outputs += [ - "$_output_dir/{{module_name}}.swiftconstvalues" - ] + outputs += [ "$_output_dir/{{module_name}}.swiftconstvalues" ] # This seems broken in Xcode 26 beta 1. The OutputFileMap.json # confirms the file should be there, but when # whole-module-optimization is enabled it's not there. if (xcode_version_int < 2600) { - outputs += [ - "$_output_dir/{{module_name}}.swiftdeps" - ] + outputs += [ "$_output_dir/{{module_name}}.swiftdeps" ] } - } else { outputs += [ "$_output_dir/{{module_name}}.priors" ] partial_outputs += [ diff --git a/naiveproxy/src/build/toolchain/cros/BUILD.gn b/naiveproxy/src/build/toolchain/cros/BUILD.gn index 360c76e187..0fb7834dab 100644 --- a/naiveproxy/src/build/toolchain/cros/BUILD.gn +++ b/naiveproxy/src/build/toolchain/cros/BUILD.gn @@ -93,88 +93,6 @@ cros_toolchain("target") { } } -# This is a special toolchain needed just for the nacl_bootstrap target in -# //native_client/src/trusted/service_runtime/linux. It is identical -# to ":target" except that it forces `use_debug_fission1 and `use_sysroot` off, -# and allows the user to set different sets of extra flags. -cros_toolchain("nacl_bootstrap") { - toolchain_args = { - if (target_cpu == "arm64") { - current_cpu = "arm" - } else { - current_cpu = target_cpu - } - current_os = "chromeos" - use_debug_fission = false - use_sysroot = false - } - - if (!lacros_use_chromium_toolchain) { - ar = cros_target_ar - cc = cros_target_cc - cxx = cros_target_cxx - ld = cros_target_ld - - if (cros_target_nm != "") { - nm = cros_target_nm - } - if (cros_target_readelf != "") { - readelf = cros_target_readelf - } - extra_cflags = cros_nacl_bootstrap_extra_cflags - extra_cppflags = cros_nacl_bootstrap_extra_cppflags - extra_cxxflags = cros_nacl_bootstrap_extra_cxxflags - extra_ldflags = cros_nacl_bootstrap_extra_ldflags - - needs_rewrapper_path_arg = cros_needs_rewrapper_path_arg - } - - # We build for ARM32, even when the rest of the build targets ARM64. - if (target_cpu == "arm64") { - ar = cros_nacl_helper_arm32_ar - cc = cros_nacl_helper_arm32_cc - cxx = cros_nacl_helper_arm32_cxx - ld = cros_nacl_helper_arm32_ld - - # Avoid accidental use of Arm64 sysroot because of SYSROOT - # env variable set in ChromeOS builds. - toolchain_args.sysroot = cros_nacl_helper_arm32_sysroot - } -} - -# This is a special toolchain needed just for the nacl_helper target for -# building an Arm32 nacl_helper binary on Arm64 ChromeOS targets. -cros_toolchain("nacl_helper_arm32") { - toolchain_args = { - current_cpu = "arm" - current_os = "chromeos" - use_debug_fission = false - sysroot = cros_nacl_helper_arm32_sysroot - - # Disable some uses of libraries that this build does not require. The - # sysroot for this build does not provide them, and they would be pulled in - # by indirect dependencies of nacl_helper otherwise. - use_cras = false - use_nss_certs = false - use_system_libdrm = false - use_system_libsync = false - } - ar = cros_nacl_helper_arm32_ar - cc = cros_nacl_helper_arm32_cc - cxx = cros_nacl_helper_arm32_cxx - ld = cros_nacl_helper_arm32_ld - readelf = cros_nacl_helper_arm32_readelf - - extra_cflags = "" - extra_cppflags = "" - extra_cxxflags = "" - extra_ldflags = "" - - if (!lacros_use_chromium_toolchain) { - needs_rewrapper_path_arg = cros_needs_rewrapper_path_arg - } -} - cros_toolchain("host") { toolchain_args = { current_cpu = host_cpu diff --git a/naiveproxy/src/build/toolchain/cros_toolchain.gni b/naiveproxy/src/build/toolchain/cros_toolchain.gni index c1fb4e2d68..f5a962de90 100644 --- a/naiveproxy/src/build/toolchain/cros_toolchain.gni +++ b/naiveproxy/src/build/toolchain/cros_toolchain.gni @@ -70,22 +70,10 @@ declare_args() { cros_v8_snapshot_extra_cxxflags = "" cros_v8_snapshot_extra_ldflags = "" cros_v8_snapshot_sysroot = "" - - cros_nacl_bootstrap_extra_cflags = "" - cros_nacl_bootstrap_extra_cppflags = "" - cros_nacl_bootstrap_extra_cxxflags = "" - cros_nacl_bootstrap_extra_ldflags = "" - - cros_nacl_helper_arm32_ar = "${clang_base_path}/bin/llvm-ar" - cros_nacl_helper_arm32_cc = "${clang_base_path}/bin/clang" - cros_nacl_helper_arm32_cxx = "${clang_base_path}/bin/clang++" - cros_nacl_helper_arm32_readelf = "" - cros_nacl_helper_arm32_sysroot = "" } declare_args() { cros_target_ld = cros_target_cxx cros_host_ld = cros_host_cxx cros_v8_snapshot_ld = cros_v8_snapshot_cxx - cros_nacl_helper_arm32_ld = cros_nacl_helper_arm32_cxx } diff --git a/naiveproxy/src/build/toolchain/gcc_toolchain.gni b/naiveproxy/src/build/toolchain/gcc_toolchain.gni index 15334c79c3..7d670b1315 100644 --- a/naiveproxy/src/build/toolchain/gcc_toolchain.gni +++ b/naiveproxy/src/build/toolchain/gcc_toolchain.gni @@ -13,13 +13,6 @@ import("//build/toolchain/cc_wrapper.gni") import("//build/toolchain/rbe.gni") import("//build/toolchain/toolchain.gni") -if (is_nacl) { - # To keep NaCl variables out of builds that don't include NaCl, all - # variables defined in nacl/config.gni referenced here should be protected by - # is_nacl conditions. - import("//build/config/nacl/config.gni") -} - declare_args() { # Enables allowlist generation for IDR_ grit defines seen by the compiler. # Currently works only on some platforms and enabled by default for official @@ -216,6 +209,8 @@ template("single_gcc_toolchain") { toolchain_use_clang_coverage = use_clang_coverage } + coverage_wrapper = "" + # For a coverage build, we use the wrapper script globally so that it can # remove coverage cflags from files that should not have them. if (toolchain_use_clang_coverage) { @@ -247,8 +242,7 @@ template("single_gcc_toolchain") { rebase_path(toolchain_coverage_instrumentation_input_file, root_build_dir) } - compiler_prefix = - "\"$python_path\" ${_coverage_wrapper} " + compiler_prefix + coverage_wrapper = "\"$python_path\" ${_coverage_wrapper} " } cc = compiler_prefix + invoker.cc @@ -344,7 +338,7 @@ template("single_gcc_toolchain") { tool("cc") { depfile = "{{output}}.d" precompiled_header_type = "gcc" - command = "$cc $md -MF $depfile ${rebuild_string}{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}}${extra_cppflags}${extra_cflags} -c {{source}} -o {{output}}" + command = "$coverage_wrapper$cc $md -MF $depfile ${rebuild_string}{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}}${extra_cppflags}${extra_cflags} -c {{source}} -o {{output}}" depsformat = "gcc" description = "CC {{output}}" outputs = [ "$object_subdir/{{source_name_part}}.o" ] @@ -353,7 +347,7 @@ template("single_gcc_toolchain") { tool("cxx") { depfile = "{{output}}.d" precompiled_header_type = "gcc" - command = "$cxx $md -MF $depfile ${rebuild_string}{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}${extra_cppflags}${extra_cxxflags} {{module_deps_no_self}} -c {{source}} -o {{output}}" + command = "$coverage_wrapper$cxx $md -MF $depfile ${rebuild_string}{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}${extra_cppflags}${extra_cxxflags} {{module_deps_no_self}} -c {{source}} -o {{output}}" depsformat = "gcc" description = "CXX {{output}}" outputs = [ "$object_subdir/{{source_name_part}}.o" ] @@ -361,6 +355,9 @@ template("single_gcc_toolchain") { tool("cxx_module") { depfile = "{{output}}.d" + + # Module file doesn't need coverage instrumentation because module files + # represent interfaces rather than implementations. command = "$cxx $md -MF $depfile ${rebuild_string}{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}${extra_cppflags}${extra_cxxflags} {{module_deps_no_self}} -fmodule-name={{label_name}} -c -x c++ -Xclang -emit-module {{source}} -o {{output}}" depsformat = "gcc" description = "CXX_MODULE {{output}}" @@ -683,7 +680,7 @@ template("single_gcc_toolchain") { rustc_bin = "$rust_sysroot_relative/bin/rustc" rustc = "$rust_compiler_prefix${rustc_bin}" rustc_wrapper = - rebase_path("//build/rust/rustc_wrapper.py", root_build_dir) + rebase_path("//build/rust/gni_impl/rustc_wrapper.py", root_build_dir) # RSP manipulation due to https://bugs.chromium.org/p/gn/issues/detail?id=249 tool("rust_staticlib") { diff --git a/naiveproxy/src/build/toolchain/ios/BUILD.gn b/naiveproxy/src/build/toolchain/ios/BUILD.gn index a5b2e3ea01..a1329faf2f 100644 --- a/naiveproxy/src/build/toolchain/ios/BUILD.gn +++ b/naiveproxy/src/build/toolchain/ios/BUILD.gn @@ -154,26 +154,12 @@ ios_blink_app_ext_toolchain("ios_clang_x64_blink_app_ext") { } } -ios_app_ext_toolchain("ios_clang_arm64_app_ext_13_4") { - toolchain_args = { - current_cpu = "arm64" - ios_deployment_target = "13.4" - } -} - ios_app_ext_toolchain("ios_clang_x64_app_ext") { toolchain_args = { current_cpu = "x64" } } -ios_app_ext_toolchain("ios_clang_x64_app_ext_13_4") { - toolchain_args = { - current_cpu = "x64" - ios_deployment_target = "13.4" - } -} - ios_toolchain("ios_clang_arm64_blink") { toolchain_args = { current_cpu = "arm64" diff --git a/naiveproxy/src/build/toolchain/nacl/BUILD.gn b/naiveproxy/src/build/toolchain/nacl/BUILD.gn deleted file mode 100644 index 910217c424..0000000000 --- a/naiveproxy/src/build/toolchain/nacl/BUILD.gn +++ /dev/null @@ -1,342 +0,0 @@ -# Copyright (c) 2014 The Native Client Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/nacl/config.gni") -import("//build/config/sysroot.gni") -import("//build/toolchain/nacl_toolchain.gni") - -# Add the toolchain revision as a preprocessor define so that sources are -# rebuilt when a toolchain is updated. -# Idea we could use the toolchain deps feature, but currently that feature is -# bugged and does not trigger a rebuild. -# https://code.google.com/p/chromium/issues/detail?id=431880 -# Calls to get the toolchain revision are relatively slow, so do them all in a -# single batch to amortize python startup, etc. -revisions = exec_script("//native_client/build/get_toolchain_revision.py", - [ - "nacl_x86_glibc", - "nacl_arm_glibc", - "pnacl_newlib", - "saigo_newlib", - ], - "trim list lines") -nacl_x86_glibc_rev = revisions[0] -nacl_arm_glibc_rev = revisions[1] - -pnacl_newlib_rev = revisions[2] -saigo_newlib_rev = revisions[3] - -if (host_os == "win") { - toolsuffix = ".exe" -} else { - toolsuffix = "" -} - -# The PNaCl toolchain tools are all wrapper scripts rather than binary -# executables. On POSIX systems, nobody cares what kind of executable -# file you are. But on Windows, scripts (.bat files) cannot be run -# directly and need the Windows shell (cmd.exe) specified explicily. -if (host_os == "win") { - # NOTE! The //build/toolchain/gcc_*_wrapper.py scripts recognize - # this exact prefix string, so they must be updated if this string - # is changed in any way. - scriptprefix = "cmd /c call " - scriptsuffix = ".bat" -} else { - scriptprefix = "" - scriptsuffix = "" -} - -# When the compilers are run via reclient or ccache rather than directly by -# GN/Ninja, the reclient/ccache wrapper handles .bat files but gets confused -# by being given the scriptprefix. -if (host_os == "win" && !use_reclient && cc_wrapper == "") { - compiler_scriptprefix = scriptprefix -} else { - compiler_scriptprefix = "" -} - -template("pnacl_toolchain") { - assert(defined(invoker.executable_extension), - "Must define executable_extension") - - nacl_toolchain(target_name) { - toolchain_package = "pnacl_newlib" - toolchain_revision = pnacl_newlib_rev - toolprefix = - rebase_path("${nacl_toolchain_dir}/${toolchain_package}/bin/pnacl-", - root_build_dir) - - if (host_os == "win") { - # Flip the slashes so that copy/paste of the commands works. - # This is also done throughout build\toolchain\win\BUILD.gn - toolprefix = string_replace(toolprefix, "/", "\\") - } - - cc = compiler_scriptprefix + toolprefix + "clang" + scriptsuffix - cxx = compiler_scriptprefix + toolprefix + "clang++" + scriptsuffix - ar = toolprefix + "ar" + scriptsuffix - readelf = scriptprefix + toolprefix + "readelf" + scriptsuffix - nm = scriptprefix + toolprefix + "nm" + scriptsuffix - if (defined(invoker.strip)) { - strip = scriptprefix + toolprefix + invoker.strip + scriptsuffix - } - forward_variables_from(invoker, - [ - "executable_extension", - "is_clang_analysis_supported", - "extra_cppflags", - ]) - - # Note this is not the usual "ld = cxx" because "ld" uses are - # never run via rbe, so this needs scriptprefix. - ld = scriptprefix + toolprefix + "clang++" + scriptsuffix - - toolchain_args = { - is_clang = true - current_cpu = "pnacl" - use_lld = false - } - } -} - -pnacl_toolchain("newlib_pnacl") { - executable_extension = ".pexe" - - # The pnacl-finalize tool turns a .pexe.debug file into a .pexe file. - # It's very similar in purpose to the traditional "strip" utility: it - # turns what comes out of the linker into what you actually want to - # distribute and run. PNaCl doesn't have a "strip"-like utility that - # you ever actually want to use other than pnacl-finalize, so just - # make pnacl-finalize the strip tool rather than adding an additional - # step like "postlink" to run pnacl-finalize. - strip = "finalize" -} - -template("nacl_glibc_toolchain") { - toolchain_cpu = target_name - assert(defined(invoker.toolchain_tuple), "Must define toolchain_tuple") - assert(defined(invoker.toolchain_package), "Must define toolchain_package") - assert(defined(invoker.toolchain_revision), "Must define toolchain_revision") - forward_variables_from(invoker, - [ - "toolchain_package", - "toolchain_revision", - ]) - - toolprefix = rebase_path("${nacl_toolchain_dir}/${toolchain_package}/bin/" + - invoker.toolchain_tuple + "-", - root_build_dir) - - if (host_os == "win") { - # Flip the slashes so that copy/paste of the commands works. - # This is also done throughout build\toolchain\win\BUILD.gn - toolprefix = string_replace(toolprefix, "/", "\\") - } - - nacl_toolchain("glibc_" + toolchain_cpu) { - cc = toolprefix + "gcc" + toolsuffix - cxx = toolprefix + "g++" + toolsuffix - ar = toolprefix + "ar" + toolsuffix - ld = cxx - readelf = toolprefix + "readelf" + toolsuffix - nm = toolprefix + "nm" + toolsuffix - strip = toolprefix + "strip" + toolsuffix - - toolchain_args = { - current_cpu = toolchain_cpu - - # reclient does not support gcc. - use_remoteexec = false - is_clang = false - is_nacl_glibc = true - use_lld = false - } - } -} - -nacl_glibc_toolchain("x86") { - toolchain_package = "nacl_x86_glibc" - toolchain_revision = nacl_x86_glibc_rev - - # Rely on the :compiler_cpu_abi config adding the -m32 flag here rather - # than using the i686-nacl binary directly. - toolchain_tuple = "x86_64-nacl" -} - -nacl_glibc_toolchain("x64") { - toolchain_package = "nacl_x86_glibc" - toolchain_revision = nacl_x86_glibc_rev - toolchain_tuple = "x86_64-nacl" -} - -nacl_glibc_toolchain("arm") { - toolchain_package = "nacl_arm_glibc" - toolchain_revision = nacl_arm_glibc_rev - toolchain_tuple = "arm-nacl" -} - -template("nacl_clang_toolchain") { - toolchain_cpu = target_name - assert(defined(invoker.toolchain_tuple), "Must define toolchain_tuple") - - toolchain_package = "pnacl_newlib" - toolchain_revision = pnacl_newlib_rev - toolprefix = rebase_path("${nacl_toolchain_dir}/${toolchain_package}/bin/" + - invoker.toolchain_tuple + "-", - root_build_dir) - - if (host_os == "win") { - # Flip the slashes so that copy/paste of the commands works. - # This is also done throughout build\toolchain\win\BUILD.gn - toolprefix = string_replace(toolprefix, "/", "\\") - } - - nacl_toolchain("clang_newlib_" + toolchain_cpu) { - cc = toolprefix + "clang" + toolsuffix - cxx = toolprefix + "clang++" + toolsuffix - ar = toolprefix + "ar" + toolsuffix - ld = cxx - readelf = toolprefix + "readelf" + toolsuffix - nm = toolprefix + "nm" + toolsuffix - strip = toolprefix + "strip" + toolsuffix - - toolchain_args = { - current_cpu = toolchain_cpu - is_clang = true - use_lld = false - } - } -} - -template("nacl_irt_toolchain") { - toolchain_cpu = target_name - assert(defined(invoker.toolchain_tuple), "Must define toolchain_tuple") - - toolchain_package = "saigo_newlib" - toolchain_revision = saigo_newlib_rev - toolprefix = rebase_path("${nacl_toolchain_dir}/${toolchain_package}/bin/" + - invoker.toolchain_tuple + "-", - root_build_dir) - - if (host_os == "win") { - # Flip the slashes so that copy/paste of the commands works. - # This is also done throughout build\toolchain\win\BUILD.gn - toolprefix = string_replace(toolprefix, "/", "\\") - } - - link_irt = rebase_path("//native_client/build/link_irt.py", root_build_dir) - - tls_edit_label = - "//native_client/src/tools/tls_edit:tls_edit($host_toolchain)" - host_toolchain_out_dir = - rebase_path(get_label_info(tls_edit_label, "root_out_dir"), - root_build_dir) - tls_edit = "${host_toolchain_out_dir}/tls_edit" - - nacl_toolchain("irt_" + toolchain_cpu) { - cc = toolprefix + "clang" + toolsuffix - cxx = toolprefix + "clang++" + toolsuffix - ar = toolprefix + "ar" + toolsuffix - readelf = toolprefix + "readelf" + toolsuffix - nm = toolprefix + "nm" + toolsuffix - strip = toolprefix + "strip" + toolsuffix - - # Some IRT implementations (notably, Chromium's) contain C++ code, - # so we need to link w/ the C++ linker. - ld = "${python_path} ${link_irt} --tls-edit=${tls_edit} --link-cmd=${cxx} --readelf-cmd=${readelf}" - - # reclient requires explicit upload of toolchain lib - if (is_chromeos && use_remoteexec) { - if (defined(invoker.extra_cppflags) && invoker.extra_cppflags != "") { - extra_cppflags = " " + invoker.extra_cppflags - } else { - extra_cppflags = "" - } - - libdir = rebase_path("${nacl_toolchain_dir}/${toolchain_package}/lib", - root_build_dir) - extra_cppflags += " -B${libdir}" - } - - toolchain_args = { - current_cpu = toolchain_cpu - is_clang = true - use_lld = false - is_nacl_saigo = true - host_toolchain_is_msan = is_msan - host_toolchain_msan_track_origins = msan_track_origins - } - - # TODO(ncbray): depend on link script - deps = [ tls_edit_label ] - } -} - -# This is essentially a clone of nacl_irt_toolchain above, except it uses the -# standard ld. This toolchain can be used to build regular nexes for NaCl -# browser tests. -template("nacl_test_irt_toolchain") { - toolchain_cpu = target_name - assert(defined(invoker.toolchain_tuple), "Must define toolchain_tuple") - - toolchain_package = "saigo_newlib" - toolchain_revision = saigo_newlib_rev - toolprefix = rebase_path("${nacl_toolchain_dir}/${toolchain_package}/bin/" + - invoker.toolchain_tuple + "-", - root_build_dir) - - if (host_os == "win") { - # Flip the slashes so that copy/paste of the commands works. - # This is also done throughout build\toolchain\win\BUILD.gn - toolprefix = string_replace(toolprefix, "/", "\\") - } - - nacl_toolchain("test_irt_" + toolchain_cpu) { - cc = toolprefix + "clang" + toolsuffix - cxx = toolprefix + "clang++" + toolsuffix - ar = toolprefix + "ar" + toolsuffix - ld = cxx - readelf = toolprefix + "readelf" + toolsuffix - nm = toolprefix + "nm" + toolsuffix - strip = toolprefix + "strip" + toolsuffix - - toolchain_args = { - current_cpu = toolchain_cpu - is_clang = true - use_lld = false - is_nacl_saigo = true - } - } -} - -template("nacl_clang_toolchains") { - assert(defined(invoker.toolchain_tuple), "Must define toolchain_tuple") - nacl_clang_toolchain(target_name) { - toolchain_tuple = invoker.toolchain_tuple - } - nacl_irt_toolchain(target_name) { - toolchain_tuple = invoker.toolchain_tuple - } - nacl_test_irt_toolchain(target_name) { - toolchain_tuple = invoker.toolchain_tuple - } -} - -nacl_clang_toolchains("x86") { - # Rely on :compiler_cpu_abi adding -m32. See nacl_x86_glibc above. - toolchain_tuple = "x86_64-nacl" -} - -nacl_clang_toolchains("x64") { - toolchain_tuple = "x86_64-nacl" -} - -nacl_clang_toolchains("arm") { - toolchain_tuple = "arm-nacl" -} - -nacl_clang_toolchains("mipsel") { - toolchain_tuple = "mipsel-nacl" -} diff --git a/naiveproxy/src/build/toolchain/nacl_toolchain.gni b/naiveproxy/src/build/toolchain/nacl_toolchain.gni deleted file mode 100644 index 915716a37f..0000000000 --- a/naiveproxy/src/build/toolchain/nacl_toolchain.gni +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright (c) 2014 The Native Client Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/nacl/config.gni") -import("//build/toolchain/gcc_toolchain.gni") - -# This template defines a NaCl toolchain. -# -# It requires the following variables specifying the executables to run: -# - cc -# - cxx -# - ar -# - ld - -template("nacl_toolchain") { - assert(defined(invoker.cc), "nacl_toolchain() must specify a \"cc\" value") - assert(defined(invoker.cxx), "nacl_toolchain() must specify a \"cxx\" value") - assert(defined(invoker.ar), "nacl_toolchain() must specify a \"ar\" value") - assert(defined(invoker.ld), "nacl_toolchain() must specify a \"ld\" value") - gcc_toolchain(target_name) { - if (defined(invoker.executable_extension)) { - executable_extension = invoker.executable_extension - } else { - executable_extension = ".nexe" - } - rebuild_define = "NACL_TC_REV=" + invoker.toolchain_revision - - forward_variables_from(invoker, - [ - "ar", - "cc", - "cxx", - "deps", - "ld", - "link_outputs", - "nm", - "readelf", - "strip", - "extra_cppflags", - ]) - - toolchain_args = { - # Use all values set on the invoker's toolchain_args. - forward_variables_from(invoker.toolchain_args, "*") - - current_os = "nacl" - - # We do not support component builds with the NaCl toolchains. - is_component_build = false - - # We do not support clang profiling in the NaCl toolchains. - use_clang_profiling = false - use_clang_coverage = false - coverage_instrumentation_input_file = "" - - # NaCl doesn't work with Clang modules. - use_libcxx_modules = false - - if (use_reclient) { - if (is_win) { - reclient_cc_cfg_file = rebase_path(reclient_cfg_dir, root_build_dir) + - "/nacl/rewrapper_windows.cfg" - } else if (is_mac) { - reclient_cc_cfg_file = rebase_path(reclient_cfg_dir, root_build_dir) + - "/nacl/rewrapper_mac.cfg" - } else { - # TODO(ukai): non linux? - reclient_cc_cfg_file = rebase_path(reclient_cfg_dir, root_build_dir) + - "/nacl/rewrapper_linux.cfg" - } - } - } - } -} diff --git a/naiveproxy/src/build/toolchain/toolchain.gni b/naiveproxy/src/build/toolchain/toolchain.gni index 44dbc84d0e..ed381d00db 100644 --- a/naiveproxy/src/build/toolchain/toolchain.gni +++ b/naiveproxy/src/build/toolchain/toolchain.gni @@ -35,7 +35,10 @@ declare_args() { declare_args() { if (llvm_android_mainline) { # https://crbug.com/1481060 clang_version = "17" + } else if (llvm_force_head_revision) { + clang_version = "22" } else { + # TODO(crbug.com/432036065): Remove in the next Clang roll. clang_version = "21" } } diff --git a/naiveproxy/src/build/toolchain/win/BUILD.gn b/naiveproxy/src/build/toolchain/win/BUILD.gn index d7f3484875..87d1e4aa19 100644 --- a/naiveproxy/src/build/toolchain/win/BUILD.gn +++ b/naiveproxy/src/build/toolchain/win/BUILD.gn @@ -48,18 +48,6 @@ if (target_cpu == "arm64") { } } -# The nacl_win64 toolchain is nearly identical to the plain x64 toolchain. -# It's used solely for building nacl64.exe (//components/nacl/broker:nacl64). -# The only reason it's a separate toolchain is so that it can force -# is_component_build to false in the toolchain_args() block, because -# building nacl64.exe in component style does not work. -win_toolchains("nacl_win64") { - toolchain_arch = "x64" - toolchain_args = { - is_component_build = false - } -} - # WinUWP toolchains. Only define these when targeting them. if (target_os == "winuwp") { diff --git a/naiveproxy/src/build/toolchain/win/toolchain.gni b/naiveproxy/src/build/toolchain/win/toolchain.gni index 7dbd8a17ed..c54119276f 100644 --- a/naiveproxy/src/build/toolchain/win/toolchain.gni +++ b/naiveproxy/src/build/toolchain/win/toolchain.gni @@ -230,6 +230,14 @@ template("msvc_toolchain") { command = "$coverage_wrapper$env_wrapper$cl /c {{source}} /nologo $show_includes $sys_include_flags{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} /Fo{{output}} /Fd\"$pdbname\"" } + tool("cxx_module") { + pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb" + depsformat = "msvc" + description = "CXX_MODULE {{output}}" + outputs = [ "$object_subdir/{{source_name_part}}.pcm" ] + command = "$env_wrapper$cl /Fo{{output}} /nologo $show_includes $sys_include_flags{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} {{module_deps_no_self}} /Fd\"$pdbname\" -fmodule-name={{label_name}} /c -x c++ -Xclang -emit-module {{source}}" + } + tool("cxx") { precompiled_header_type = "msvc" @@ -243,7 +251,7 @@ template("msvc_toolchain") { # Note that the code coverage wrapper scripts assumes that {{source}} # comes immediately after /c. - command = "$coverage_wrapper$env_wrapper$cl /c {{source}} /Fo{{output}} /nologo $show_includes $sys_include_flags{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} /Fd\"$pdbname\"" + command = "$coverage_wrapper$env_wrapper$cl /c {{source}} /Fo{{output}} /nologo $show_includes $sys_include_flags{{defines}} {{include_dirs}} {{cflags}} /TP {{cflags_cc}} {{module_deps_no_self}} /Fd\"$pdbname\"" } tool("rc") { @@ -330,7 +338,7 @@ template("msvc_toolchain") { rust_sysroot_relative = rebase_path(rust_sysroot, root_build_dir) rustc = "$rust_sysroot_relative/bin/rustc" rustc_wrapper = - rebase_path("//build/rust/rustc_wrapper.py", root_build_dir) + rebase_path("//build/rust/gni_impl/rustc_wrapper.py", root_build_dir) rustc_windows_args = " -Clinker=$link$rust_linkflags $rustc_common_args" tool("rust_staticlib") { diff --git a/naiveproxy/src/build/util/LASTCHANGE b/naiveproxy/src/build/util/LASTCHANGE index 64533584db..803b2103a0 100644 --- a/naiveproxy/src/build/util/LASTCHANGE +++ b/naiveproxy/src/build/util/LASTCHANGE @@ -1,2 +1,2 @@ -LASTCHANGE=9ecdc2077ce88e6c6cfed8e7a61df7ada8282bee-refs/branch-heads/7258@{#2215} +LASTCHANGE=202bdc7b1c78777deb8fb5046c1d686b9cc3a01f-refs/branch-heads/7339@{#1839} LASTCHANGE_YEAR=2025 diff --git a/naiveproxy/src/build/util/LASTCHANGE.committime b/naiveproxy/src/build/util/LASTCHANGE.committime index 6b0e9f70d4..d5336b8618 100644 --- a/naiveproxy/src/build/util/LASTCHANGE.committime +++ b/naiveproxy/src/build/util/LASTCHANGE.committime @@ -1 +1 @@ -1753818699 \ No newline at end of file +1757361266 \ 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 fcd97d2ff8..6b3888857f 100755 --- a/naiveproxy/src/build/util/android_chrome_version.py +++ b/naiveproxy/src/build/util/android_chrome_version.py @@ -60,6 +60,8 @@ _PACKAGE_NAMES = { 'WEBVIEW_STABLE': 0, 'WEBVIEW_BETA': 10, 'WEBVIEW_DEV': 20, + 'WEBVIEW_AUTO': 70, + 'WEBVIEW_DESKTOP': 80 } """ "Next" builds get +500 on their patch number. @@ -103,6 +105,8 @@ _APKS = { ('WEBVIEW_STABLE', 'WEBVIEW_STABLE', '64'), ('WEBVIEW_BETA', 'WEBVIEW_BETA', '64'), ('WEBVIEW_DEV', 'WEBVIEW_DEV', '64'), + ('WEBVIEW_AUTO', 'WEBVIEW_AUTO', '64'), + ('WEBVIEW_DESKTOP', 'WEBVIEW_DESKTOP', '64'), ], 'hybrid': [ ('CHROME', 'CHROME', '64'), @@ -133,14 +137,24 @@ _APKS = { ('TRICHROME_DESKTOP_64', 'TRICHROME_DESKTOP', '64'), ('TRICHROME_64_BETA', 'TRICHROME_BETA', '64'), ('WEBVIEW_STABLE', 'WEBVIEW_STABLE', '32_64'), - ('WEBVIEW_BETA', 'WEBVIEW_BETA', '32_64'), - ('WEBVIEW_DEV', 'WEBVIEW_DEV', '32_64'), ('WEBVIEW_32_STABLE', 'WEBVIEW_STABLE', '32'), - ('WEBVIEW_32_BETA', 'WEBVIEW_BETA', '32'), - ('WEBVIEW_32_DEV', 'WEBVIEW_DEV', '32'), + ('WEBVIEW_32_64_STABLE', 'WEBVIEW_STABLE', '32_64'), ('WEBVIEW_64_STABLE', 'WEBVIEW_STABLE', '64'), + ('WEBVIEW_64_32_STABLE', 'WEBVIEW_STABLE', '64_32'), + ('WEBVIEW_64_32_HIGH_STABLE', 'WEBVIEW_STABLE', '64_32_high'), + ('WEBVIEW_BETA', 'WEBVIEW_BETA', '32_64'), + ('WEBVIEW_32_BETA', 'WEBVIEW_BETA', '32'), ('WEBVIEW_64_BETA', 'WEBVIEW_BETA', '64'), + ('WEBVIEW_64_32_BETA', 'WEBVIEW_BETA', '64_32'), + ('WEBVIEW_64_32_HIGH_BETA', 'WEBVIEW_BETA', '64_32_high'), + ('WEBVIEW_DEV', 'WEBVIEW_DEV', '32_64'), + ('WEBVIEW_32_DEV', 'WEBVIEW_DEV', '32'), ('WEBVIEW_64_DEV', 'WEBVIEW_DEV', '64'), + ('WEBVIEW_64_32_DEV', 'WEBVIEW_DEV', '64_32'), + ('WEBVIEW_AUTO_64', 'WEBVIEW_AUTO', '64'), + ('WEBVIEW_AUTO_64_32', 'WEBVIEW_AUTO', '64_32'), + ('WEBVIEW_AUTO_64_32_HIGH', 'WEBVIEW_AUTO', '64_32_high'), + ('WEBVIEW_DESKTOP_64', 'WEBVIEW_DESKTOP', '64'), ] } diff --git a/naiveproxy/src/build/util/android_chrome_version_test.py b/naiveproxy/src/build/util/android_chrome_version_test.py index 76cea29363..5d7344d558 100644 --- a/naiveproxy/src/build/util/android_chrome_version_test.py +++ b/naiveproxy/src/build/util/android_chrome_version_test.py @@ -68,14 +68,23 @@ class _VersionTest(unittest.TestCase): self.assertEqual(webview_beta_version_code, '484400010') - def testGenerateVersionCodesAndroidWebviewDev(self): + def testGenerateVersionCodesAndroidWebviewAuto(self): """Assert it gives correct values for standard/example inputs""" output = GenerateVersionCodes(4844, 0, - arch='arm') + arch='arm64') - webview_dev_version_code = output['WEBVIEW_DEV_VERSION_CODE'] + webview_auto_version_code = output['WEBVIEW_AUTO_64_32_VERSION_CODE'] - self.assertEqual(webview_dev_version_code, '484400020') + self.assertEqual(webview_auto_version_code, '484400074') + + def testGenerateVersionCodesAndroidWebviewDesktop(self): + """Assert it gives correct values for standard/example inputs""" + output = GenerateVersionCodes(4844, 0, + arch='arm64') + + webview_desktop_version_code = output['WEBVIEW_DESKTOP_64_VERSION_CODE'] + + self.assertEqual(webview_desktop_version_code, '484400085') def testGenerateVersionCodesAndroidArchArm(self): """Assert it handles different architectures correctly. @@ -284,6 +293,24 @@ class _VersionTest(unittest.TestCase): self.assertGreater(webview_beta_version_code, webview_stable_version_code) + def testGenerateVersionCodesAndroidWebviewChannelOrderBeta64bit(self): + """Assert 64-bit webview beta channel is higher than stable. + + The channel-specific version codes for standalone webview needs to follow + the order stable < beta < dev. + + This allows that if a user opts into beta track, they will always have the + beta apk, including any finch experiments targeted at beta users, even when + beta and stable channels are otherwise on the same version. + """ + output = GenerateVersionCodes(4844, 0, + arch='arm64') + + webview_stable_version_code = output['WEBVIEW_64_STABLE_VERSION_CODE'] + webview_beta_version_code = output['WEBVIEW_64_BETA_VERSION_CODE'] + + self.assertGreater(webview_beta_version_code, webview_stable_version_code) + def testGenerateVersionCodesAndroidWebviewChannelOrderDev(self): """Assert webview dev channel is higher than beta. @@ -1066,6 +1093,55 @@ class _VersionCodeGroupedTest(unittest.TestCase): self.assertEqual(abi, 'arm') self.assertEqual(is_next_build, False) + def testWebview_64_32_Translate(self): + """Test for a build with Webview.""" + build, patch, package, abi, is_next_build = TranslateVersionCode( + '575000002', is_webview=True) + self.assertEqual(build, 5750) + self.assertEqual(patch, 0) + self.assertEqual(package, 'WEBVIEW_STABLE') + self.assertEqual(abi, 'arm_64_32') + self.assertEqual(is_next_build, False) + + def testWebviewAutoTranslate(self): + """Test for a build with Webview.""" + build, patch, package, abi, is_next_build = TranslateVersionCode( + '575000070', is_webview=True) + self.assertEqual(build, 5750) + self.assertEqual(patch, 0) + self.assertEqual(package, 'WEBVIEW_AUTO') + self.assertEqual(abi, 'arm') + self.assertEqual(is_next_build, False) + + def testWebviewAuto_64_32_Translate(self): + """Test for a build with Webview.""" + build, patch, package, abi, is_next_build = TranslateVersionCode( + '575000072', is_webview=True) + self.assertEqual(build, 5750) + self.assertEqual(patch, 0) + self.assertEqual(package, 'WEBVIEW_AUTO') + self.assertEqual(abi, 'arm_64_32') + self.assertEqual(is_next_build, False) + + def testWebviewDesktopTranslate(self): + """Test for a build with Webview.""" + build, patch, package, abi, is_next_build = TranslateVersionCode( + '575000080', is_webview=True) + self.assertEqual(build, 5750) + self.assertEqual(patch, 0) + self.assertEqual(package, 'WEBVIEW_DESKTOP') + self.assertEqual(abi, 'arm') + self.assertEqual(is_next_build, False) + + def testWebviewDesktop_64_High_Translate(self): + """Test for a build with Webview.""" + build, patch, package, abi, is_next_build = TranslateVersionCode( + '575000084', is_webview=True) + self.assertEqual(build, 5750) + self.assertEqual(patch, 0) + self.assertEqual(package, 'WEBVIEW_DESKTOP') + self.assertEqual(abi, 'arm_64_high') + self.assertEqual(is_next_build, False) if __name__ == '__main__': unittest.main() diff --git a/naiveproxy/src/build/util/lib/common/chrome_test_server_spawner.py b/naiveproxy/src/build/util/lib/common/chrome_test_server_spawner.py deleted file mode 100644 index e1700cf2db..0000000000 --- a/naiveproxy/src/build/util/lib/common/chrome_test_server_spawner.py +++ /dev/null @@ -1,486 +0,0 @@ -# Copyright 2017 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""A "Test Server Spawner" that handles killing/stopping per-test test servers. - -It's used to accept requests from the device to spawn and kill instances of the -chrome test server on the host. -""" -# pylint: disable=W0702 - -import json -import logging -import os -import select -import struct -import subprocess -import sys -import threading -import time -import urllib - -from http.server import BaseHTTPRequestHandler -from http.server import HTTPServer - -SERVER_TYPES = { - 'http': '', - 'ftp': '-f', - 'ws': '--websocket', -} - - -_DIR_SOURCE_ROOT = os.path.abspath( - os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, os.pardir, - os.pardir)) - - -_logger = logging.getLogger(__name__) - - -# Path that are needed to import necessary modules when launching a testserver. -os.environ['PYTHONPATH'] = os.environ.get('PYTHONPATH', '') + ( - ':%s:%s' % (os.path.join(_DIR_SOURCE_ROOT, 'third_party'), - os.path.join(_DIR_SOURCE_ROOT, 'net', 'tools', 'testserver'))) - - -def _GetServerTypeCommandLine(server_type): - """Returns the command-line by the given server type. - - Args: - server_type: the server type to be used (e.g. 'http'). - - Returns: - A string containing the command-line argument. - """ - if server_type not in SERVER_TYPES: - raise NotImplementedError('Unknown server type: %s' % server_type) - return SERVER_TYPES[server_type] - - -class PortForwarder: - def Map(self, port_pairs): - pass - - def GetDevicePortForHostPort(self, host_port): - """Returns the device port that corresponds to a given host port.""" - return host_port - - def WaitHostPortAvailable(self, port): - """Returns True if |port| is available.""" - return True - - def WaitPortNotAvailable(self, port): - """Returns True if |port| is not available.""" - return True - - def WaitDevicePortReady(self, port): - """Returns whether the provided port is used.""" - return True - - def Unmap(self, device_port): - """Unmaps specified port""" - pass - - -class TestServerThread(threading.Thread): - """A thread to run the test server in a separate process.""" - - def __init__(self, ready_event, arguments, port_forwarder): - """Initialize TestServerThread with the following argument. - - Args: - ready_event: event which will be set when the test server is ready. - arguments: dictionary of arguments to run the test server. - device: An instance of DeviceUtils. - tool: instance of runtime error detection tool. - """ - threading.Thread.__init__(self) - self.wait_event = threading.Event() - self.stop_event = threading.Event() - self.ready_event = ready_event - self.ready_event.clear() - self.arguments = arguments - self.port_forwarder = port_forwarder - self.test_server_process = None - self.is_ready = False - self.host_port = 0 - self.host_ocsp_port = 0 - assert isinstance(self.host_port, int) - # The forwarder device port now is dynamically allocated. - self.forwarder_device_port = 0 - self.forwarder_ocsp_device_port = 0 - self.process = None - self.command_line = [] - - def _WaitToStartAndGetPortFromTestServer(self, pipe_in): - """Waits for the Python test server to start and gets the port it is using. - - The port information is passed by the Python test server with a pipe given - by |pipe_in|. It is written as a result to |self.host_port|. - - Returns: - Whether the port used by the test server was successfully fetched. - """ - (in_fds, _, _) = select.select([pipe_in], [], []) - if len(in_fds) == 0: - _logger.error('Failed to wait to the Python test server to be started.') - return False - # First read the data length as an unsigned 4-byte value. This - # is _not_ using network byte ordering since the Python test server packs - # size as native byte order and all Chromium platforms so far are - # configured to use little-endian. - # TODO(jnd): Change the Python test server and local_test_server_*.cc to - # use a unified byte order (either big-endian or little-endian). - data_length = os.read(pipe_in, struct.calcsize('=L')) - if data_length: - (data_length,) = struct.unpack('=L', data_length) - assert data_length - if not data_length: - _logger.error('Failed to get length of server data.') - return False - server_data_json = os.read(pipe_in, data_length) - if not server_data_json: - _logger.error('Failed to get server data.') - return False - _logger.info('Got port json data: %s', server_data_json) - - parsed_server_data = None - try: - parsed_server_data = json.loads(server_data_json) - except ValueError: - pass - - if not isinstance(parsed_server_data, dict): - _logger.error('Failed to parse server_data: %s' % server_data_json) - return False - - if not isinstance(parsed_server_data.get('port'), int): - _logger.error('Failed to get port information from the server data.') - return False - - self.host_port = parsed_server_data['port'] - self.host_ocsp_port = parsed_server_data.get('ocsp_port', 0) - - return self.port_forwarder.WaitPortNotAvailable(self.host_port) - - def _GenerateCommandLineArguments(self, pipe_out): - """Generates the command line to run the test server. - - Note that all options are processed by following the definitions in - testserver.py. - """ - if self.command_line: - return - - args_copy = dict(self.arguments) - - # Translate the server type. - type_cmd = _GetServerTypeCommandLine(args_copy.pop('server-type')) - if type_cmd: - self.command_line.append(type_cmd) - - # Use a pipe to get the port given by the Python test server. - self.command_line.append('--startup-pipe=%d' % pipe_out) - - # Pass the remaining arguments as-is. - for key, values in args_copy.items(): - if not isinstance(values, list): - values = [values] - for value in values: - if value is None: - self.command_line.append('--%s' % key) - else: - self.command_line.append('--%s=%s' % (key, value)) - - def _CloseUnnecessaryFDsForTestServerProcess(self, pipe_out): - # This is required to avoid subtle deadlocks that could be caused by the - # test server child process inheriting undesirable file descriptors such as - # file lock file descriptors. Note stdin, stdout, and stderr (0-2) are left - # alone and redirected with subprocess.Popen. It is important to leave those - # fds filled, or the test server will accidentally open other fds at those - # numbers. - for fd in range(3, 1024): - if fd != pipe_out: - try: - os.close(fd) - except: - pass - - def run(self): - _logger.info('Start running the thread!') - self.wait_event.clear() - - # Set up a pipe for the server to report when it has started. - pipe_in, pipe_out = os.pipe() - - # TODO(crbug.com/40618161): Remove if condition after python3 migration. - if hasattr(os, 'set_inheritable'): - os.set_inheritable(pipe_out, True) - - try: - self._GenerateCommandLineArguments(pipe_out) - # TODO(crbug.com/40618161): When this script is ported to Python 3, replace - # 'vpython3' below with sys.executable. - command = [ - 'vpython3', - os.path.join(_DIR_SOURCE_ROOT, 'net', 'tools', 'testserver', - 'testserver.py') - ] + self.command_line - _logger.info('Running: %s', command) - - # Disable PYTHONUNBUFFERED because it has a bad interaction with the - # testserver. Remove once this interaction is fixed. - unbuf = os.environ.pop('PYTHONUNBUFFERED', None) - - # Pass _DIR_SOURCE_ROOT as the child's working directory so that relative - # paths in the arguments are resolved correctly. devnull can be replaced - # with subprocess.DEVNULL in Python 3. - with open(os.devnull, 'r+b') as devnull: - self.process = subprocess.Popen( - command, - preexec_fn=lambda: self._CloseUnnecessaryFDsForTestServerProcess( - pipe_out), - stdin=devnull, - # Preserve stdout and stderr from the test server. - stdout=None, - stderr=None, - cwd=_DIR_SOURCE_ROOT, - close_fds=False) - - # Close pipe_out early. If self.process crashes, this will be visible - # in _WaitToStartAndGetPortFromTestServer's select loop. - os.close(pipe_out) - pipe_out = -1 - if unbuf: - os.environ['PYTHONUNBUFFERED'] = unbuf - self.is_ready = self._WaitToStartAndGetPortFromTestServer(pipe_in) - - if self.is_ready: - port_map = [(0, self.host_port)] - if self.host_ocsp_port: - port_map.extend([(0, self.host_ocsp_port)]) - self.port_forwarder.Map(port_map) - - self.forwarder_device_port = \ - self.port_forwarder.GetDevicePortForHostPort(self.host_port) - if self.host_ocsp_port: - self.forwarder_ocsp_device_port = \ - self.port_forwarder.GetDevicePortForHostPort(self.host_ocsp_port) - - # Check whether the forwarder is ready on the device. - self.is_ready = self.forwarder_device_port and \ - self.port_forwarder.WaitDevicePortReady(self.forwarder_device_port) - - # Wake up the request handler thread. - self.ready_event.set() - # Keep thread running until Stop() gets called. - self.stop_event.wait() - if self.process.poll() is None: - self.process.kill() - # Wait for process to actually terminate. - # (crbug.com/946475) - self.process.wait() - - self.port_forwarder.Unmap(self.forwarder_device_port) - self.process = None - self.is_ready = False - finally: - if pipe_in >= 0: - os.close(pipe_in) - if pipe_out >= 0: - os.close(pipe_out) - _logger.info('Test-server has died.') - self.wait_event.set() - - def Stop(self): - """Blocks until the loop has finished. - - Note that this must be called in another thread. - """ - if not self.process: - return - self.stop_event.set() - self.wait_event.wait() - - -class SpawningServerRequestHandler(BaseHTTPRequestHandler): - """A handler used to process http GET/POST request.""" - - def _SendResponse(self, response_code, response_reason, additional_headers, - contents): - """Generates a response sent to the client from the provided parameters. - - Args: - response_code: number of the response status. - response_reason: string of reason description of the response. - additional_headers: dict of additional headers. Each key is the name of - the header, each value is the content of the header. - contents: string of the contents we want to send to client. - """ - self.send_response(response_code, response_reason) - self.send_header('Content-Type', 'text/html') - # Specify the content-length as without it the http(s) response will not - # be completed properly (and the browser keeps expecting data). - self.send_header('Content-Length', len(contents)) - for header_name in additional_headers: - self.send_header(header_name, additional_headers[header_name]) - self.end_headers() - self.wfile.write(contents.encode('utf8')) - self.wfile.flush() - - def _StartTestServer(self): - """Starts the test server thread.""" - _logger.info('Handling request to spawn a test server.') - content_type = self.headers.get('content-type') - if content_type != 'application/json': - raise Exception('Bad content-type for start request.') - content_length = self.headers.get('content-length') - if not content_length: - content_length = 0 - try: - content_length = int(content_length) - except: - raise Exception('Bad content-length for start request.') - _logger.info(content_length) - test_server_argument_json = self.rfile.read(content_length) - _logger.info(test_server_argument_json) - - if len(self.server.test_servers) >= self.server.max_instances: - self._SendResponse(400, 'Invalid request', {}, - 'Too many test servers running') - return - - ready_event = threading.Event() - new_server = TestServerThread(ready_event, - json.loads(test_server_argument_json), - self.server.port_forwarder) - new_server.setDaemon(True) - new_server.start() - ready_event.wait() - if new_server.is_ready: - response = {'port': new_server.forwarder_device_port, - 'message': 'started'}; - if new_server.forwarder_ocsp_device_port: - response['ocsp_port'] = new_server.forwarder_ocsp_device_port - self._SendResponse(200, 'OK', {}, json.dumps(response)) - _logger.info('Test server is running on port %d forwarded to %d.' % - (new_server.forwarder_device_port, new_server.host_port)) - port = new_server.forwarder_device_port - assert port not in self.server.test_servers - self.server.test_servers[port] = new_server - else: - new_server.Stop() - self._SendResponse(500, 'Test Server Error.', {}, '') - _logger.info('Encounter problem during starting a test server.') - - def _KillTestServer(self, params): - """Stops the test server instance.""" - try: - port = int(params['port'][0]) - except ValueError: - port = None - if port == None or port <= 0: - self._SendResponse(400, 'Invalid request.', {}, 'port must be specified') - return - - if port not in self.server.test_servers: - self._SendResponse(400, 'Invalid request.', {}, - "testserver isn't running on port %d" % port) - return - - server = self.server.test_servers.pop(port) - - _logger.info('Handling request to kill a test server on port: %d.', port) - server.Stop() - - # Make sure the status of test server is correct before sending response. - if self.server.port_forwarder.WaitHostPortAvailable(port): - self._SendResponse(200, 'OK', {}, 'killed') - _logger.info('Test server on port %d is killed', port) - else: - # We expect the port to be free, but nothing stops the system from - # binding something else to that port, so don't throw error. - # (crbug.com/946475) - self._SendResponse(200, 'OK', {}, '') - _logger.warn('Port %s is not free after killing test server.' % port) - - def log_message(self, format, *args): - # Suppress the default HTTP logging behavior if the logging level is higher - # than INFO. - if _logger.getEffectiveLevel() <= logging.INFO: - pass - - def do_POST(self): - parsed_path = urllib.parse.urlparse(self.path) - action = parsed_path.path - _logger.info('Action for POST method is: %s.', action) - if action == '/start': - self._StartTestServer() - else: - self._SendResponse(400, 'Unknown request.', {}, '') - _logger.info('Encounter unknown request: %s.', action) - - def do_GET(self): - parsed_path = urllib.parse.urlparse(self.path) - action = parsed_path.path - params = urllib.parse.parse_qs(parsed_path.query, keep_blank_values=1) - _logger.info('Action for GET method is: %s.', action) - for param in params: - _logger.info('%s=%s', param, params[param][0]) - if action == '/kill': - self._KillTestServer(params) - elif action == '/ping': - # The ping handler is used to check whether the spawner server is ready - # to serve the requests. We don't need to test the status of the test - # server when handling ping request. - self._SendResponse(200, 'OK', {}, 'ready') - _logger.info('Handled ping request and sent response.') - else: - self._SendResponse(400, 'Unknown request', {}, '') - _logger.info('Encounter unknown request: %s.', action) - - -class SpawningServer(object): - """The class used to start/stop a http server.""" - - def __init__(self, test_server_spawner_port, port_forwarder, max_instances): - self.server = HTTPServer(('', test_server_spawner_port), - SpawningServerRequestHandler) - self.server_port = self.server.server_port - _logger.info('Started test server spawner on port: %d.', self.server_port) - - self.server.port_forwarder = port_forwarder - self.server.test_servers = {} - self.server.max_instances = max_instances - - def _Listen(self): - _logger.info('Starting test server spawner.') - self.server.serve_forever() - - def Start(self): - """Starts the test server spawner.""" - listener_thread = threading.Thread(target=self._Listen) - listener_thread.setDaemon(True) - listener_thread.start() - - def Stop(self): - """Stops the test server spawner. - - Also cleans the server state. - """ - self.CleanupState() - self.server.shutdown() - - def CleanupState(self): - """Cleans up the spawning server state. - - This should be called if the test server spawner is reused, - to avoid sharing the test server instance. - """ - if self.server.test_servers: - _logger.warning('Not all test servers were stopped.') - for port in self.server.test_servers: - _logger.warning('Stopping test server on port %d' % port) - self.server.test_servers[port].Stop() - self.server.test_servers = {} diff --git a/naiveproxy/src/build/util/tast_control.py b/naiveproxy/src/build/util/tast_control.py index 7a21af709b..3d095cc415 100755 --- a/naiveproxy/src/build/util/tast_control.py +++ b/naiveproxy/src/build/util/tast_control.py @@ -27,6 +27,7 @@ def PopulateData(out, data, indent=2): continue if stripped.startswith('#'): continue + stripped = stripped.removeprefix('tast.') out.write(' ' * indent) out.write('"%s",\n' % stripped) diff --git a/naiveproxy/src/build/xcode_binaries.yaml b/naiveproxy/src/build/xcode_binaries.yaml index eef9287f2d..e22ab237a9 100644 --- a/naiveproxy/src/build/xcode_binaries.yaml +++ b/naiveproxy/src/build/xcode_binaries.yaml @@ -1,21 +1,27 @@ # This yaml file is used to package binaries from Xcode.app. +# # To use this: # 1) Make sure Xcode is fully updated (via the app store or otherwise). -# 2) Move Xcode.app to the same directory as this file, -# and rename Xcode.app to xcode_binaries. Or make a symlink: +# 2) Move Xcode.app to the same directory as this file, and rename Xcode.app +# to xcode_binaries. Or make a symlink: # $ rm -rf build/xcode_binaries && \ # ln -s /Applications/Xcode.app build/xcode_binaries -# 3) Call `cipd create --pkg-def build/xcode_binaries.yaml \ -# -ref -ref ` -# a.) The version information can be found in "About Xcode", -# or by running `xcodebuild -version` +# 3) Create the package and upload it to CIPD: +# $ cipd create --pkg-def build/xcode_binaries.yaml \ +# -ref ${xcode_version} -ref ${xcode_build_version} \ +# -ref sdk_${sdk_version} -ref sdk_${sdk_build_version} +# ${xcode_version} and ${xcode_build_version} can be found in "About +# Xcode", or by running `xcodebuild -version`. ${sdk_version} can be found +# by running `xcrun --show-sdk-version`. ${sdk_build_version} can be found +# by running `xcrun --show-sdk-build-version`. +# # To deploy the newly created cipd package across the fleet, modify # ./mac_toolchain.py to point to the new cipd hash, and update the # mac_sdk_official_* variables in build/config/mac/mac_sdk.gni. # # Note that the Chromium build looks for the mac binaries in -# build/mac_files/xcode_binaries; it won't see the build/xcode_binaries that -# you just created. In order to use the new toolchain version, you still need to +# build/mac_files/xcode_binaries; it won't see the build/xcode_binaries that you +# just created. In order to use the new toolchain version, you still need to # `gclient runhooks` after updating the hash in mac_toolchain.py. # # The ACLs for this package are determined by the directory structure. The @@ -25,8 +31,8 @@ description: A hermetic deployment of all Xcode binaries used to build Chromium. root: "xcode_binaries" data: - dir: Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ - - dir: Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/share/bison - - dir: Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/metal + - dir: Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/share/bison/ + - dir: Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/metal/ - file: Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/air-lld - file: Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/bison - file: Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/gm4 @@ -55,12 +61,12 @@ data: - file: Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/libexec/migcom - file: Contents/Developer/usr/bin/atos - file: Contents/Developer/usr/bin/notarytool - - file: Contents/Resources/en.lproj/License.rtf - file: Contents/Resources/LicenseInfo.plist - - dir: Contents/SharedFrameworks/CoreSymbolicationDT.framework - - dir: Contents/SharedFrameworks/DebugSymbolsDT.framework - - dir: Contents/SharedFrameworks/MallocStackLoggingDT.framework - - dir: Contents/SharedFrameworks/SymbolicationDT.framework + - file: Contents/Resources/en.lproj/License.rtf + - dir: Contents/SharedFrameworks/CoreSymbolicationDT.framework/ + - dir: Contents/SharedFrameworks/DebugSymbolsDT.framework/ + - dir: Contents/SharedFrameworks/MallocStackLoggingDT.framework/ + - dir: Contents/SharedFrameworks/SymbolicationDT.framework/ - file: Contents/version.plist # llvm-size and size are run on swarming, those are symlinked to out of # isolated tree and produce invalid symlinks if we don't use copy mode here. diff --git a/naiveproxy/src/build_overrides/build.gni b/naiveproxy/src/build_overrides/build.gni index 279041fa61..ec8982ac2f 100644 --- a/naiveproxy/src/build_overrides/build.gni +++ b/naiveproxy/src/build_overrides/build.gni @@ -46,9 +46,8 @@ declare_args() { # //third_party/robolectric . limit_android_deps = false - # Allows googletest to pretty-print various absl types. Disabled for nacl due - # to lack of toolchain support. - gtest_enable_absl_printers = !is_nacl + # Allows googletest to pretty-print various absl types. + gtest_enable_absl_printers = true # Allow projects that wish to stay on C++17 to override Chromium's default. # TODO(crbug.com/40251117): evaluate removing this end of 2023 @@ -59,7 +58,7 @@ declare_args() { declare_args() { # Use Perfetto's trace processor for converting protobuf-encoded traces to # the legacy JSON format in base::TraceLog. - use_perfetto_trace_processor = !is_nacl && !is_cronet_build + use_perfetto_trace_processor = !is_cronet_build } # Allows different projects to specify their own suppression/ignore lists for diff --git a/naiveproxy/src/build_overrides/partition_alloc.gni b/naiveproxy/src/build_overrides/partition_alloc.gni index ae7040d2d2..c039386e97 100644 --- a/naiveproxy/src/build_overrides/partition_alloc.gni +++ b/naiveproxy/src/build_overrides/partition_alloc.gni @@ -78,10 +78,8 @@ partition_alloc_remove_configs += _disable_partition_alloc_everywhere = (!is_linux && is_component_build) || (is_win && is_debug) -# - NaCl: No plans to support it. # - iOS: Depends on ios_partition_alloc_enabled. -_is_partition_alloc_everywhere_platform = - !is_nacl && (!is_ios || ios_partition_alloc_enabled) +_is_partition_alloc_everywhere_platform = !is_ios || ios_partition_alloc_enabled use_allocator_shim_default = true # Updated below: @@ -90,19 +88,12 @@ if (is_asan || is_hwasan || is_lsan || is_tsan || is_msan) { use_allocator_shim_default = false } -# NaCl will never support the allocator shim. -if (is_nacl) { - use_allocator_shim_default = false -} - # Under Fuchsia, the allocator shim is only required for PA-E. if (is_fuchsia && _disable_partition_alloc_everywhere) { use_allocator_shim_default = false } # Under Windows debug build, the allocator shim is not compatible with CRT. -# NaCl in particular does seem to link some binaries statically against the -# debug CRT with "is_nacl=false". if (is_win && is_debug) { use_allocator_shim_default = false } diff --git a/naiveproxy/src/buildtools/deps_revisions.gni b/naiveproxy/src/buildtools/deps_revisions.gni index 16be0a7ec1..fe1a65609c 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 var in //DEPS. - libcxx_revision = "2c359c239b138a20a03f798e47889448ef131c22" + libcxx_revision = "adbb4a5210ae2a8a4e27fa6199221156c02a9b1a" } diff --git a/naiveproxy/src/buildtools/third_party/eu-strip/bin/eu-strip b/naiveproxy/src/buildtools/third_party/eu-strip/bin/eu-strip deleted file mode 100755 index 7dcb3c0ddb..0000000000 Binary files a/naiveproxy/src/buildtools/third_party/eu-strip/bin/eu-strip and /dev/null differ diff --git a/naiveproxy/src/buildtools/third_party/libc++/BUILD.gn b/naiveproxy/src/buildtools/third_party/libc++/BUILD.gn index 7135ef310b..2900b06198 100644 --- a/naiveproxy/src/buildtools/third_party/libc++/BUILD.gn +++ b/naiveproxy/src/buildtools/third_party/libc++/BUILD.gn @@ -3,10 +3,15 @@ # found in the LICENSE file. import("//build/config/c++/c++.gni") -import("//build/config/clang/clang.gni") +import("//build/config/compiler/compiler.gni") import("//build/config/sanitizers/sanitizers.gni") import("//build/toolchain/toolchain.gni") import("//buildtools/third_party/libc++/libcxx_headers.gni") +import("//buildtools/third_party/libc++/modules.gni") + +if (is_mac) { + import("//build/config/mac/mac_sdk.gni") +} # Used by libc++ and libc++abi. # See //build/config/c++:runtime_library for the config used by users of libc++. @@ -22,15 +27,21 @@ config("config") { "-Wno-macro-redefined", ] - cflags_cc = [ - # We want to use a uniform C++ version across all of chromium, but - # upstream libc++ requires C++20 so we have to make an exception here. - # No other target should override the default -std= flag. - "-std:c++20", - ] + # We want to use a uniform C++ version across all of chromium, but upstream + # libc++ requires at least C++20 so we have to make an exception here. No + # other target should override the default -std= flag. + if (use_cxx23) { + cflags_cc = [ "-std:c++23" ] + } else { + cflags_cc = [ "-std:c++20" ] + } } else { cflags += [ "-fPIC" ] - cflags_cc = [ "-std=c++20" ] + if (use_cxx23) { + cflags_cc = [ "-std=c++23" ] + } else { + cflags_cc = [ "-std=c++20" ] + } } defines = [ "_LIBCPP_BUILDING_LIBRARY" ] @@ -47,112 +58,588 @@ config("winver") { ] } -configs_to_add = [ - ":config", - "//build/config/compiler:no_chromium_code", -] - -configs_to_remove = [ - "//build/config/compiler:chromium_code", - "//build/config/coverage:default_coverage", -] - -if (use_libcxx_modules) { - template("sysroot_modules") { - source_set(target_name) { - forward_variables_from(invoker, [ "public_deps" ]) - use_libcxx_modules = false - sources = [ "//build/linux/amd64/module.modulemap" ] - deps = [ - ":copy_custom_headers", - ":copy_libcxx_headers", +if (use_clang_modules) { + if (is_linux || is_chromeos) { + textual_module("sysroot_ctype") { + } + textual_module("sysroot_errno") { + public_deps = [ ":sysroot" ] + } + textual_module("sysroot_fenv") { + } + alias("sysroot_features") { + actual = [ ":sysroot_limits" ] + } + textual_module("sysroot_inttypes") { + public_deps = [ + ":_Builtin_stdint", + ":sysroot_features", ] - - configs -= configs_to_remove - configs += configs_to_add } - } - - sysroot_modules("sysroot_features") { - } - - sysroot_modules("sysroot_bits") { - public_deps = [ - ":sysroot_features", - ":sysroot_time", - ] - } - - sysroot_modules("sysroot_time") { - public_deps = [ ":sysroot_features" ] - } - - sysroot_modules("sysroot_types") { - public_deps = [ - ":sysroot_bits", - ":sysroot_features", - ":sysroot_time", - ] - } - - template("builtin_modules") { - # This is a template to build clang builtin's module file. - source_set(target_name) { - forward_variables_from(invoker, [ "public_deps" ]) - use_libcxx_modules = false - sources = [ "${clang_base_path}/lib/clang/${clang_version}/include/module.modulemap" ] - - configs -= configs_to_remove - configs += configs_to_add + sysroot_module("sysroot_limits") { } - } - builtin_modules("_Builtin_float") { - } + alias("sysroot_locale") { + actual = [] + } - builtin_modules("_Builtin_intrinsics") { - public_deps = [ - ":_Builtin_limits", - ":_Builtin_stddef", - ] - } + textual_module("sysroot_math") { + public_deps = [ ":sysroot_stdlib" ] + } - builtin_modules("_Builtin_inttypes") { - } + alias("sysroot_pthread") { + actual = [ ":sysroot" ] + } - builtin_modules("_Builtin_limits") { - public_deps = [] - } + textual_module("sysroot_stdatomic") { + } + textual_module("sysroot_stdint") { + public_deps = [ ":sysroot_features" ] + } + alias("sysroot_stdlib") { + actual = [ ":sysroot" ] + } + textual_module("sysroot_string") { + public_deps = [ + ":_Builtin_stddef", + ":sysroot", + ] + } + textual_module("sysroot_uchar") { + public_deps = [ ":_Builtin_stddef" ] + } + alias("sysroot_wchar") { + actual = [ ":sysroot" ] + } + textual_module("sysroot_wctype") { + } - builtin_modules("_Builtin_stdalign") { - } - - builtin_modules("_Builtin_stdarg") { - } - - builtin_modules("_Builtin_stdatomic") { - } - - builtin_modules("_Builtin_stdbool") { - } - - builtin_modules("_Builtin_stddef") { - } - - builtin_modules("_Builtin_stdint") { - public_deps = [] - if (is_mac) { - public_deps += [ + sysroot_module("sysroot") { + public_deps = [ + ":_Builtin_limits", ":_Builtin_stdarg", ":_Builtin_stddef", ] } + + alias("all_sysroot") { + actual = [ + ":sysroot_limits", + ":sysroot", + ] + } + } else if (is_android) { + textual_module("sysroot_ctype") { + public_deps = [ ":sysroot" ] + } + + textual_module("sysroot_errno") { + public_deps = [ ":sysroot" ] + } + + sysroot_module("sysroot_features") { + } + + textual_module("sysroot_fenv") { + public_deps = [ ":sysroot" ] + } + + textual_module("sysroot_inttypes") { + public_deps = [ + ":_Builtin_stdint", + ":sysroot_features", + ] + } + + textual_module("sysroot_limits") { + public_deps = [ ":sysroot_features" ] + } + + alias("sysroot_locale") { + actual = [] + } + + textual_module("sysroot_math") { + public_deps = [ ":sysroot_stdlib" ] + } + + alias("sysroot_pthread") { + actual = [ ":sysroot" ] + } + + textual_module("sysroot_stdatomic") { + # stdatomic includes libc++'s + public_deps = [ ":std" ] + } + + textual_module("sysroot_stdint") { + public_deps = [ + ":_Builtin_stddef", + ":sysroot_features", + ] + } + + alias("sysroot_stdlib") { + actual = [ ":sysroot" ] + } + + textual_module("sysroot_string") { + public_deps = [ + ":_Builtin_stddef", + ":sysroot", + ] + } + + textual_module("sysroot_uchar") { + public_deps = [ + ":_Builtin_stddef", + ":sysroot", + ] + } + + textual_module("sysroot_wctype") { + public_deps = [ ":sysroot" ] + } + + alias("sysroot_wchar") { + actual = [ ":sysroot" ] + } + + config("wchar_fix") { + # See https://github.com/llvm/llvm-project/blob/3f33e7ba5b08a97939280e539ad20a34d54b2719/libcxx/include/wchar.h#L139 + # Since android doesn't come with glibc, this isn't defined, and thus + # wchar.h defines (not declares) additional overloads when this is unset, + # and wchar.h is textual, we set this to ensure ODR is not violated. + defines = [ "_LIBCPP_WCHAR_H_HAS_CONST_OVERLOADS" ] + } + + sysroot_module("sysroot") { + public_deps = [ + ":_Builtin_limits", + ":_Builtin_stdarg", + ":_Builtin_stddef", + ":_Builtin_stdint", + ] + public_configs = [ ":wchar_fix" ] + } + + alias("all_sysroot") { + actual = [ + ":sysroot_features", + ":sysroot", + ] + } + } else if (is_apple) { + if (default_toolchain == current_toolchain && is_ios) { + # sysroot_modulemaps can be inside the build directory. This no-op action + # declares the modulemap files as outputs to satisfy GN's dependency + # tracking when other targets use them as inputs. + action("copy_sysroot_modulemaps") { + script = "//build/noop.py" + outputs = sysroot_modulemaps + } + } + + DarwinBasic_module("MachO") { + public_deps = [ + ":_Builtin_stdbool", + ":_Builtin_stdint", + ":_limits", + ":_string", + ":mach", + ":std_string_h", + ":unistd", + ":uuid", + ] + } + + DarwinBasic_module("_strings") { + public_deps = [ ":DarwinFoundation" ] + } + + DarwinBasic_module("alloca") { + public_deps = [ ":DarwinFoundation" ] + } + + DarwinBasic_module("gethostuuid") { + public_deps = [ + ":_time", + ":uuid", + ] + } + + DarwinBasic_module("nl_types") { + public_deps = [ + ":DarwinFoundation", + ":sys_types", + ] + } + + DarwinBasic_module("pthread") { + public_deps = [ + ":DarwinFoundation", + ":_signal", + ":_time", + ":mach", + ] + } + + DarwinBasic_module("runetype") { + public_deps = [ ":DarwinFoundation" ] + } + + DarwinBasic_module("sys_select") { + public_deps = [ + ":DarwinFoundation", + ":_signal", + ":_sys_select", + ":_time", + ":sys_time", + ] + } + + DarwinBasic_module("sys_types") { + public_deps = [ + ":DarwinFoundation", + ":_errno", + ":_sys_select", + ":_useconds_t", + ":netinet_in", + ] + } + + DarwinBasic_module("sys_wait") { + public_deps = [ + ":DarwinFoundation", + ":_signal", + ":sys_resource", + ":sys_types", + ] + } + + DarwinBasic_module("sys_resource") { + public_deps = [ + ":DarwinFoundation", + ":_Builtin_stdint", + ":sys_time", + ":sys_types", + ] + } + + DarwinBasic_module("unistd") { + public_deps = [ + ":DarwinFoundation", + ":_limits", + ":_stdio", + ":gethostuuid", + ":sys_select", + ":uuid", + ] + } + + DarwinBasic_module("xlocale") { + public_deps = [ + ":DarwinFoundation", + ":_locale", + ] + } + + DarwinFoundation_module("DarwinFoundation") { + public_deps = [ + ":_Builtin_stdarg", + ":_Builtin_stddef", + ] + } + + DarwinFoundation_module("_sys_select") { + public_deps = [ ":DarwinFoundation" ] + } + + DarwinFoundation_module("_useconds_t") { + public_deps = [ ":DarwinFoundation" ] + } + + DarwinFoundation_module("mach") { + public_deps = [ ":DarwinFoundation" ] + } + + DarwinFoundation_module("netinet_in") { + public_deps = [ ":DarwinFoundation" ] + } + + DarwinFoundation_module("sys_time") { + public_deps = [ ":DarwinFoundation" ] + } + + DarwinFoundation_module("uuid") { + public_deps = [ ":DarwinFoundation" ] + } + + c_standard_library_module("__wctype") { + public_deps = [ + ":_ctype", + ":std_ctype_h", + ] + } + + c_standard_library_module("_assert") { + public_deps = [ ":DarwinFoundation" ] + } + + c_standard_library_module("_ctype") { + public_deps = [ + ":DarwinFoundation", + ":runetype", + ] + } + + c_standard_library_module("_errno") { + public_deps = [ ":DarwinFoundation" ] + } + + c_standard_library_module("_fenv") { + } + + c_standard_library_module("_inttypes") { + public_deps = [ + ":_Builtin_stdint", + ":_stdint", + ] + } + + c_standard_library_module("_limits") { + public_deps = [ ":DarwinFoundation" ] + } + + c_standard_library_module("_locale") { + public_deps = [ ":DarwinFoundation" ] + } + + c_standard_library_module("_math") { + public_deps = [ ":DarwinFoundation" ] + } + + c_standard_library_module("_setjmp") { + public_deps = [ ":DarwinFoundation" ] + } + + c_standard_library_module("_signal") { + public_deps = [ + ":DarwinFoundation", + ":mach", + ":sys_types", + ] + } + + c_standard_library_module("_stdint") { + public_deps = [ ":DarwinFoundation" ] + } + + c_standard_library_module("_stdio") { + public_deps = [ + ":DarwinFoundation", + ":sys_types", + ] + } + + c_standard_library_module("_stdlib") { + public_deps = [ + ":_signal", + ":_stdint", + ":alloca", + ":runetype", + ":sys_wait", + ] + } + + c_standard_library_module("_string") { + public_deps = [ + ":DarwinFoundation", + ":_strings", + ":sys_types", + ] + } + + c_standard_library_module("_time") { + public_deps = [ + ":DarwinFoundation", + ":sys_types", + ] + } + + c_standard_library_module("_wchar") { + public_deps = [ + ":__wctype", + ":_stdio", + ":_time", + ] + } + + c_standard_library_module("_wctype") { + public_deps = [ ":__wctype" ] + } + + alias("all_sysroot") { + actual = [ + ":DarwinFoundation", + ":MachO", + ":__wctype", + ":_assert", + ":_ctype", + ":_errno", + ":_fenv", + ":_inttypes", + ":_limits", + ":_locale", + ":_setjmp", + ":_signal", + ":_stdint", + ":_stdio", + ":_stdlib", + ":_string", + ":_strings", + ":_sys_select", + ":_time", + ":_useconds_t", + ":_wchar", + ":_wctype", + ":alloca", + ":gethostuuid", + ":mach", + ":netinet_in", + ":nl_types", + ":pthread", + ":runetype", + ":sys_resource", + ":sys_time", + ":sys_types", + ":sys_wait", + ":unistd", + ":uuid", + ":xlocale", + ] + } + + alias("sysroot_ctype") { + actual = [ ":_ctype" ] + } + alias("sysroot_errno") { + actual = [ ":_errno" ] + } + alias("sysroot_fenv") { + actual = [ ":_fenv" ] + } + alias("sysroot_inttypes") { + actual = [ ":_inttypes" ] + } + alias("sysroot_limits") { + actual = [ ":_limits" ] + } + alias("sysroot_locale") { + actual = [ ":_locale" ] + } + alias("sysroot_math") { + actual = [ ":_math" ] + } + alias("sysroot_pthread") { + actual = [ ":pthread" ] + } + alias("sysroot_stdatomic") { + actual = [] + } + alias("sysroot_stdint") { + actual = [ ":_stdint" ] + } + alias("sysroot_stdlib") { + actual = [ ":_stdlib" ] + } + alias("sysroot_string") { + actual = [ ":_string" ] + } + alias("sysroot_uchar") { + actual = [] + } + alias("sysroot_wchar") { + actual = [ ":_wchar" ] + } + alias("sysroot_wctype") { + actual = [ ":_wctype" ] + } } - builtin_modules("_Builtin_unwind") { + builtin_module("_Builtin_float") { + } + + builtin_module("_Builtin_intrinsics") { + public_deps = [ + ":std_core", + ":sysroot_stdlib", + ] + if (current_cpu == "arm" || current_cpu == "arm64") { + # includes which requires _Builtin_stdint module. + public_deps += [ ":_Builtin_stdint" ] + } + } + + builtin_module("_Builtin_inttypes") { + public_deps = [ ":sysroot_inttypes" ] + } + + builtin_module("_Builtin_limits") { + public_deps = [ + ":std_float_h", + ":sysroot_limits", + ] + } + + builtin_module("_Builtin_stdalign") { + } + + builtin_module("_Builtin_stdarg") { + } + + builtin_module("_Builtin_stdatomic") { + public_deps = [ + ":_Builtin_stddef", + ":_Builtin_stdint", + ":sysroot_stdatomic", + ] + } + + builtin_module("_Builtin_stdbool") { + } + + builtin_module("_Builtin_stddef") { + } + + builtin_module("_Builtin_stdint") { + public_deps = [ ":sysroot_stdint" ] + } + + builtin_module("_Builtin_unwind") { public_deps = [ ":_Builtin_stdint" ] } + builtin_module("ptrauth") { + } + + alias("all_builtins") { + actual = [ + "//buildtools/third_party/libc++:_Builtin_float", + "//buildtools/third_party/libc++:_Builtin_intrinsics", + "//buildtools/third_party/libc++:_Builtin_inttypes", + "//buildtools/third_party/libc++:_Builtin_limits", + "//buildtools/third_party/libc++:_Builtin_stdalign", + "//buildtools/third_party/libc++:_Builtin_stdarg", + "//buildtools/third_party/libc++:_Builtin_stdatomic", + "//buildtools/third_party/libc++:_Builtin_stdbool", + "//buildtools/third_party/libc++:_Builtin_stddef", + "//buildtools/third_party/libc++:_Builtin_stdint", + "//buildtools/third_party/libc++:_Builtin_unwind", + "//buildtools/third_party/libc++:ptrauth", + ] + } + # We need to have libc++ headers, __assertion_handler and __config_site in the # same directory for clang modules build. copy("copy_libcxx_headers") { @@ -170,27 +657,10 @@ if (use_libcxx_modules) { ] } - template("libcxx_modules") { - # This is a template to build libc++'s module file. - source_set(target_name) { - forward_variables_from(invoker, [ "public_deps" ]) - - use_libcxx_modules = false - deps = [] - sources = - [ "${root_gen_dir}/third_party/libc++/src/include/module.modulemap" ] - deps += [ - ":copy_custom_headers", - ":copy_libcxx_headers", - ] - - configs -= configs_to_remove - configs += configs_to_add - } - } - - libcxx_modules("std") { + libcxx_module("std") { public_deps = [ + ":_Builtin_limits", + ":_Builtin_stdalign", ":std_core", ":std_ctype_h", ":std_errno_h", @@ -202,61 +672,145 @@ if (use_libcxx_modules) { ":std_string_h", ":std_uchar_h", ":std_wctype_h", + ":sysroot_locale", + ":sysroot_pthread", + ] + if (is_apple) { + public_deps += [ + # includes inside an __APPLE__ macro guard which + # requires nl_types module. + ":nl_types", + + # __locale_dir/support/apple.h includes __locale_dir/support/bsd_like.h, + # which includes xlocale.h. + ":xlocale", + ] + } + } + + textual_module("std_config") { + # Snippet from __configuration/platform.h: + # #if defined(__linux__) || defined(__AMDGPU__) || defined(__NVPTX__) + # if __has_include() + # include + if (is_linux || is_chromeos || is_android) { + public_deps = [ ":sysroot_features" ] + } + } + + libcxx_module("std_core") { + public_deps = [ + ":_Builtin_stddef", + ":_Builtin_stdint", + ":std_config", ] } - libcxx_modules("std_config") { + libcxx_module("std_ctype_h") { + public_deps = [ + ":std_config", + ":sysroot_ctype", + ] } - libcxx_modules("std_core") { + libcxx_module("std_errno_h") { + public_deps = [ + ":std_config", + ":sysroot_errno", + ] } - libcxx_modules("std_ctype_h") { + libcxx_module("std_fenv_h") { + public_deps = [ + ":std_config", + ":sysroot_fenv", + ] } - libcxx_modules("std_errno_h") { + libcxx_module("std_float_h") { + public_deps = [ + ":_Builtin_float", + ":std_config", + ] } - libcxx_modules("std_fenv_h") { + libcxx_module("std_inttypes_h") { + public_deps = [ + ":_Builtin_inttypes", + ":std_config", + ] } - libcxx_modules("std_float_h") { + libcxx_module("std_math_h") { + public_deps = [ + ":std_core", + ":sysroot_math", + ":sysroot_stdlib", + ] } - libcxx_modules("std_inttypes_h") { + libcxx_module("std_private_mbstate_t") { + public_deps = [ + ":std_config", + ":sysroot_wchar", + ] } - libcxx_modules("std_math_h") { - public_deps = [ ":std_core" ] + libcxx_module("std_stdatomic_h") { + public_deps = [ + ":_Builtin_stdatomic", + ":std_config", + ":sysroot_stdint", + ] } - libcxx_modules("std_private_mbstate_t") { + libcxx_module("std_string_h") { + public_deps = [ + ":std_config", + ":sysroot_string", + ] } - libcxx_modules("std_stdatomic_h") { + libcxx_module("std_uchar_h") { + public_deps = [ + ":std_private_mbstate_t", + ":sysroot_uchar", + ] } - libcxx_modules("std_stdbool_h") { + libcxx_module("std_wctype_h") { + public_deps = [ + ":std_config", + ":sysroot_wctype", + ] } - libcxx_modules("std_stddef_h") { + alias("all_std") { + # There are more modules than this, but since the others are purely + # textual, they don't need to be compiled to a pcm. + actual = [ + ":std", + ":std_core", + ":std_ctype_h", + ":std_errno_h", + ":std_fenv_h", + ":std_float_h", + ":std_inttypes_h", + ":std_math_h", + ":std_private_mbstate_t", + ":std_stdatomic_h", + ":std_string_h", + ":std_uchar_h", + ":std_wctype_h", + ] } - libcxx_modules("std_string_h") { - } - - libcxx_modules("std_uchar_h") { - public_deps = [ ":std_private_mbstate_t" ] - } - - libcxx_modules("std_wchar_h") { - } - - libcxx_modules("std_wctype_h") { - public_deps = [] - if (is_mac) { - public_deps += [ ":std_ctype_h" ] - } + alias("all_modules") { + actual = [ + ":all_builtins", + ":all_std", + ":all_sysroot", + ] } } @@ -266,7 +820,7 @@ target(libcxx_target_type, "libc++") { # need to explicitly depend on libc++. visibility = [ "//build/config:common_deps", - "//third_party/catapult/devil:devil", + "//third_party/catapult/devil", ] if (is_linux) { # This target packages libc++.so, so must have an explicit dependency on @@ -392,7 +946,7 @@ target(libcxx_target_type, "libc++") { deps = [ "//third_party/llvm-libc:llvm-libc-shared" ] - if (use_libcxx_modules) { + if (use_clang_modules) { # TODO(https://github.com/llvm/llvm-project/issues/127012): We don't enable # Clang modules for libc++ as libc++'s iostream.cpp has ODR issue # (https://crbug.com/40440396#comment81). Also we don't take care about the @@ -455,4 +1009,8 @@ target(libcxx_target_type, "libc++") { deps += [ "//buildtools/third_party/libc++abi" ] } } + + # Disabling -Wexit-time-destructors, as libc++ uses `static string` objects + # for locale code. + configs += [ "//build/config/compiler:no_exit_time_destructors" ] } diff --git a/naiveproxy/src/buildtools/third_party/libc++/generate_libcxx_headers.py b/naiveproxy/src/buildtools/third_party/libc++/generate_libcxx_headers.py new file mode 100755 index 0000000000..d07bf88b49 --- /dev/null +++ b/naiveproxy/src/buildtools/third_party/libc++/generate_libcxx_headers.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 + +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import os +import pathlib +import subprocess + +from typing import Optional + +_CURRENT_DIR = pathlib.Path(__file__).parent +_OUT_OF_DATE_ERROR = """Your libcxx_headers.gni is out of date. + +If you synced without running hooks, run `gclient sync` + +If you were messing around with the libc++ repository, run: +`buildtools/third_party/libc++/generate_libcxx_headers.py` + +In any other scenario, this *should not* happen. You can temporarily solve the +problem by running the above command, but please file a bug and assign it to +msta@ with reproduction details.""".replace('\n', '$0x0A') + + +def _get_headers(include_dir: pathlib.Path) -> list[str]: + headers = [] + for (dirpath, _, filenames) in os.walk(include_dir): + dirpath = pathlib.Path(dirpath).relative_to(include_dir) + for f in filenames: + path = dirpath / f + if f != 'CMakeLists.txt' and '__cxx03' not in path.parts: + headers.append(str(path)) + headers.sort() + return headers + + +def _get_libcxx_revision(path: pathlib.Path) -> Optional[str]: + # On CoG this command will fail because libcxx is not a git repository. + ps = subprocess.run( + ['git', 'rev-parse', 'HEAD'], + cwd=path, + check=False, + stdout=subprocess.PIPE, + text=True, + ) + if ps.returncode == 0: + return ps.stdout.strip() + + +def _write_headers(path: pathlib.Path, headers: list[str], + libcxx_revision: Optional[str]): + lines = [f' "//third_party/libc++/src/include/{hdr}",' for hdr in headers] + header_lines = '\n'.join(lines) + if libcxx_revision is None: + assertion = '' + else: + assertion = f""" +assert(libcxx_revision == "{libcxx_revision}", + "{_OUT_OF_DATE_ERROR}") +""" + path.write_text(f"""# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# DO NOT EDIT. This file is generated. +# This file should automatically be generated as a gclient hook. +# To manually regenerate, run: +# buildtools/third_party/libc++/generate_libcxx_headers.py + +import("//buildtools/deps_revisions.gni") +{assertion} +libcxx_headers = [ +{header_lines} +] +""") + + +if __name__ == '__main__': + libcxx = _CURRENT_DIR / '../../../third_party/libc++/src' + _write_headers( + _CURRENT_DIR / 'generated_libcxx_headers.gni', + _get_headers(libcxx / 'include'), + _get_libcxx_revision(libcxx), + ) diff --git a/naiveproxy/src/buildtools/third_party/libc++/libcxx_headers.gni b/naiveproxy/src/buildtools/third_party/libc++/libcxx_headers.gni index e261a602b6..2224d85f27 100644 --- a/naiveproxy/src/buildtools/third_party/libc++/libcxx_headers.gni +++ b/naiveproxy/src/buildtools/third_party/libc++/libcxx_headers.gni @@ -2,13 +2,10 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# Generate the list via -# $ find third_party/libc++/src/include/ -type f | fgrep -v "cxx03" | \ -# sed -E 's:(.*):"//\1",:g' | LANG=C sort -# +# DO NOT EDIT. This file is generated. +# To regenerate, run buildtools/third_party/libc++/generate_libcxx_headers.py + libcxx_headers = [ - # keep-sorted start - "//third_party/libc++/src/include/CMakeLists.txt", "//third_party/libc++/src/include/__algorithm/adjacent_find.h", "//third_party/libc++/src/include/__algorithm/all_of.h", "//third_party/libc++/src/include/__algorithm/any_of.h", @@ -392,6 +389,7 @@ libcxx_headers = [ "//third_party/libc++/src/include/__format/enable_insertable.h", "//third_party/libc++/src/include/__format/escaped_output_table.h", "//third_party/libc++/src/include/__format/extended_grapheme_cluster_table.h", + "//third_party/libc++/src/include/__format/fmt_pair_like.h", "//third_party/libc++/src/include/__format/format_arg.h", "//third_party/libc++/src/include/__format/format_arg_store.h", "//third_party/libc++/src/include/__format/format_args.h", @@ -414,6 +412,7 @@ libcxx_headers = [ "//third_party/libc++/src/include/__format/indic_conjunct_break_table.h", "//third_party/libc++/src/include/__format/parser_std_format_spec.h", "//third_party/libc++/src/include/__format/range_default_formatter.h", + "//third_party/libc++/src/include/__format/range_format.h", "//third_party/libc++/src/include/__format/range_formatter.h", "//third_party/libc++/src/include/__format/unicode.h", "//third_party/libc++/src/include/__format/width_estimation_table.h", @@ -509,6 +508,7 @@ libcxx_headers = [ "//third_party/libc++/src/include/__iterator/ostreambuf_iterator.h", "//third_party/libc++/src/include/__iterator/permutable.h", "//third_party/libc++/src/include/__iterator/prev.h", + "//third_party/libc++/src/include/__iterator/product_iterator.h", "//third_party/libc++/src/include/__iterator/projected.h", "//third_party/libc++/src/include/__iterator/ranges_iterator_traits.h", "//third_party/libc++/src/include/__iterator/readable_traits.h", @@ -521,13 +521,18 @@ libcxx_headers = [ "//third_party/libc++/src/include/__iterator/unreachable_sentinel.h", "//third_party/libc++/src/include/__iterator/wrap_iter.h", "//third_party/libc++/src/include/__locale", + "//third_party/libc++/src/include/__locale_dir/check_grouping.h", + "//third_party/libc++/src/include/__locale_dir/get_c_locale.h", "//third_party/libc++/src/include/__locale_dir/locale_base_api.h", - "//third_party/libc++/src/include/__locale_dir/locale_base_api/android.h", "//third_party/libc++/src/include/__locale_dir/locale_base_api/bsd_locale_fallbacks.h", "//third_party/libc++/src/include/__locale_dir/locale_base_api/ibm.h", "//third_party/libc++/src/include/__locale_dir/locale_base_api/musl.h", "//third_party/libc++/src/include/__locale_dir/locale_base_api/openbsd.h", + "//third_party/libc++/src/include/__locale_dir/messages.h", + "//third_party/libc++/src/include/__locale_dir/money.h", + "//third_party/libc++/src/include/__locale_dir/num.h", "//third_party/libc++/src/include/__locale_dir/pad_and_output.h", + "//third_party/libc++/src/include/__locale_dir/scan_keyword.h", "//third_party/libc++/src/include/__locale_dir/support/apple.h", "//third_party/libc++/src/include/__locale_dir/support/bsd_like.h", "//third_party/libc++/src/include/__locale_dir/support/freebsd.h", @@ -536,6 +541,10 @@ libcxx_headers = [ "//third_party/libc++/src/include/__locale_dir/support/no_locale/characters.h", "//third_party/libc++/src/include/__locale_dir/support/no_locale/strtonum.h", "//third_party/libc++/src/include/__locale_dir/support/windows.h", + "//third_party/libc++/src/include/__locale_dir/time.h", + "//third_party/libc++/src/include/__locale_dir/wbuffer_convert.h", + "//third_party/libc++/src/include/__locale_dir/wstring_convert.h", + "//third_party/libc++/src/include/__log_hardening_failure", "//third_party/libc++/src/include/__math/abs.h", "//third_party/libc++/src/include/__math/copysign.h", "//third_party/libc++/src/include/__math/error_functions.h", @@ -717,6 +726,7 @@ libcxx_headers = [ "//third_party/libc++/src/include/__ranges/iota_view.h", "//third_party/libc++/src/include/__ranges/istream_view.h", "//third_party/libc++/src/include/__ranges/join_view.h", + "//third_party/libc++/src/include/__ranges/join_with_view.h", "//third_party/libc++/src/include/__ranges/lazy_split_view.h", "//third_party/libc++/src/include/__ranges/movable_box.h", "//third_party/libc++/src/include/__ranges/non_propagating_cache.h", @@ -737,6 +747,7 @@ libcxx_headers = [ "//third_party/libc++/src/include/__ranges/transform_view.h", "//third_party/libc++/src/include/__ranges/view_interface.h", "//third_party/libc++/src/include/__ranges/views.h", + "//third_party/libc++/src/include/__ranges/zip_transform_view.h", "//third_party/libc++/src/include/__ranges/zip_view.h", "//third_party/libc++/src/include/__split_buffer", "//third_party/libc++/src/include/__std_mbstate_t.h", @@ -780,16 +791,14 @@ libcxx_headers = [ "//third_party/libc++/src/include/__tuple/make_tuple_types.h", "//third_party/libc++/src/include/__tuple/sfinae_helpers.h", "//third_party/libc++/src/include/__tuple/tuple_element.h", - "//third_party/libc++/src/include/__tuple/tuple_indices.h", "//third_party/libc++/src/include/__tuple/tuple_like.h", "//third_party/libc++/src/include/__tuple/tuple_like_ext.h", "//third_party/libc++/src/include/__tuple/tuple_like_no_subrange.h", "//third_party/libc++/src/include/__tuple/tuple_size.h", "//third_party/libc++/src/include/__tuple/tuple_types.h", "//third_party/libc++/src/include/__type_traits/add_cv_quals.h", - "//third_party/libc++/src/include/__type_traits/add_lvalue_reference.h", "//third_party/libc++/src/include/__type_traits/add_pointer.h", - "//third_party/libc++/src/include/__type_traits/add_rvalue_reference.h", + "//third_party/libc++/src/include/__type_traits/add_reference.h", "//third_party/libc++/src/include/__type_traits/aligned_storage.h", "//third_party/libc++/src/include/__type_traits/aligned_union.h", "//third_party/libc++/src/include/__type_traits/alignment_of.h", @@ -811,6 +820,7 @@ libcxx_headers = [ "//third_party/libc++/src/include/__type_traits/extent.h", "//third_party/libc++/src/include/__type_traits/has_unique_object_representation.h", "//third_party/libc++/src/include/__type_traits/has_virtual_destructor.h", + "//third_party/libc++/src/include/__type_traits/integer_traits.h", "//third_party/libc++/src/include/__type_traits/integral_constant.h", "//third_party/libc++/src/include/__type_traits/invoke.h", "//third_party/libc++/src/include/__type_traits/is_abstract.h", @@ -861,7 +871,6 @@ libcxx_headers = [ "//third_party/libc++/src/include/__type_traits/is_same.h", "//third_party/libc++/src/include/__type_traits/is_scalar.h", "//third_party/libc++/src/include/__type_traits/is_signed.h", - "//third_party/libc++/src/include/__type_traits/is_signed_integer.h", "//third_party/libc++/src/include/__type_traits/is_specialization.h", "//third_party/libc++/src/include/__type_traits/is_standard_layout.h", "//third_party/libc++/src/include/__type_traits/is_swappable.h", @@ -875,7 +884,6 @@ libcxx_headers = [ "//third_party/libc++/src/include/__type_traits/is_unbounded_array.h", "//third_party/libc++/src/include/__type_traits/is_union.h", "//third_party/libc++/src/include/__type_traits/is_unsigned.h", - "//third_party/libc++/src/include/__type_traits/is_unsigned_integer.h", "//third_party/libc++/src/include/__type_traits/is_valid_expansion.h", "//third_party/libc++/src/include/__type_traits/is_void.h", "//third_party/libc++/src/include/__type_traits/is_volatile.h", @@ -946,6 +954,7 @@ libcxx_headers = [ "//third_party/libc++/src/include/__vector/vector_bool.h", "//third_party/libc++/src/include/__vector/vector_bool_formatter.h", "//third_party/libc++/src/include/__verbose_abort", + "//third_party/libc++/src/include/__verbose_trap", "//third_party/libc++/src/include/algorithm", "//third_party/libc++/src/include/any", "//third_party/libc++/src/include/array", @@ -1090,6 +1099,4 @@ libcxx_headers = [ "//third_party/libc++/src/include/version", "//third_party/libc++/src/include/wchar.h", "//third_party/libc++/src/include/wctype.h", - - # keep-sorted end ] diff --git a/naiveproxy/src/buildtools/third_party/libc++/modules.gni b/naiveproxy/src/buildtools/third_party/libc++/modules.gni new file mode 100644 index 0000000000..d66d50f55c --- /dev/null +++ b/naiveproxy/src/buildtools/third_party/libc++/modules.gni @@ -0,0 +1,130 @@ +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/c++/modules.gni") +import("//build/config/clang/clang.gni") + +if (is_ios) { + import("//build/config/ios/ios_sdk.gni") + sdk_path = ios_sdk_path +} + +if (is_mac) { + import("//build/config/mac/mac_sdk.gni") + sdk_path = mac_sdk_path +} + +configs_to_add = [ + "//buildtools/third_party/libc++:config", + "//build/config/compiler:no_chromium_code", +] + +configs_to_remove = [ + "//build/config/compiler:chromium_code", + "//build/config/coverage:default_coverage", +] + +if (use_clang_modules) { + template("modulemap") { + source_set(target_name) { + forward_variables_from(invoker, + [ + "deps", + "public_configs", + "public_deps", + ]) + use_libcxx_modules = false + sources = [ invoker.modulemap ] + + # By always including all module maps, we can get it to error out if + # we attempt to include something not in your dependencies. + # Otherwise, it would silently add it to your own AST. + cflags = module_map_flags + configs -= configs_to_remove + configs += configs_to_add + } + } + + # When I change sysroot_features from an alias to a group, it omits + # -fmodule-file for the aliased target from the command-line. + # This seems like it might be a bug in GN, but I'm not waiting for a fix + # before submitting this. + template("alias") { + source_set(target_name) { + public_deps = invoker.actual + use_libcxx_modules = false + } + } + + template("builtin_module") { + # This is a template to build clang builtin's module file. + modulemap(target_name) { + forward_variables_from(invoker, "*") + modulemap = "${clang_base_path}/lib/clang/${clang_version}/include/module.modulemap" + } + } + + template("libcxx_module") { + # This is a template to build libc++'s module file. + modulemap(target_name) { + forward_variables_from(invoker, "*") + modulemap = + "${root_gen_dir}/third_party/libc++/src/include/module.modulemap" + deps = [ + "//buildtools/third_party/libc++:copy_custom_headers", + "//buildtools/third_party/libc++:copy_libcxx_headers", + ] + } + } + + if (is_apple) { + template("DarwinBasic_module") { + modulemap(target_name) { + forward_variables_from(invoker, "*") + modulemap = "$sdk_path/usr/include/DarwinBasic.modulemap" + if (!defined(public_deps)) { + public_deps = [] + } + if (is_ios) { + public_deps += [ ":copy_sysroot_modulemaps($default_toolchain)" ] + } + } + } + template("DarwinFoundation_module") { + modulemap(target_name) { + forward_variables_from(invoker, "*") + modulemap = "$sdk_path/usr/include/DarwinFoundation.modulemap" + if (!defined(public_deps)) { + public_deps = [] + } + if (is_ios) { + public_deps += [ ":copy_sysroot_modulemaps($default_toolchain)" ] + } + } + } + template("c_standard_library_module") { + modulemap(target_name) { + forward_variables_from(invoker, "*") + modulemap = "$sdk_path/usr/include/c_standard_library.modulemap" + if (!defined(public_deps)) { + public_deps = [] + } + if (is_ios) { + public_deps += [ ":copy_sysroot_modulemaps($default_toolchain)" ] + } + } + } + } else { + template("sysroot_module") { + modulemap(target_name) { + forward_variables_from(invoker, "*") + modulemap = sysroot_modulemap + deps = [ + ":copy_custom_headers", + ":copy_libcxx_headers", + ] + } + } + } +} diff --git a/naiveproxy/src/buildtools/third_party/libc++abi/BUILD.gn b/naiveproxy/src/buildtools/third_party/libc++abi/BUILD.gn index 4fb90c9784..c17d627e61 100644 --- a/naiveproxy/src/buildtools/third_party/libc++abi/BUILD.gn +++ b/naiveproxy/src/buildtools/third_party/libc++abi/BUILD.gn @@ -22,7 +22,7 @@ target(libcxxabi_target_type, "libc++abi") { deps += [ "//buildtools/third_party/libunwind" ] } - if (use_libcxx_modules) { + if (use_clang_modules) { deps += [ "//buildtools/third_party/libc++:copy_custom_headers", "//buildtools/third_party/libc++:copy_libcxx_headers", @@ -106,6 +106,10 @@ target(libcxxabi_target_type, "libc++abi") { # libc++abi depends on libc++ internals. include_dirs = [ "//third_party/libc++/src/src" ] + # Disabling -Wexit-time-destructors, as libc++abi uses a static object for + # at exit management (see `static DtorsManager manager`). + configs += [ "//build/config/compiler:no_exit_time_destructors" ] + 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 8089b3d256..e77853a97a 100644 --- a/naiveproxy/src/chrome/VERSION +++ b/naiveproxy/src/chrome/VERSION @@ -1,4 +1,4 @@ -MAJOR=139 +MAJOR=140 MINOR=0 -BUILD=7258 -PATCH=62 +BUILD=7339 +PATCH=123 diff --git a/naiveproxy/src/chrome/android/profiles/newest.txt b/naiveproxy/src/chrome/android/profiles/newest.txt index 623620cbb5..45cd10d324 100644 --- a/naiveproxy/src/chrome/android/profiles/newest.txt +++ b/naiveproxy/src/chrome/android/profiles/newest.txt @@ -1 +1 @@ -chromeos-chrome-amd64-139.0.7258.59_rc-r1-merged.afdo.bz2 +chromeos-chrome-amd64-140.0.7339.100_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 5bbfbb1b59..0b5f505e3e 100644 --- a/naiveproxy/src/chrome/build/android-arm32.pgo.txt +++ b/naiveproxy/src/chrome/build/android-arm32.pgo.txt @@ -1 +1 @@ -chrome-android32-main-1750679862-e8cd39855f71235e44de9c61d7aa97c1164e7b1c-9c39818cb32c6b56caef52d01f475ccf6b096049.profdata +chrome-android32-main-1754308544-6c9fdd52c29e7623172130fc0f5de3ada5060dd6-8f771923c5ae9a6832681bb6441f7779445a972c.profdata diff --git a/naiveproxy/src/chrome/build/android-arm64.pgo.txt b/naiveproxy/src/chrome/build/android-arm64.pgo.txt index 586d898ec3..026b618071 100644 --- a/naiveproxy/src/chrome/build/android-arm64.pgo.txt +++ b/naiveproxy/src/chrome/build/android-arm64.pgo.txt @@ -1 +1 @@ -chrome-android64-7258-1753803638-0eeb0e52f8450d6bf366af03fa038893b0ec450d-329afe5a280c79bdb130234a75b6ec814fa550d3.profdata +chrome-android64-7339-1756848249-3f18e526d8f73f32a6ec7e07625ab7c27d4922b4-85016540b523d8b6da61659b5540e10c08c34bad.profdata diff --git a/naiveproxy/src/chrome/build/android-desktop-arm64.pgo.txt b/naiveproxy/src/chrome/build/android-desktop-arm64.pgo.txt new file mode 100644 index 0000000000..4c1c64fccc --- /dev/null +++ b/naiveproxy/src/chrome/build/android-desktop-arm64.pgo.txt @@ -0,0 +1 @@ +chrome-android-desktop-arm64-main-1754186741-76eb47e4aa79fdc5e1fc41fbe0a9f93787dc9c91-e69c02481d9a10a6fa2c7ff7c98b0eb483c922b6.profdata diff --git a/naiveproxy/src/chrome/build/android-desktop-x64.pgo.txt b/naiveproxy/src/chrome/build/android-desktop-x64.pgo.txt index 9d4a3965b9..06c338c540 100644 --- a/naiveproxy/src/chrome/build/android-desktop-x64.pgo.txt +++ b/naiveproxy/src/chrome/build/android-desktop-x64.pgo.txt @@ -1 +1 @@ -chrome-android-desktop-x64-main-1750643961-35e68d17396f6db2bcbc23dd27892cb6240ae0eb-6f8723a37996015adf9f0973cdaed7a179682c44.profdata +chrome-android-desktop-x64-main-1754308544-414e0d6f021ab98b3b8851addc568cc42f08908d-8f771923c5ae9a6832681bb6441f7779445a972c.profdata diff --git a/naiveproxy/src/chrome/build/linux.pgo.txt b/naiveproxy/src/chrome/build/linux.pgo.txt index 065e543a3c..fcd93a08f5 100644 --- a/naiveproxy/src/chrome/build/linux.pgo.txt +++ b/naiveproxy/src/chrome/build/linux.pgo.txt @@ -1 +1 @@ -chrome-linux-7258-1752969416-a528e01185d141ca77542255592e211024c33d34-b4ba555e3de319acd633d70ccd6c1d01f0460a1c.profdata +chrome-linux-main-1752989296-3dc3c84b1ea64dfbadeca18145c6e823bab3ff87-3a0e503d2bd87771c1e55103ac2a9a7b59a7411b.profdata diff --git a/naiveproxy/src/chrome/build/mac-arm.pgo.txt b/naiveproxy/src/chrome/build/mac-arm.pgo.txt index 3def104744..f76e0b0254 100644 --- a/naiveproxy/src/chrome/build/mac-arm.pgo.txt +++ b/naiveproxy/src/chrome/build/mac-arm.pgo.txt @@ -1 +1 @@ -chrome-mac-arm-7258-1753811959-d7f51a51500b4f6c11ee428c38d73844c4885ef4-bf01cfbec7473f2d6f6cadbb95eb54fbe26daf59.profdata +chrome-mac-arm-7339-1756848249-ed9cb8baeddb344edb6cd72d0eef6a38afe4d447-85016540b523d8b6da61659b5540e10c08c34bad.profdata diff --git a/naiveproxy/src/chrome/build/mac.pgo.txt b/naiveproxy/src/chrome/build/mac.pgo.txt index 49ab5ffb39..9cea966196 100644 --- a/naiveproxy/src/chrome/build/mac.pgo.txt +++ b/naiveproxy/src/chrome/build/mac.pgo.txt @@ -1 +1 @@ -chrome-mac-7258-1753790016-ae36766100a23ba86fedb7fc872c037b0aa198c1-cffc4cb149566a8e113b8244b93d0557ce662ab0.profdata +chrome-mac-7339-1756835008-b642d6d242366625c5cc1192d331f94bc64b2e71-1ed65dc990ea30d64c53cf01c7e21b26bfa80e63.profdata diff --git a/naiveproxy/src/chrome/build/win-arm64.pgo.txt b/naiveproxy/src/chrome/build/win-arm64.pgo.txt index 1e1c084093..98d72d7a3c 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-1750679862-ef1c25bf50297c8fd7dd06bd944b56dd32af749f-9c39818cb32c6b56caef52d01f475ccf6b096049.profdata +chrome-win-arm64-main-1753984643-2d9b0172080dc3c51a908c33cad2e3cf9d619714-739f10b7f26e3db54704550f0cea4efc11e28c37.profdata \ No newline at end of file diff --git a/naiveproxy/src/chrome/build/win32.pgo.txt b/naiveproxy/src/chrome/build/win32.pgo.txt index 26840d9097..8cfe11c686 100644 --- a/naiveproxy/src/chrome/build/win32.pgo.txt +++ b/naiveproxy/src/chrome/build/win32.pgo.txt @@ -1 +1 @@ -chrome-win32-7258-1753746204-7c8038d80adbef813f69efb77954a33cc6166a97-3b1322c35305419327f6e9288401eca5e0c96cd6.profdata +chrome-win32-7339-1756835008-f91201edc384400768926af2b13b6dedd04462d9-1ed65dc990ea30d64c53cf01c7e21b26bfa80e63.profdata diff --git a/naiveproxy/src/chrome/build/win64.pgo.txt b/naiveproxy/src/chrome/build/win64.pgo.txt index f7fbe7351a..4940a9b34c 100644 --- a/naiveproxy/src/chrome/build/win64.pgo.txt +++ b/naiveproxy/src/chrome/build/win64.pgo.txt @@ -1 +1 @@ -chrome-win64-7258-1753790016-741888eb5e8e38d04b278e403852c23debce481e-cffc4cb149566a8e113b8244b93d0557ce662ab0.profdata +chrome-win64-7339-1756835008-2d312b4b7bb945e1e6cdb266a5434c0ec6ab1f97-1ed65dc990ea30d64c53cf01c7e21b26bfa80e63.profdata diff --git a/naiveproxy/src/chrome/version.gni b/naiveproxy/src/chrome/version.gni index 84ad35c21a..7e7c4a838f 100644 --- a/naiveproxy/src/chrome/version.gni +++ b/naiveproxy/src/chrome/version.gni @@ -78,8 +78,7 @@ if (target_os == "android") { "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@\" " + _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@\" " @@ -105,6 +104,12 @@ if (target_os == "android") { "webview_64_beta_version_code = \"@WEBVIEW_64_BETA_VERSION_CODE@\" " _version_dictionary_template += "webview_64_dev_version_code = \"@WEBVIEW_64_DEV_VERSION_CODE@\" " + _version_dictionary_template += "webview_32_64_stable_version_code = \"@WEBVIEW_32_64_STABLE_VERSION_CODE@\" " + _version_dictionary_template += + "webview_64_32_dev_version_code = \"@WEBVIEW_64_32_DEV_VERSION_CODE@\" " + _version_dictionary_template += "webview_64_32_beta_version_code = \"@WEBVIEW_64_32_BETA_VERSION_CODE@\" " + _version_dictionary_template += "webview_64_32_stable_version_code = \"@WEBVIEW_64_32_STABLE_VERSION_CODE@\" " + _version_dictionary_template += "webview_64_32_high_stable_version_code = \"@WEBVIEW_64_32_HIGH_STABLE_VERSION_CODE@\" " } _script_arguments += [ @@ -183,6 +188,11 @@ if (is_mac) { "webview_64_beta_version_code", "webview_64_dev_version_code", "webview_64_stable_version_code", + "webview_32_64_stable_version_code", + "webview_64_32_dev_version_code", + "webview_64_32_beta_version_code", + "webview_64_32_stable_version_code", + "webview_64_32_high_stable_version_code", ]) chrome_version_name = chrome_version_full @@ -192,6 +202,7 @@ if (is_mac) { 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 + webview_64_32_high_stable_version_code = webview_64_32_stable_version_code } } @@ -329,46 +340,53 @@ if (is_android) { } } - # Key: {android_64bit_target_cpu}_{include_64_bit_webview}_{include_32_bit_webview} + # Key: {android_64bit_target_cpu}_{is_64_bit_browser}_{include_64_bit_webview}_{include_32_bit_webview} WEBVIEW_VERSION_MAP = { # 64-bit constants are not generated by version.py on non-64-bit target_cpu. if (android_64bit_target_cpu) { if (defined(android_app_secondary_abi)) { if (android_channel == "dev") { - true_false_true = webview_32_dev_version_code - true_true_false = webview_64_dev_version_code - true_true_true = webview_dev_version_code + true_false_false_true = webview_32_dev_version_code + true_true_true_false = webview_64_dev_version_code + true_false_true_true = webview_dev_version_code + true_true_true_true = webview_64_32_dev_version_code } else if (android_channel == "beta") { - true_false_true = webview_32_beta_version_code - true_true_false = webview_64_beta_version_code - true_true_true = webview_beta_version_code + true_false_false_true = webview_32_beta_version_code + true_true_true_false = webview_64_beta_version_code + true_false_true_true = webview_beta_version_code + true_true_true_true = webview_64_32_beta_version_code } else { - true_false_true = webview_32_stable_version_code - true_true_false = webview_64_stable_version_code - true_true_true = webview_stable_version_code + if (is_high_end_android) { + true_true_true_true = webview_64_32_high_stable_version_code + } else { + true_true_true_true = webview_64_32_stable_version_code + } + true_false_false_true = webview_32_stable_version_code + true_true_true_false = webview_64_stable_version_code + true_false_true_true = webview_stable_version_code } } else { if (android_channel == "dev") { - true_true_false = webview_dev_version_code + true_true_true_false = webview_dev_version_code } else if (android_channel == "beta") { - true_true_false = webview_beta_version_code + true_true_true_false = webview_beta_version_code } else { - true_true_false = webview_stable_version_code + true_true_true_false = webview_stable_version_code } } } else { # !android_64bit_target_cpu if (android_channel == "dev") { - false_false_true = webview_dev_version_code + false_false_false_true = webview_dev_version_code } else if (android_channel == "beta") { - false_false_true = webview_beta_version_code + false_false_false_true = webview_beta_version_code } else { - false_false_true = webview_stable_version_code + false_false_false_true = webview_stable_version_code } } # For system_webview_no_weblayer_apk. - true_false_false = "1" - false_false_false = "1" + true_false_false_false = "1" + false_false_false_false = "1" } } diff --git a/naiveproxy/src/components/nacl/toolchain.gni b/naiveproxy/src/components/nacl/toolchain.gni deleted file mode 100644 index d2bcf656f9..0000000000 --- a/naiveproxy/src/components/nacl/toolchain.gni +++ /dev/null @@ -1,14 +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. - -# To run NaCl on CrOS ARM64, we use a nacl_helper binary which gets built for -# ARM32. is_minimal_toolchain indicates that we are currently building this. -# This is required because the Chrome OS build makes only a minimal set of ARM32 -# libraries available inside an ARM64 build, which means we need to limit the -# (indirect) dependencies of nacl_helper. -# Note that this is different from is_nacl in that we are not actually using a -# nacl toolchain to compile nacl_helper. -# See https://crbug.com/1339021 for more details. -is_minimal_toolchain = - target_cpu == "arm64" && current_cpu == "arm" && (is_chromeos || is_linux) diff --git a/naiveproxy/src/components/network_time/BUILD.gn b/naiveproxy/src/components/network_time/BUILD.gn index 0067c43ee0..f8a339f39b 100644 --- a/naiveproxy/src/components/network_time/BUILD.gn +++ b/naiveproxy/src/components/network_time/BUILD.gn @@ -18,7 +18,7 @@ static_library("network_time") { "//components/prefs", "//components/variations", "//net", - "//services/network/public/cpp:cpp", + "//services/network/public/cpp", ] } diff --git a/naiveproxy/src/components/version_info/BUILD.gn b/naiveproxy/src/components/version_info/BUILD.gn index 37b9bdb5dc..b26d5b7bdd 100644 --- a/naiveproxy/src/components/version_info/BUILD.gn +++ b/naiveproxy/src/components/version_info/BUILD.gn @@ -41,7 +41,7 @@ source_set("version_string") { # Facade for "//base/version_info:channel" source_set("channel") { sources = [ "channel.h" ] - public_deps = [ "//base:base" ] + public_deps = [ "//base" ] } # Facade for "//base/version_info:generate_version_info" diff --git a/naiveproxy/src/components/version_info/android/BUILD.gn b/naiveproxy/src/components/version_info/android/BUILD.gn index 7e1fc2bb31..887034a63f 100644 --- a/naiveproxy/src/components/version_info/android/BUILD.gn +++ b/naiveproxy/src/components/version_info/android/BUILD.gn @@ -6,5 +6,5 @@ import("//build/config/android/rules.gni") static_library("channel_getter") { sources = [ "channel_getter.h" ] - public_deps = [ "//base:base" ] + public_deps = [ "//base" ] } diff --git a/naiveproxy/src/crypto/BUILD.gn b/naiveproxy/src/crypto/BUILD.gn index d40f1a8c2d..0bbbf1ca13 100644 --- a/naiveproxy/src/crypto/BUILD.gn +++ b/naiveproxy/src/crypto/BUILD.gn @@ -3,7 +3,6 @@ # found in the LICENSE file. import("//build/buildflag_header.gni") -import("//components/nacl/toolchain.gni") import("//crypto/features.gni") if (is_ios) { @@ -25,12 +24,6 @@ component("crypto") { "aes_ctr.cc", "aes_ctr.h", "crypto_export.h", - "ec_private_key.cc", - "ec_private_key.h", - "ec_signature_creator.cc", - "ec_signature_creator.h", - "ec_signature_creator_impl.cc", - "ec_signature_creator_impl.h", "evp.cc", "evp.h", "features.cc", @@ -64,8 +57,6 @@ component("crypto") { "sha2.h", "sign.cc", "sign.h", - "signature_creator.cc", - "signature_creator.h", "signature_verifier.cc", "signature_verifier.h", "subtle_passkey.cc", @@ -89,20 +80,20 @@ component("crypto") { if (is_apple) { sources += [ - "apple_keychain.cc", - "apple_keychain.h", - "apple_keychain_secitem.h", - "apple_keychain_secitem.mm", - "apple_keychain_util.h", - "apple_keychain_util.mm", - "apple_keychain_v2.h", - "apple_keychain_v2.mm", + "apple/keychain.cc", + "apple/keychain.h", + "apple/keychain_secitem.h", + "apple/keychain_secitem.mm", + "apple/keychain_util.h", + "apple/keychain_util.mm", + "apple/keychain_v2.h", + "apple/keychain_v2.mm", ] if (is_mac) { sources += [ - "apple_keychain_seckeychain.cc", - "apple_keychain_seckeychain.h", + "apple/keychain_seckeychain.cc", + "apple/keychain_seckeychain.h", "mac_security_services_lock.cc", "mac_security_services_lock.h", "scoped_lacontext.h", @@ -149,11 +140,10 @@ component("crypto") { "nss_util.h", "nss_util_internal.h", ] - deps += [ "//components/nacl/common:buildflags" ] configs += [ "//build/config/linux/nss" ] } - if (is_chromeos && !is_minimal_toolchain) { + if (is_chromeos) { sources += [ "chaps_support.cc", "chaps_support.h", diff --git a/naiveproxy/src/crypto/DEPS b/naiveproxy/src/crypto/DEPS index 2dc13cc79d..b74c2ae474 100644 --- a/naiveproxy/src/crypto/DEPS +++ b/naiveproxy/src/crypto/DEPS @@ -1,5 +1,4 @@ include_rules = [ - "+components/nacl/common/buildflags.h", "+third_party/boringssl/src/include", ] new_usages_require_review = True diff --git a/naiveproxy/src/crypto/README.md b/naiveproxy/src/crypto/README.md index fcaa662390..47a1583fb9 100644 --- a/naiveproxy/src/crypto/README.md +++ b/naiveproxy/src/crypto/README.md @@ -26,3 +26,28 @@ This directory is actively being refactored as of 2025-06. See Many interfaces in this directory are deprecated and being changed or removed; check the comment at the top of the header file before using them. + +## Advice For Clients + +* Ciphertext, keys, certificates, and other cryptographic material are generally + sequences of bytes, not characters, so prefer using byte-oriented types to + represent them: `vector`, `array`, and `span` + rather than `string` and `string_view`. +* To serialize private keys, use `keypair::PrivateKey::ToPrivateKeyInfo()`, + which returns a [PKCS#8][pkcs8] PrivateKeyInfo structure serialized as a + byte vector. To unserialize keys in this format, use + `keypair::PrivateKey::FromPrivateKeyInfo()`. +* To serialize public keys, use `keypair::PublicKey::ToSubjectPublicKeyInfo()` + or `keypair::PrivateKey::ToSubjectPublicKeyInfo()`, which return a + [X.509][x509] SubjectPublicKeyInfo structure serialized as a byte vector. To + unserialize public keys in this format, use + `keypair::PublicKey::FromPublicKeyInfo()`. +* SubjectPublicKeyInfo and PrivateKeyInfo can represent many kinds of keys, so + code that expects a specific kind of key must check the kind after + deserialization. +* To serialize symmetric keys (AEAD, HMAC, or symmetric encryption keys), use a + raw sequence of bytes for the key material. Represent these keys in memory + using `vector`, `array`, or `span` directly. + +[pkcs8]: https://datatracker.ietf.org/doc/html/rfc5208 +[x509]: https://datatracker.ietf.org/doc/html/rfc5280 diff --git a/naiveproxy/src/crypto/fake_apple_keychain_v2.h b/naiveproxy/src/crypto/apple/fake_keychain_v2.h similarity index 69% rename from naiveproxy/src/crypto/fake_apple_keychain_v2.h rename to naiveproxy/src/crypto/apple/fake_keychain_v2.h index f307965d56..c3d43823c5 100644 --- a/naiveproxy/src/crypto/fake_apple_keychain_v2.h +++ b/naiveproxy/src/crypto/apple/fake_keychain_v2.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 CRYPTO_FAKE_APPLE_KEYCHAIN_V2_H_ -#define CRYPTO_FAKE_APPLE_KEYCHAIN_V2_H_ +#ifndef CRYPTO_APPLE_FAKE_KEYCHAIN_V2_H_ +#define CRYPTO_APPLE_FAKE_KEYCHAIN_V2_H_ #import @@ -11,24 +11,24 @@ #include #include "base/apple/scoped_cftyperef.h" -#include "crypto/apple_keychain_v2.h" +#include "crypto/apple/keychain_v2.h" +#include "crypto/apple/scoped_fake_keychain_v2.h" #include "crypto/crypto_export.h" -#include "crypto/scoped_fake_apple_keychain_v2.h" -namespace crypto { +namespace crypto::apple { -// FakeAppleKeychainV2 is an implementation of AppleKeychainV2 for testing. It -// works around behavior that can't be relied on in tests, such as writing to -// the actual Keychain or using functionality that requires code-signed, -// entitled builds. -class CRYPTO_EXPORT FakeAppleKeychainV2 : public AppleKeychainV2 { +// FakeKeychainV2 is an implementation of KeychainV2 for testing. It works +// around behavior that can't be relied on in tests, such as writing to the +// actual Keychain or using functionality that requires code-signed, entitled +// builds. +class CRYPTO_EXPORT FakeKeychainV2 : public KeychainV2 { public: - using UVMethod = ScopedFakeAppleKeychainV2::UVMethod; + using UVMethod = ScopedFakeKeychainV2::UVMethod; - explicit FakeAppleKeychainV2(const std::string& keychain_access_group); - FakeAppleKeychainV2(const FakeAppleKeychainV2&) = delete; - FakeAppleKeychainV2& operator=(const FakeAppleKeychainV2&) = delete; - ~FakeAppleKeychainV2() override; + explicit FakeKeychainV2(const std::string& keychain_access_group); + FakeKeychainV2(const FakeKeychainV2&) = delete; + FakeKeychainV2& operator=(const FakeKeychainV2&) = delete; + ~FakeKeychainV2() override; const std::vector>& items() { return items_; @@ -40,7 +40,7 @@ class CRYPTO_EXPORT FakeAppleKeychainV2 : public AppleKeychainV2 { void set_uv_method(UVMethod uv_method) { uv_method_ = uv_method; } - // AppleKeychainV2: + // KeychainV2: NSArray* GetTokenIDs() override; base::apple::ScopedCFTypeRef KeyCreateRandomKey( CFDictionaryRef params, @@ -75,6 +75,6 @@ class CRYPTO_EXPORT FakeAppleKeychainV2 : public AppleKeychainV2 { base::apple::ScopedCFTypeRef keychain_access_group_; }; -} // namespace crypto +} // namespace crypto::apple -#endif // CRYPTO_FAKE_APPLE_KEYCHAIN_V2_H_ +#endif // CRYPTO_APPLE_FAKE_KEYCHAIN_V2_H_ diff --git a/naiveproxy/src/crypto/fake_apple_keychain_v2.mm b/naiveproxy/src/crypto/apple/fake_keychain_v2.mm similarity index 91% rename from naiveproxy/src/crypto/fake_apple_keychain_v2.mm rename to naiveproxy/src/crypto/apple/fake_keychain_v2.mm index 72601fd9de..2edf8012bf 100644 --- a/naiveproxy/src/crypto/fake_apple_keychain_v2.mm +++ b/naiveproxy/src/crypto/apple/fake_keychain_v2.mm @@ -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 "crypto/fake_apple_keychain_v2.h" +#include "crypto/apple/fake_keychain_v2.h" #import #import @@ -20,19 +20,18 @@ #include "base/memory/scoped_policy.h" #include "base/notimplemented.h" #include "base/strings/sys_string_conversions.h" -#include "crypto/apple_keychain_v2.h" +#include "crypto/apple/keychain_v2.h" #if defined(LEAK_SANITIZER) #include #endif -namespace crypto { +namespace crypto::apple { -FakeAppleKeychainV2::FakeAppleKeychainV2( - const std::string& keychain_access_group) +FakeKeychainV2::FakeKeychainV2(const std::string& keychain_access_group) : keychain_access_group_( base::SysUTF8ToCFStringRef(keychain_access_group)) {} -FakeAppleKeychainV2::~FakeAppleKeychainV2() { +FakeKeychainV2::~FakeKeychainV2() { // Avoid shutdown leak of error string in Security.framework. // See // https://github.com/apple-oss-distributions/Security/blob/Security-60158.140.3/OSX/libsecurity_keychain/lib/SecBase.cpp#L88 @@ -41,14 +40,14 @@ FakeAppleKeychainV2::~FakeAppleKeychainV2() { #endif } -NSArray* FakeAppleKeychainV2::GetTokenIDs() { +NSArray* FakeKeychainV2::GetTokenIDs() { if (is_secure_enclave_available_) { return @[ base::apple::CFToNSPtrCast(kSecAttrTokenIDSecureEnclave) ]; } return @[]; } -base::apple::ScopedCFTypeRef FakeAppleKeychainV2::KeyCreateRandomKey( +base::apple::ScopedCFTypeRef FakeKeychainV2::KeyCreateRandomKey( CFDictionaryRef params, CFErrorRef* error) { // Validate certain fields that we always expect to be set. @@ -129,8 +128,8 @@ base::apple::ScopedCFTypeRef FakeAppleKeychainV2::KeyCreateRandomKey( return private_key; } -base::apple::ScopedCFTypeRef -FakeAppleKeychainV2::KeyCopyAttributes(SecKeyRef key) { +base::apple::ScopedCFTypeRef FakeKeychainV2::KeyCopyAttributes( + SecKeyRef key) { const auto& it = std::ranges::find_if(items_, [&key](const auto& item) { return CFEqual(key, CFDictionaryGetValue(item.get(), kSecValueRef)); }); @@ -145,8 +144,8 @@ FakeAppleKeychainV2::KeyCopyAttributes(SecKeyRef key) { return result; } -OSStatus FakeAppleKeychainV2::ItemAdd(CFDictionaryRef attributes, - CFTypeRef* result) { +OSStatus FakeKeychainV2::ItemAdd(CFDictionaryRef attributes, + CFTypeRef* result) { CFStringRef keychain_access_group = base::apple::GetValueFromDictionary(attributes, kSecAttrAccessGroup); @@ -159,8 +158,8 @@ OSStatus FakeAppleKeychainV2::ItemAdd(CFDictionaryRef attributes, return errSecSuccess; } -OSStatus FakeAppleKeychainV2::ItemCopyMatching(CFDictionaryRef query, - CFTypeRef* result) { +OSStatus FakeKeychainV2::ItemCopyMatching(CFDictionaryRef query, + CFTypeRef* result) { // In practice we don't need to care about limit queries, or leaving out the // SecKeyRef or attributes from the result set. DCHECK_EQ( @@ -239,7 +238,7 @@ OSStatus FakeAppleKeychainV2::ItemCopyMatching(CFDictionaryRef query, return errSecSuccess; } -OSStatus FakeAppleKeychainV2::ItemDelete(CFDictionaryRef query) { +OSStatus FakeKeychainV2::ItemDelete(CFDictionaryRef query) { // Validate certain fields that we always expect to be set. DCHECK_EQ(base::apple::GetValueFromDictionary(query, kSecClass), kSecClassKey); @@ -266,8 +265,8 @@ OSStatus FakeAppleKeychainV2::ItemDelete(CFDictionaryRef query) { return errSecItemNotFound; } -OSStatus FakeAppleKeychainV2::ItemUpdate(CFDictionaryRef query, - CFDictionaryRef attributes_to_update) { +OSStatus FakeKeychainV2::ItemUpdate(CFDictionaryRef query, + CFDictionaryRef attributes_to_update) { DCHECK_EQ(base::apple::GetValueFromDictionary(query, kSecClass), kSecClassKey); DCHECK(CFEqual(base::apple::GetValueFromDictionary( @@ -299,9 +298,9 @@ OSStatus FakeAppleKeychainV2::ItemUpdate(CFDictionaryRef query, #if !BUILDFLAG(IS_IOS) base::apple::ScopedCFTypeRef -FakeAppleKeychainV2::TaskCopyValueForEntitlement(SecTaskRef task, - CFStringRef entitlement, - CFErrorRef* error) { +FakeKeychainV2::TaskCopyValueForEntitlement(SecTaskRef task, + CFStringRef entitlement, + CFErrorRef* error) { CHECK(task); CHECK(CFEqual(entitlement, base::SysUTF8ToCFStringRef("keychain-access-groups").get())) @@ -317,7 +316,7 @@ FakeAppleKeychainV2::TaskCopyValueForEntitlement(SecTaskRef task, #endif // !BUILDFLAG(IS_IOS) #if !BUILDFLAG(IS_IOS_TVOS) -BOOL FakeAppleKeychainV2::LAContextCanEvaluatePolicy( +BOOL FakeKeychainV2::LAContextCanEvaluatePolicy( LAPolicy policy, NSError* __autoreleasing* error) { switch (policy) { @@ -336,4 +335,4 @@ BOOL FakeAppleKeychainV2::LAContextCanEvaluatePolicy( } #endif // !BUILDFLAG(IS_IOS_TVOS) -} // namespace crypto +} // namespace crypto::apple diff --git a/naiveproxy/src/crypto/apple_keychain.cc b/naiveproxy/src/crypto/apple/keychain.cc similarity index 81% rename from naiveproxy/src/crypto/apple_keychain.cc rename to naiveproxy/src/crypto/apple/keychain.cc index e0662f78e0..8dbc87e580 100644 --- a/naiveproxy/src/crypto/apple_keychain.cc +++ b/naiveproxy/src/crypto/apple/keychain.cc @@ -2,20 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "crypto/apple_keychain.h" +#include "crypto/apple/keychain.h" #include #include "base/feature_list.h" #include "build/build_config.h" -#include "crypto/apple_keychain_secitem.h" +#include "crypto/apple/keychain_secitem.h" #include "third_party/abseil-cpp/absl/cleanup/cleanup.h" #if BUILDFLAG(IS_MAC) -#include "crypto/apple_keychain_seckeychain.h" +#include "crypto/apple/keychain_seckeychain.h" #endif -namespace crypto { +namespace crypto::apple { #if BUILDFLAG(IS_MAC) BASE_FEATURE(kAppleKeychainUseSecItem, @@ -24,20 +24,20 @@ BASE_FEATURE(kAppleKeychainUseSecItem, #endif // static -std::unique_ptr AppleKeychain::DefaultKeychain() { +std::unique_ptr Keychain::DefaultKeychain() { #if BUILDFLAG(IS_MAC) if (base::FeatureList::IsEnabled(kAppleKeychainUseSecItem)) { - return std::make_unique(); + return std::make_unique(); } - return std::make_unique(); + return std::make_unique(); #else - return std::make_unique(); + return std::make_unique(); #endif } -AppleKeychain::AppleKeychain() = default; -AppleKeychain::~AppleKeychain() = default; +Keychain::Keychain() = default; +Keychain::~Keychain() = default; #if BUILDFLAG(IS_MAC) @@ -89,4 +89,4 @@ ScopedKeychainUserInteractionAllowed::~ScopedKeychainUserInteractionAllowed() { #endif // BUILDFLAG(IS_MAC) -} // namespace crypto +} // namespace crypto::apple diff --git a/naiveproxy/src/crypto/apple_keychain.h b/naiveproxy/src/crypto/apple/keychain.h similarity index 87% rename from naiveproxy/src/crypto/apple_keychain.h rename to naiveproxy/src/crypto/apple/keychain.h index 605a6db7fd..2438c3947f 100644 --- a/naiveproxy/src/crypto/apple_keychain.h +++ b/naiveproxy/src/crypto/apple/keychain.h @@ -16,9 +16,9 @@ #include "build/build_config.h" #include "crypto/crypto_export.h" -namespace crypto { +namespace crypto::apple { -// DEPRECATED: use `AppleKeychainV2` instead. +// DEPRECATED: use `KeychainV2` instead. // Wraps the KeychainServices API in a very thin layer, to allow it to be // mocked out for testing. @@ -26,20 +26,20 @@ namespace crypto { // through directly to their Keychain Services equivalents (Foo -> // SecKeychainFoo). // -// New code should use AppleKeychainV2. -class CRYPTO_EXPORT AppleKeychain { +// New code should use KeychainV2. +class CRYPTO_EXPORT Keychain { public: // Returns an object suitable for accessing the platform's default type of // keychain. // // On macOS, this will access the default file-based keychain. On // iOS, this will access the application's data protection keychain. - static std::unique_ptr DefaultKeychain(); + static std::unique_ptr DefaultKeychain(); - AppleKeychain(const AppleKeychain&) = delete; - AppleKeychain& operator=(const AppleKeychain&) = delete; + Keychain(const Keychain&) = delete; + Keychain& operator=(const Keychain&) = delete; - virtual ~AppleKeychain(); + virtual ~Keychain(); // Note that even though OSStatus has a noError value, that can never be // returned in the OSStatus arm of FindGenericPassword() - in that case, the @@ -54,7 +54,7 @@ class CRYPTO_EXPORT AppleKeychain { base::span password) const = 0; protected: - AppleKeychain(); + Keychain(); }; #if BUILDFLAG(IS_MAC) @@ -85,6 +85,6 @@ class CRYPTO_EXPORT ScopedKeychainUserInteractionAllowed { #endif // BUILDFLAG(IS_MAC) -} // namespace crypto +} // namespace crypto::apple #endif // CRYPTO_APPLE_KEYCHAIN_H_ diff --git a/naiveproxy/src/crypto/apple_keychain_secitem.h b/naiveproxy/src/crypto/apple/keychain_secitem.h similarity index 69% rename from naiveproxy/src/crypto/apple_keychain_secitem.h rename to naiveproxy/src/crypto/apple/keychain_secitem.h index 1632c22c66..eb74282ada 100644 --- a/naiveproxy/src/crypto/apple_keychain_secitem.h +++ b/naiveproxy/src/crypto/apple/keychain_secitem.h @@ -5,15 +5,15 @@ #ifndef CRYPTO_APPLE_KEYCHAIN_SECITEM_H_ #define CRYPTO_APPLE_KEYCHAIN_SECITEM_H_ -#include "crypto/apple_keychain.h" +#include "crypto/apple/keychain.h" -namespace crypto { +namespace crypto::apple { -// An implementation of AppleKeychain on top of the SecItem API. -class CRYPTO_EXPORT AppleKeychainSecItem : public AppleKeychain { +// An implementation of Keychain on top of the SecItem API. +class CRYPTO_EXPORT KeychainSecItem : public Keychain { public: - AppleKeychainSecItem(); - ~AppleKeychainSecItem() override; + KeychainSecItem(); + ~KeychainSecItem() override; base::expected, OSStatus> FindGenericPassword( std::string_view service_name, @@ -25,6 +25,6 @@ class CRYPTO_EXPORT AppleKeychainSecItem : public AppleKeychain { base::span password) const override; }; -} // namespace crypto +} // namespace crypto::apple #endif // CRYPTO_APPLE_KEYCHAIN_SECITEM_H_ diff --git a/naiveproxy/src/crypto/apple_keychain_secitem.mm b/naiveproxy/src/crypto/apple/keychain_secitem.mm similarity index 51% rename from naiveproxy/src/crypto/apple_keychain_secitem.mm rename to naiveproxy/src/crypto/apple/keychain_secitem.mm index 12b400a1f2..d2b9526f9a 100644 --- a/naiveproxy/src/crypto/apple_keychain_secitem.mm +++ b/naiveproxy/src/crypto/apple/keychain_secitem.mm @@ -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 "crypto/apple_keychain_secitem.h" +#include "crypto/apple/keychain_secitem.h" #import @@ -11,6 +11,7 @@ #include "base/apple/scoped_cftyperef.h" #include "base/containers/to_vector.h" #include "base/strings/sys_string_conversions.h" +#include "crypto/features.h" using base::apple::CFToNSPtrCast; using base::apple::NSToCFOwnershipCast; @@ -36,6 +37,7 @@ base::apple::ScopedCFTypeRef MakeGenericPasswordQuery( // Use the proper search constants, return only the data of the first match. CFToNSPtrCast(kSecMatchLimit) : CFToNSPtrCast(kSecMatchLimitOne), CFToNSPtrCast(kSecReturnData) : @YES, + CFToNSPtrCast(kSecReturnAttributes) : @YES, }; return base::apple::ScopedCFTypeRef( NSToCFOwnershipCast(query)); @@ -60,6 +62,19 @@ base::apple::ScopedCFTypeRef MakeKeychainData( CFToNSPtrCast(kSecValueData) : password, }; } else { + NSString* attr_accessible; +#if BUILDFLAG(IS_IOS) + if (base::FeatureList::IsEnabled( + crypto::features::kMigrateIOSKeychainAccessibility)) { + // Only allow access after the device has been unlocked once. + attr_accessible = CFToNSPtrCast(kSecAttrAccessibleAfterFirstUnlock); + } else { + // Only allow access while the device is unlocked. + attr_accessible = CFToNSPtrCast(kSecAttrAccessibleWhenUnlocked); + } +#else + attr_accessible = CFToNSPtrCast(kSecAttrAccessibleWhenUnlocked); +#endif // BUILDFLAG(IS_IOS) keychain_data = @{ // Set the password. CFToNSPtrCast(kSecValueData) : password, @@ -67,9 +82,8 @@ base::apple::ScopedCFTypeRef MakeKeychainData( // Set the type of the data. CFToNSPtrCast(kSecClass) : CFToNSPtrCast(kSecClassGenericPassword), - // Only allow access when the device has been unlocked. - CFToNSPtrCast(kSecAttrAccessible) : - CFToNSPtrCast(kSecAttrAccessibleWhenUnlocked), + // Set the accessibility attribute as determined above. + CFToNSPtrCast(kSecAttrAccessible) : attr_accessible, // Set the service name. CFToNSPtrCast(kSecAttrService) : base::SysUTF8ToNSString(serviceName), @@ -83,15 +97,44 @@ base::apple::ScopedCFTypeRef MakeKeychainData( NSToCFOwnershipCast(keychain_data)); } +// Creates a dictionary containing the attributes for an accessibility +// migration. Only used on iOS. +#if BUILDFLAG(IS_IOS) +base::apple::ScopedCFTypeRef MakeAttributeMigrationQuery() { + NSDictionary* query = @{ + CFToNSPtrCast(kSecAttrAccessible) : + CFToNSPtrCast(kSecAttrAccessibleAfterFirstUnlock), + }; + return base::apple::ScopedCFTypeRef( + NSToCFOwnershipCast(query)); +} +#endif // BUILDFLAG(IS_IOS) + +// Creates a dictionary that can be used to update a generic password. Only used +// on iOS. +#if BUILDFLAG(IS_IOS) +base::apple::ScopedCFTypeRef MakeGenericPasswordUpdateQuery( + std::string_view service_name, + std::string_view account_name) { + NSDictionary* query = @{ + CFToNSPtrCast(kSecClass) : CFToNSPtrCast(kSecClassGenericPassword), + CFToNSPtrCast(kSecAttrService) : base::SysUTF8ToNSString(service_name), + CFToNSPtrCast(kSecAttrAccount) : base::SysUTF8ToNSString(account_name), + }; + return base::apple::ScopedCFTypeRef( + NSToCFOwnershipCast(query)); +} +#endif // BUILDFLAG(IS_IOS) + } // namespace -namespace crypto { +namespace crypto::apple { -AppleKeychainSecItem::AppleKeychainSecItem() = default; +KeychainSecItem::KeychainSecItem() = default; -AppleKeychainSecItem::~AppleKeychainSecItem() = default; +KeychainSecItem::~KeychainSecItem() = default; -OSStatus AppleKeychainSecItem::AddGenericPassword( +OSStatus KeychainSecItem::AddGenericPassword( std::string_view service_name, std::string_view account_name, base::span password) const { @@ -117,20 +160,47 @@ OSStatus AppleKeychainSecItem::AddGenericPassword( } base::expected, OSStatus> -AppleKeychainSecItem::FindGenericPassword(std::string_view service_name, - std::string_view account_name) const { +KeychainSecItem::FindGenericPassword(std::string_view service_name, + std::string_view account_name) const { base::apple::ScopedCFTypeRef query = MakeGenericPasswordQuery(service_name, account_name); - // Get the keychain item containing the password. + // Get the keychain item containing the password and attributes. + // When kSecReturnData and kSecReturnAttributes are both true, the result is + // a CFDictionaryRef, but the API returns it as a CFTypeRef. base::apple::ScopedCFTypeRef result; OSStatus status = SecItemCopyMatching(query.get(), result.InitializeInto()); if (status != noErr) { return base::unexpected(status); } - CFDataRef data = base::apple::CFCast(result.get()); - return base::ToVector(base::apple::CFDataToSpan(data)); + CFDictionaryRef result_dict = + base::apple::CFCast(result.get()); + CFDataRef password_data = base::apple::GetValueFromDictionary( + result_dict, kSecValueData); + +#if BUILDFLAG(IS_IOS) + if (base::FeatureList::IsEnabled( + crypto::features::kMigrateIOSKeychainAccessibility)) { + CFStringRef accessibility = + base::apple::GetValueFromDictionary(result_dict, + kSecAttrAccessible); + if (CFStringCompare(accessibility, kSecAttrAccessibleWhenUnlocked, 0) == + kCFCompareEqualTo) { + // The item has the old accessibility attribute, so update it. + base::apple::ScopedCFTypeRef update_query = + MakeGenericPasswordUpdateQuery(service_name, account_name); + base::apple::ScopedCFTypeRef attributes_to_update = + MakeAttributeMigrationQuery(); + status = SecItemUpdate(update_query.get(), attributes_to_update.get()); + // The status of the update is intentionally ignored. The goal is to + // migrate the item on a best-effort basis. If it fails, the item will + // just keep its legacy accessibility attribute. + } + } +#endif // BUILDFLAG(IS_IOS) + + return base::ToVector(base::apple::CFDataToSpan(password_data)); } -} // namespace crypto +} // namespace crypto::apple diff --git a/naiveproxy/src/crypto/apple_keychain_seckeychain.cc b/naiveproxy/src/crypto/apple/keychain_seckeychain.cc similarity index 82% rename from naiveproxy/src/crypto/apple_keychain_seckeychain.cc rename to naiveproxy/src/crypto/apple/keychain_seckeychain.cc index c7f015a410..4ad5acbf29 100644 --- a/naiveproxy/src/crypto/apple_keychain_seckeychain.cc +++ b/naiveproxy/src/crypto/apple/keychain_seckeychain.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 "crypto/apple_keychain_seckeychain.h" +#include "crypto/apple/keychain_seckeychain.h" #include "base/containers/span.h" #include "base/containers/to_vector.h" @@ -17,16 +17,15 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" -namespace crypto { +namespace crypto::apple { -AppleKeychainSecKeychain::AppleKeychainSecKeychain() = default; +KeychainSecKeychain::KeychainSecKeychain() = default; -AppleKeychainSecKeychain::~AppleKeychainSecKeychain() = default; +KeychainSecKeychain::~KeychainSecKeychain() = default; base::expected, OSStatus> -AppleKeychainSecKeychain::FindGenericPassword( - std::string_view service_name, - std::string_view account_name) const { +KeychainSecKeychain::FindGenericPassword(std::string_view service_name, + std::string_view account_name) const { base::AutoLock lock(GetMacSecurityServicesLock()); uint32_t password_length = 0; void* password_data = nullptr; @@ -47,7 +46,7 @@ AppleKeychainSecKeychain::FindGenericPassword( return result; } -OSStatus AppleKeychainSecKeychain::AddGenericPassword( +OSStatus KeychainSecKeychain::AddGenericPassword( std::string_view service_name, std::string_view account_name, base::span password) const { @@ -61,4 +60,4 @@ OSStatus AppleKeychainSecKeychain::AddGenericPassword( #pragma clang diagnostic pop -} // namespace crypto +} // namespace crypto::apple diff --git a/naiveproxy/src/crypto/apple_keychain_seckeychain.h b/naiveproxy/src/crypto/apple/keychain_seckeychain.h similarity index 71% rename from naiveproxy/src/crypto/apple_keychain_seckeychain.h rename to naiveproxy/src/crypto/apple/keychain_seckeychain.h index ecf5e229c8..991b2c8deb 100644 --- a/naiveproxy/src/crypto/apple_keychain_seckeychain.h +++ b/naiveproxy/src/crypto/apple/keychain_seckeychain.h @@ -5,18 +5,18 @@ #ifndef CRYPTO_APPLE_KEYCHAIN_SECKEYCHAIN_H_ #define CRYPTO_APPLE_KEYCHAIN_SECKEYCHAIN_H_ -#include "crypto/apple_keychain.h" +#include "crypto/apple/keychain.h" -namespace crypto { +namespace crypto::apple { -// An implementation of AppleKeychain on top of the deprecated SecKeychain API. +// An implementation of Keychain on top of the deprecated SecKeychain API. // // The underlying API was deprecated as of the macOS 13 SDK. // Removal of its use is tracked in https://crbug.com/1348251 -class CRYPTO_EXPORT AppleKeychainSecKeychain : public AppleKeychain { +class CRYPTO_EXPORT KeychainSecKeychain : public Keychain { public: - AppleKeychainSecKeychain(); - ~AppleKeychainSecKeychain() override; + KeychainSecKeychain(); + ~KeychainSecKeychain() override; base::expected, OSStatus> FindGenericPassword( std::string_view service_name, @@ -28,6 +28,6 @@ class CRYPTO_EXPORT AppleKeychainSecKeychain : public AppleKeychain { base::span password) const override; }; -} // namespace crypto +} // namespace crypto::apple #endif // CRYPTO_APPLE_KEYCHAIN_SECKEYCHAIN_H_ diff --git a/naiveproxy/src/crypto/apple_keychain_util.h b/naiveproxy/src/crypto/apple/keychain_util.h similarity index 92% rename from naiveproxy/src/crypto/apple_keychain_util.h rename to naiveproxy/src/crypto/apple/keychain_util.h index 2ab9f751b2..c7bc0338b9 100644 --- a/naiveproxy/src/crypto/apple_keychain_util.h +++ b/naiveproxy/src/crypto/apple/keychain_util.h @@ -10,7 +10,7 @@ #include "build/build_config.h" #include "crypto/crypto_export.h" -namespace crypto { +namespace crypto::apple { #if !BUILDFLAG(IS_IOS) // Returns whether the main executable is signed with a keychain-access-groups @@ -20,6 +20,6 @@ CRYPTO_EXPORT bool ExecutableHasKeychainAccessGroupEntitlement( const std::string& keychain_access_group); #endif // !BUILDFLAG(IS_IOS) -} // namespace crypto +} // namespace crypto::apple #endif // CRYPTO_APPLE_KEYCHAIN_UTIL_H_ diff --git a/naiveproxy/src/crypto/apple_keychain_util.mm b/naiveproxy/src/crypto/apple/keychain_util.mm similarity index 85% rename from naiveproxy/src/crypto/apple_keychain_util.mm rename to naiveproxy/src/crypto/apple/keychain_util.mm index 74bcf0b131..7124c9c0dd 100644 --- a/naiveproxy/src/crypto/apple_keychain_util.mm +++ b/naiveproxy/src/crypto/apple/keychain_util.mm @@ -2,19 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "crypto/apple_keychain_util.h" - -#include +#include "crypto/apple/keychain_util.h" #import +#include + #include "base/apple/bridging.h" #include "base/apple/foundation_util.h" #include "base/apple/scoped_cftyperef.h" #include "base/strings/sys_string_conversions.h" -#include "crypto/apple_keychain_v2.h" +#include "crypto/apple/keychain_v2.h" -namespace crypto { +namespace crypto::apple { #if !BUILDFLAG(IS_IOS) bool ExecutableHasKeychainAccessGroupEntitlement( @@ -25,7 +25,7 @@ bool ExecutableHasKeychainAccessGroupEntitlement( } base::apple::ScopedCFTypeRef entitlement_value_cftype( - AppleKeychainV2::GetInstance().TaskCopyValueForEntitlement( + KeychainV2::GetInstance().TaskCopyValueForEntitlement( task.get(), CFSTR("keychain-access-groups"), nullptr)); if (!entitlement_value_cftype) { return false; @@ -42,4 +42,4 @@ bool ExecutableHasKeychainAccessGroupEntitlement( } #endif // !BUILDFLAG(IS_IOS) -} // namespace crypto +} // namespace crypto::apple diff --git a/naiveproxy/src/crypto/apple_keychain_v2.h b/naiveproxy/src/crypto/apple/keychain_v2.h similarity index 85% rename from naiveproxy/src/crypto/apple_keychain_v2.h rename to naiveproxy/src/crypto/apple/keychain_v2.h index fd679727ae..27d701f0b7 100644 --- a/naiveproxy/src/crypto/apple_keychain_v2.h +++ b/naiveproxy/src/crypto/apple/keychain_v2.h @@ -9,25 +9,25 @@ #import #import -#include "crypto/crypto_export.h" #include "base/apple/scoped_cftyperef.h" #include "base/no_destructor.h" +#include "crypto/crypto_export.h" #if !BUILDFLAG(IS_IOS_TVOS) #import #endif -namespace crypto { +namespace crypto::apple { -// AppleKeychainV2 wraps iOS-style operations from the macOS Security framework +// KeychainV2 wraps iOS-style operations from the macOS Security framework // to work with keys and keychain items. These functions are grouped here so // they can be mocked out in testing. -class CRYPTO_EXPORT AppleKeychainV2 { +class CRYPTO_EXPORT KeychainV2 { public: - static AppleKeychainV2& GetInstance(); + static KeychainV2& GetInstance(); - AppleKeychainV2(const AppleKeychainV2&) = delete; - AppleKeychainV2& operator=(const AppleKeychainV2&) = delete; + KeychainV2(const KeychainV2&) = delete; + KeychainV2& operator=(const KeychainV2&) = delete; // Wraps the |TKTokenWatcher.tokenIDs| property. virtual NSArray* GetTokenIDs(); @@ -79,21 +79,21 @@ class CRYPTO_EXPORT AppleKeychainV2 { #endif // !BUILDFLAG(IS_IOS_TVOS) protected: - AppleKeychainV2(); - virtual ~AppleKeychainV2(); + KeychainV2(); + virtual ~KeychainV2(); protected: - friend class base::NoDestructor; + friend class base::NoDestructor; friend class ScopedTouchIdTestEnvironment; - friend class ScopedFakeAppleKeychainV2; + friend class ScopedFakeKeychainV2; // Set an override to the singleton instance returned by |GetInstance|. The // caller keeps ownership of the injected keychain and must remove the // override by calling |ClearInstanceOverride| before deleting it. - static void SetInstanceOverride(AppleKeychainV2* keychain); + static void SetInstanceOverride(KeychainV2* keychain); static void ClearInstanceOverride(); }; -} // namespace crypto +} // namespace crypto::apple #endif // CRYPTO_APPLE_KEYCHAIN_V2_H_ diff --git a/naiveproxy/src/crypto/apple_keychain_v2.mm b/naiveproxy/src/crypto/apple/keychain_v2.mm similarity index 51% rename from naiveproxy/src/crypto/apple_keychain_v2.mm rename to naiveproxy/src/crypto/apple/keychain_v2.mm index bb599d1fb5..ecc4fc5b3c 100644 --- a/naiveproxy/src/crypto/apple_keychain_v2.mm +++ b/naiveproxy/src/crypto/apple/keychain_v2.mm @@ -2,54 +2,55 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "crypto/apple/keychain_v2.h" + #import #import -#include "crypto/apple_keychain_v2.h" #include "base/apple/foundation_util.h" #include "base/apple/scoped_cftyperef.h" #include "base/no_destructor.h" -namespace crypto { +namespace crypto::apple { -static AppleKeychainV2* g_keychain_instance_override = nullptr; +static KeychainV2* g_keychain_instance_override = nullptr; // static -AppleKeychainV2& AppleKeychainV2::GetInstance() { +KeychainV2& KeychainV2::GetInstance() { if (g_keychain_instance_override) { return *g_keychain_instance_override; } - static base::NoDestructor k; + static base::NoDestructor k; return *k; } // static -void AppleKeychainV2::SetInstanceOverride(AppleKeychainV2* AppleKeychainV2) { +void KeychainV2::SetInstanceOverride(KeychainV2* KeychainV2) { CHECK(!g_keychain_instance_override); - g_keychain_instance_override = AppleKeychainV2; + g_keychain_instance_override = KeychainV2; } // static -void AppleKeychainV2::ClearInstanceOverride() { +void KeychainV2::ClearInstanceOverride() { CHECK(g_keychain_instance_override); g_keychain_instance_override = nullptr; } -AppleKeychainV2::AppleKeychainV2() = default; -AppleKeychainV2::~AppleKeychainV2() = default; +KeychainV2::KeychainV2() = default; +KeychainV2::~KeychainV2() = default; -NSArray* AppleKeychainV2::GetTokenIDs() { +NSArray* KeychainV2::GetTokenIDs() { return [[TKTokenWatcher alloc] init].tokenIDs; } -base::apple::ScopedCFTypeRef AppleKeychainV2::KeyCreateRandomKey( +base::apple::ScopedCFTypeRef KeychainV2::KeyCreateRandomKey( CFDictionaryRef params, CFErrorRef* error) { return base::apple::ScopedCFTypeRef( SecKeyCreateRandomKey(params, error)); } -base::apple::ScopedCFTypeRef AppleKeychainV2::KeyCreateSignature( +base::apple::ScopedCFTypeRef KeychainV2::KeyCreateSignature( SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef data, @@ -58,59 +59,56 @@ base::apple::ScopedCFTypeRef AppleKeychainV2::KeyCreateSignature( SecKeyCreateSignature(key, algorithm, data, error)); } -base::apple::ScopedCFTypeRef AppleKeychainV2::KeyCopyPublicKey( +base::apple::ScopedCFTypeRef KeychainV2::KeyCopyPublicKey( SecKeyRef key) { return base::apple::ScopedCFTypeRef(SecKeyCopyPublicKey(key)); } base::apple::ScopedCFTypeRef -AppleKeychainV2::KeyCopyExternalRepresentation(SecKeyRef key, - CFErrorRef* error) { +KeychainV2::KeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef* error) { return base::apple::ScopedCFTypeRef( SecKeyCopyExternalRepresentation(key, error)); } -base::apple::ScopedCFTypeRef -AppleKeychainV2::KeyCopyAttributes(SecKeyRef key) { +base::apple::ScopedCFTypeRef KeychainV2::KeyCopyAttributes( + SecKeyRef key) { return base::apple::ScopedCFTypeRef( SecKeyCopyAttributes(key)); } -OSStatus AppleKeychainV2::ItemAdd(CFDictionaryRef attributes, - CFTypeRef* result) { +OSStatus KeychainV2::ItemAdd(CFDictionaryRef attributes, CFTypeRef* result) { return SecItemAdd(attributes, result); } -OSStatus AppleKeychainV2::ItemCopyMatching( - CFDictionaryRef query, CFTypeRef* result) { +OSStatus KeychainV2::ItemCopyMatching(CFDictionaryRef query, + CFTypeRef* result) { return SecItemCopyMatching(query, result); } -OSStatus AppleKeychainV2::ItemDelete(CFDictionaryRef query) { +OSStatus KeychainV2::ItemDelete(CFDictionaryRef query) { return SecItemDelete(query); } -OSStatus AppleKeychainV2::ItemUpdate(CFDictionaryRef query, - CFDictionaryRef keychain_data) { +OSStatus KeychainV2::ItemUpdate(CFDictionaryRef query, + CFDictionaryRef keychain_data) { return SecItemUpdate(query, keychain_data); } #if !BUILDFLAG(IS_IOS) -base::apple::ScopedCFTypeRef -AppleKeychainV2::TaskCopyValueForEntitlement(SecTaskRef task, - CFStringRef entitlement, - CFErrorRef* error) { +base::apple::ScopedCFTypeRef KeychainV2::TaskCopyValueForEntitlement( + SecTaskRef task, + CFStringRef entitlement, + CFErrorRef* error) { return base::apple::ScopedCFTypeRef( SecTaskCopyValueForEntitlement(task, entitlement, error)); } #endif // !BUILDFLAG(IS_IOS) #if !BUILDFLAG(IS_IOS_TVOS) -BOOL AppleKeychainV2::LAContextCanEvaluatePolicy(LAPolicy policy, - NSError** error) { +BOOL KeychainV2::LAContextCanEvaluatePolicy(LAPolicy policy, NSError** error) { LAContext* context = [[LAContext alloc] init]; return [context canEvaluatePolicy:policy error:error]; } #endif // !BUILDFLAG(IS_IOS_TVOS) -} // namespace crypto +} // namespace crypto::apple diff --git a/naiveproxy/src/crypto/mock_apple_keychain.cc b/naiveproxy/src/crypto/apple/mock_keychain.cc similarity index 69% rename from naiveproxy/src/crypto/mock_apple_keychain.cc rename to naiveproxy/src/crypto/apple/mock_keychain.cc index d766dc4129..080806aaf3 100644 --- a/naiveproxy/src/crypto/mock_apple_keychain.cc +++ b/naiveproxy/src/crypto/apple/mock_keychain.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 "crypto/mock_apple_keychain.h" +#include "crypto/apple/mock_keychain.h" #include "base/check_op.h" #include "base/containers/span.h" @@ -14,8 +14,8 @@ namespace { constexpr char kPassword[] = "mock_password"; -// Adds an entry to a local histogram to indicate that the Apple Keychain would -// have been accessed, if this class were not a mock of the Apple Keychain. +// Adds an entry to a local histogram to indicate that the Keychain would have +// been accessed, if this class were not a mock of the Keychain. void IncrementKeychainAccessHistogram() { // This local histogram is accessed by Telemetry to track the number of times // the keychain is accessed, since keychain access is known to be synchronous @@ -25,14 +25,14 @@ void IncrementKeychainAccessHistogram() { } // namespace -namespace crypto { +namespace crypto::apple { -MockAppleKeychain::MockAppleKeychain() = default; -MockAppleKeychain::~MockAppleKeychain() = default; +MockKeychain::MockKeychain() = default; +MockKeychain::~MockKeychain() = default; base::expected, OSStatus> -MockAppleKeychain::FindGenericPassword(std::string_view service_name, - std::string_view account_name) const { +MockKeychain::FindGenericPassword(std::string_view service_name, + std::string_view account_name) const { IncrementKeychainAccessHistogram(); // When simulating |noErr|, return canned |passwordData| and @@ -44,7 +44,7 @@ MockAppleKeychain::FindGenericPassword(std::string_view service_name, return base::unexpected(find_generic_result_); } -OSStatus MockAppleKeychain::AddGenericPassword( +OSStatus MockKeychain::AddGenericPassword( std::string_view service_name, std::string_view account_name, base::span password) const { @@ -56,9 +56,9 @@ OSStatus MockAppleKeychain::AddGenericPassword( return noErr; } -std::string MockAppleKeychain::GetEncryptionPassword() const { +std::string MockKeychain::GetEncryptionPassword() const { IncrementKeychainAccessHistogram(); return kPassword; } -} // namespace crypto +} // namespace crypto::apple diff --git a/naiveproxy/src/crypto/mock_apple_keychain.h b/naiveproxy/src/crypto/apple/mock_keychain.h similarity index 72% rename from naiveproxy/src/crypto/mock_apple_keychain.h rename to naiveproxy/src/crypto/apple/mock_keychain.h index fd903e64c7..40fb4e1f75 100644 --- a/naiveproxy/src/crypto/mock_apple_keychain.h +++ b/naiveproxy/src/crypto/apple/mock_keychain.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 CRYPTO_MOCK_APPLE_KEYCHAIN_H_ -#define CRYPTO_MOCK_APPLE_KEYCHAIN_H_ +#ifndef CRYPTO_APPLE_MOCK_KEYCHAIN_H_ +#define CRYPTO_APPLE_MOCK_KEYCHAIN_H_ #include #include @@ -15,27 +15,26 @@ #include "base/compiler_specific.h" #include "build/build_config.h" -#include "crypto/apple_keychain.h" +#include "crypto/apple/keychain.h" -namespace crypto { +namespace crypto::apple { // Mock Keychain wrapper for testing code that interacts with the OS X // Keychain. // // Note that "const" is pretty much meaningless for this class; the const-ness -// of AppleKeychain doesn't apply to the actual keychain data, so all of the -// Mock data is mutable; don't assume that it won't change over the life of -// tests. -class CRYPTO_EXPORT MockAppleKeychain : public AppleKeychain { +// of Keychain doesn't apply to the actual keychain data, so all of the Mock +// data is mutable; don't assume that it won't change over the life of tests. +class CRYPTO_EXPORT MockKeychain : public Keychain { public: - MockAppleKeychain(); + MockKeychain(); - MockAppleKeychain(const MockAppleKeychain&) = delete; - MockAppleKeychain& operator=(const MockAppleKeychain&) = delete; + MockKeychain(const MockKeychain&) = delete; + MockKeychain& operator=(const MockKeychain&) = delete; - ~MockAppleKeychain() override; + ~MockKeychain() override; - // AppleKeychain implementation. + // Keychain implementation. base::expected, OSStatus> FindGenericPassword( std::string_view service_name, std::string_view account_name) const override; @@ -68,6 +67,6 @@ class CRYPTO_EXPORT MockAppleKeychain : public AppleKeychain { mutable bool called_add_generic_ = false; }; -} // namespace crypto +} // namespace crypto::apple -#endif // CRYPTO_MOCK_APPLE_KEYCHAIN_H_ +#endif // CRYPTO_APPLE_MOCK_KEYCHAIN_H_ diff --git a/naiveproxy/src/crypto/apple/scoped_fake_keychain_v2.h b/naiveproxy/src/crypto/apple/scoped_fake_keychain_v2.h new file mode 100644 index 0000000000..7987b61152 --- /dev/null +++ b/naiveproxy/src/crypto/apple/scoped_fake_keychain_v2.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 CRYPTO_APPLE_SCOPED_FAKE_KEYCHAIN_V2_H_ +#define CRYPTO_APPLE_SCOPED_FAKE_KEYCHAIN_V2_H_ + +#include +#include + +#include "crypto/crypto_export.h" + +namespace crypto::apple { + +class FakeKeychainV2; + +// ScopedFakeKeychainV2 installs itself as testing override for +// `KeychainV2::GetInstance()`. +class CRYPTO_EXPORT ScopedFakeKeychainV2 { + public: + // Supported types of user verification, reported by + // LAContextCanEvaluatePolicy. + enum class UVMethod { + kNone, + kPasswordOnly, + kBiometrics, + }; + + explicit ScopedFakeKeychainV2(const std::string& keychain_access_group); + ~ScopedFakeKeychainV2(); + + FakeKeychainV2* keychain() { return keychain_.get(); } + + void SetUVMethod(UVMethod uv_method); + + private: + std::unique_ptr keychain_; +}; + +} // namespace crypto::apple + +#endif // CRYPTO_APPLE_SCOPED_FAKE_KEYCHAIN_V2_H_ diff --git a/naiveproxy/src/crypto/apple/scoped_fake_keychain_v2.mm b/naiveproxy/src/crypto/apple/scoped_fake_keychain_v2.mm new file mode 100644 index 0000000000..a6c7e29b8d --- /dev/null +++ b/naiveproxy/src/crypto/apple/scoped_fake_keychain_v2.mm @@ -0,0 +1,27 @@ +// 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 "crypto/apple/scoped_fake_keychain_v2.h" + +#include + +#include "crypto/apple/fake_keychain_v2.h" + +namespace crypto::apple { + +ScopedFakeKeychainV2::ScopedFakeKeychainV2( + const std::string& keychain_access_group) + : keychain_(std::make_unique(keychain_access_group)) { + KeychainV2::SetInstanceOverride(keychain_.get()); +} + +ScopedFakeKeychainV2::~ScopedFakeKeychainV2() { + KeychainV2::ClearInstanceOverride(); +} + +void ScopedFakeKeychainV2::SetUVMethod(UVMethod uv_method) { + keychain_->set_uv_method(uv_method); +} + +} // namespace crypto::apple diff --git a/naiveproxy/src/crypto/ec_private_key.cc b/naiveproxy/src/crypto/ec_private_key.cc deleted file mode 100644 index 056ae2ac64..0000000000 --- a/naiveproxy/src/crypto/ec_private_key.cc +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2012 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/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - -#include "crypto/ec_private_key.h" - -#include -#include - -#include -#include - -#include "base/check_op.h" -#include "crypto/openssl_util.h" -#include "third_party/boringssl/src/include/openssl/bytestring.h" -#include "third_party/boringssl/src/include/openssl/ec.h" -#include "third_party/boringssl/src/include/openssl/ec_key.h" -#include "third_party/boringssl/src/include/openssl/evp.h" -#include "third_party/boringssl/src/include/openssl/mem.h" -#include "third_party/boringssl/src/include/openssl/pkcs8.h" - -namespace crypto { - -ECPrivateKey::~ECPrivateKey() = default; - -// static -std::unique_ptr ECPrivateKey::Create() { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - - bssl::UniquePtr ec_key( - EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); - if (!ec_key || !EC_KEY_generate_key(ec_key.get())) - return nullptr; - - std::unique_ptr result(new ECPrivateKey()); - result->key_.reset(EVP_PKEY_new()); - if (!result->key_ || !EVP_PKEY_set1_EC_KEY(result->key_.get(), ec_key.get())) - return nullptr; - - CHECK_EQ(EVP_PKEY_EC, EVP_PKEY_id(result->key_.get())); - return result; -} - -// static -std::unique_ptr ECPrivateKey::CreateFromPrivateKeyInfo( - base::span input) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - - CBS cbs; - CBS_init(&cbs, input.data(), input.size()); - bssl::UniquePtr pkey(EVP_parse_private_key(&cbs)); - if (!pkey || CBS_len(&cbs) != 0 || EVP_PKEY_id(pkey.get()) != EVP_PKEY_EC) - return nullptr; - - std::unique_ptr result(new ECPrivateKey()); - result->key_ = std::move(pkey); - return result; -} - -// static -std::unique_ptr ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( - base::span encrypted_private_key_info) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - - CBS cbs; - CBS_init(&cbs, encrypted_private_key_info.data(), - encrypted_private_key_info.size()); - bssl::UniquePtr pkey( - PKCS8_parse_encrypted_private_key(&cbs, "", 0)); - - // Hack for reading keys generated by an older version of the OpenSSL code. - // Some implementations encode the empty password as "\0\0" (passwords are - // normally encoded in big-endian UCS-2 with a NUL terminator) and some - // encode as the empty string. PKCS8_parse_encrypted_private_key - // distinguishes the two by whether the password is nullptr. - if (!pkey) { - CBS_init(&cbs, encrypted_private_key_info.data(), - encrypted_private_key_info.size()); - pkey.reset(PKCS8_parse_encrypted_private_key(&cbs, nullptr, 0)); - } - - if (!pkey || CBS_len(&cbs) != 0 || EVP_PKEY_id(pkey.get()) != EVP_PKEY_EC) - return nullptr; - - std::unique_ptr result(new ECPrivateKey()); - result->key_ = std::move(pkey); - return result; -} - -std::unique_ptr ECPrivateKey::Copy() const { - std::unique_ptr copy(new ECPrivateKey()); - copy->key_ = bssl::UpRef(key_); - return copy; -} - -bool ECPrivateKey::ExportPrivateKey(std::vector* output) const { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - uint8_t* der; - size_t der_len; - bssl::ScopedCBB cbb; - if (!CBB_init(cbb.get(), 0) || - !EVP_marshal_private_key(cbb.get(), key_.get()) || - !CBB_finish(cbb.get(), &der, &der_len)) { - return false; - } - output->assign(der, der + der_len); - OPENSSL_free(der); - return true; -} - -bool ECPrivateKey::ExportPublicKey(std::vector* output) const { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - uint8_t* der; - size_t der_len; - bssl::ScopedCBB cbb; - if (!CBB_init(cbb.get(), 0) || - !EVP_marshal_public_key(cbb.get(), key_.get()) || - !CBB_finish(cbb.get(), &der, &der_len)) { - return false; - } - output->assign(der, der + der_len); - OPENSSL_free(der); - return true; -} - -bool ECPrivateKey::ExportRawPublicKey(std::string* output) const { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - - std::array buf; - EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key_.get()); - if (!EC_POINT_point2oct(EC_KEY_get0_group(ec_key), - EC_KEY_get0_public_key(ec_key), - POINT_CONVERSION_UNCOMPRESSED, buf.data(), buf.size(), - /*ctx=*/nullptr)) { - return false; - } - - output->assign(buf.begin(), buf.end()); - return true; -} - -ECPrivateKey::ECPrivateKey() = default; - -} // namespace crypto diff --git a/naiveproxy/src/crypto/ec_private_key.h b/naiveproxy/src/crypto/ec_private_key.h deleted file mode 100644 index 386eb5a3d4..0000000000 --- a/naiveproxy/src/crypto/ec_private_key.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// This interface is deprecated and being removed: https://crbug.com/425863216. -// New users should use crypto/keypair instead. - -#ifndef CRYPTO_EC_PRIVATE_KEY_H_ -#define CRYPTO_EC_PRIVATE_KEY_H_ - -#include -#include - -#include -#include -#include - -#include "base/containers/span.h" -#include "build/build_config.h" -#include "crypto/crypto_export.h" -#include "third_party/boringssl/src/include/openssl/base.h" - -namespace crypto { - -// Encapsulates an elliptic curve (EC) private key. Can be used to generate new -// keys, export keys to other formats, or to extract a public key. -// TODO(https://crbug.com/425863216): Delete this. -class CRYPTO_EXPORT ECPrivateKey { - public: - ECPrivateKey(const ECPrivateKey&) = delete; - ECPrivateKey& operator=(const ECPrivateKey&) = delete; - - ~ECPrivateKey(); - - // Creates a new random instance. Can return nullptr if initialization fails. - // The created key will use the NIST P-256 curve. - static std::unique_ptr Create(); - - // Create a new instance by importing an existing private key. The format is - // an ASN.1-encoded PrivateKeyInfo block from PKCS #8. This can return - // nullptr if initialization fails. - static std::unique_ptr CreateFromPrivateKeyInfo( - base::span input); - - // Creates a new instance by importing an existing key pair. - // The key pair is given as an ASN.1-encoded PKCS #8 EncryptedPrivateKeyInfo - // block with empty password and an X.509 SubjectPublicKeyInfo block. - // Returns nullptr if initialization fails. - // - // This function is deprecated. Use CreateFromPrivateKeyInfo for new code. - // See https://crbug.com/603319. - static std::unique_ptr CreateFromEncryptedPrivateKeyInfo( - base::span encrypted_private_key_info); - - // Returns a copy of the object. - std::unique_ptr Copy() const; - - EVP_PKEY* key() const { return key_.get(); } - - // Exports the private key to a PKCS #8 PrivateKeyInfo block. - bool ExportPrivateKey(std::vector* output) const; - - // Exports the public key to an X.509 SubjectPublicKeyInfo block. - bool ExportPublicKey(std::vector* output) const; - - // Exports the public key as an EC point in X9.62 uncompressed form. Note this - // includes the leading 0x04 byte. - bool ExportRawPublicKey(std::string* output) const; - - private: - // Constructor is private. Use one of the Create*() methods above instead. - ECPrivateKey(); - - bssl::UniquePtr key_; -}; - -} // namespace crypto - -#endif // CRYPTO_EC_PRIVATE_KEY_H_ diff --git a/naiveproxy/src/crypto/ec_signature_creator.cc b/naiveproxy/src/crypto/ec_signature_creator.cc deleted file mode 100644 index cc2cf1ea7e..0000000000 --- a/naiveproxy/src/crypto/ec_signature_creator.cc +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "crypto/ec_signature_creator.h" - -#include "base/check.h" -#include "base/memory/ptr_util.h" -#include "crypto/ec_signature_creator_impl.h" - -namespace crypto { - -// static -std::unique_ptr ECSignatureCreator::Create( - ECPrivateKey* key) { - return std::make_unique(key); -} - -} // namespace crypto diff --git a/naiveproxy/src/crypto/ec_signature_creator.h b/naiveproxy/src/crypto/ec_signature_creator.h deleted file mode 100644 index 5ad154be87..0000000000 --- a/naiveproxy/src/crypto/ec_signature_creator.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// This interface is deprecated and being removed: https://crbug.com/406190025. -// New users should use crypto/sign instead. - -#ifndef CRYPTO_EC_SIGNATURE_CREATOR_H_ -#define CRYPTO_EC_SIGNATURE_CREATOR_H_ - -#include - -#include -#include -#include - -#include "base/containers/span.h" -#include "crypto/crypto_export.h" - -namespace crypto { - -class ECPrivateKey; -class ECSignatureCreator; - -// Signs data using a bare private key (as opposed to a full certificate). -// We need this class because SignatureCreator is hardcoded to use -// RSAPrivateKey. -// TODO(https://crbug.com/406190025): Delete this. -class CRYPTO_EXPORT ECSignatureCreator { - public: - virtual ~ECSignatureCreator() {} - - // Create an instance. The caller must ensure that the provided PrivateKey - // instance outlives the created ECSignatureCreator. - // TODO(rch): This is currently hard coded to use SHA256. Ideally, we should - // pass in the hash algorithm identifier. - static std::unique_ptr Create(ECPrivateKey* key); - - // Signs |data| and writes the results into |signature| as a DER encoded - // ECDSA-Sig-Value from RFC 3279. - // - // ECDSA-Sig-Value ::= SEQUENCE { - // r INTEGER, - // s INTEGER } - virtual bool Sign(base::span data, - std::vector* signature) = 0; -}; - -} // namespace crypto - -#endif // CRYPTO_EC_SIGNATURE_CREATOR_H_ diff --git a/naiveproxy/src/crypto/ec_signature_creator_impl.cc b/naiveproxy/src/crypto/ec_signature_creator_impl.cc deleted file mode 100644 index 9e6ddf0575..0000000000 --- a/naiveproxy/src/crypto/ec_signature_creator_impl.cc +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "crypto/ec_signature_creator_impl.h" - -#include -#include - -#include "crypto/ec_private_key.h" -#include "crypto/openssl_util.h" -#include "third_party/boringssl/src/include/openssl/bn.h" -#include "third_party/boringssl/src/include/openssl/ec.h" -#include "third_party/boringssl/src/include/openssl/ecdsa.h" -#include "third_party/boringssl/src/include/openssl/evp.h" -#include "third_party/boringssl/src/include/openssl/sha.h" - -namespace crypto { - -ECSignatureCreatorImpl::ECSignatureCreatorImpl(ECPrivateKey* key) : key_(key) {} - -ECSignatureCreatorImpl::~ECSignatureCreatorImpl() = default; - -bool ECSignatureCreatorImpl::Sign(base::span data, - std::vector* signature) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - bssl::ScopedEVP_MD_CTX ctx; - size_t sig_len = 0; - if (!ctx.get() || - !EVP_DigestSignInit(ctx.get(), nullptr, EVP_sha256(), nullptr, - key_->key()) || - !EVP_DigestSignUpdate(ctx.get(), data.data(), data.size()) || - !EVP_DigestSignFinal(ctx.get(), nullptr, &sig_len)) { - return false; - } - - signature->resize(sig_len); - if (!EVP_DigestSignFinal(ctx.get(), &signature->front(), &sig_len)) - return false; - - // NOTE: A call to EVP_DigestSignFinal() with a nullptr second parameter - // returns a maximum allocation size, while the call without a nullptr - // returns the real one, which may be smaller. - signature->resize(sig_len); - return true; -} - -} // namespace crypto diff --git a/naiveproxy/src/crypto/ec_signature_creator_impl.h b/naiveproxy/src/crypto/ec_signature_creator_impl.h deleted file mode 100644 index 0a56d6025c..0000000000 --- a/naiveproxy/src/crypto/ec_signature_creator_impl.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CRYPTO_EC_SIGNATURE_CREATOR_IMPL_H_ -#define CRYPTO_EC_SIGNATURE_CREATOR_IMPL_H_ - -#include - -#include - -#include "base/compiler_specific.h" -#include "base/containers/span.h" -#include "base/memory/raw_ptr.h" -#include "crypto/ec_signature_creator.h" - -namespace crypto { - -class ECSignatureCreatorImpl : public ECSignatureCreator { - public: - explicit ECSignatureCreatorImpl(ECPrivateKey* key); - - ECSignatureCreatorImpl(const ECSignatureCreatorImpl&) = delete; - ECSignatureCreatorImpl& operator=(const ECSignatureCreatorImpl&) = delete; - - ~ECSignatureCreatorImpl() override; - - bool Sign(base::span data, - std::vector* signature) override; - - private: - raw_ptr key_; -}; - -} // namespace crypto - -#endif // CRYPTO_EC_SIGNATURE_CREATOR_IMPL_H_ diff --git a/naiveproxy/src/crypto/features.cc b/naiveproxy/src/crypto/features.cc index 5ed15182fe..53ff5305db 100644 --- a/naiveproxy/src/crypto/features.cc +++ b/naiveproxy/src/crypto/features.cc @@ -10,10 +10,14 @@ namespace crypto::features { BASE_FEATURE(kProcessBoundStringEncryption, "ProcessBoundStringEncryption", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kIsHardwareBackedFixEnabled, "IsHardwareBackedFixEnabled", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kMigrateIOSKeychainAccessibility, + "MigrateIOSKeychainAccessibility", + base::FEATURE_DISABLED_BY_DEFAULT); + } // namespace crypto::features diff --git a/naiveproxy/src/crypto/features.h b/naiveproxy/src/crypto/features.h index 05e35572c0..c55b61b5ef 100644 --- a/naiveproxy/src/crypto/features.h +++ b/naiveproxy/src/crypto/features.h @@ -18,6 +18,10 @@ CRYPTO_EXPORT BASE_DECLARE_FEATURE(kProcessBoundStringEncryption); // Enabled by default on M139. Remove in or after M142. CRYPTO_EXPORT BASE_DECLARE_FEATURE(kIsHardwareBackedFixEnabled); +// Migrate the accessibility attribute in the iOS keychain to "after first +// unlock". +CRYPTO_EXPORT BASE_DECLARE_FEATURE(kMigrateIOSKeychainAccessibility); + } // namespace crypto::features #endif // CRYPTO_FEATURES_H_ diff --git a/naiveproxy/src/crypto/hash.cc b/naiveproxy/src/crypto/hash.cc index 4276566ac0..e379d4cde1 100644 --- a/naiveproxy/src/crypto/hash.cc +++ b/naiveproxy/src/crypto/hash.cc @@ -14,24 +14,6 @@ namespace crypto::hash { -namespace { - -const EVP_MD* EVPMDForHashKind(HashKind kind) { - switch (kind) { - case HashKind::kSha1: - return EVP_sha1(); - case HashKind::kSha256: - return EVP_sha256(); - case HashKind::kSha384: - return EVP_sha384(); - case HashKind::kSha512: - return EVP_sha512(); - } - NOTREACHED(); -} - -} // namespace - void Hash(HashKind kind, base::span data, base::span digest) { @@ -76,6 +58,34 @@ std::array Sha512(std::string_view data) { return Sha512(base::as_byte_span(data)); } +const EVP_MD* EVPMDForHashKind(HashKind kind) { + switch (kind) { + case HashKind::kSha1: + return EVP_sha1(); + case HashKind::kSha256: + return EVP_sha256(); + case HashKind::kSha384: + return EVP_sha384(); + case HashKind::kSha512: + return EVP_sha512(); + } + NOTREACHED(); +} + +std::optional HashKindForEVPMD(const EVP_MD* evp_md) { + switch (EVP_MD_type(evp_md)) { + case NID_sha1: + return crypto::hash::kSha1; + case NID_sha256: + return crypto::hash::kSha256; + case NID_sha384: + return crypto::hash::kSha384; + case NID_sha512: + return crypto::hash::kSha512; + } + return std::nullopt; +} + Hasher::Hasher(HashKind kind) { CHECK(EVP_DigestInit(ctx_.get(), EVPMDForHashKind(kind))); } diff --git a/naiveproxy/src/crypto/hash.h b/naiveproxy/src/crypto/hash.h index ca944e8154..4b62cd3fd8 100644 --- a/naiveproxy/src/crypto/hash.h +++ b/naiveproxy/src/crypto/hash.h @@ -13,6 +13,7 @@ #include "base/containers/span.h" #include "base/notreached.h" #include "crypto/crypto_export.h" +#include "third_party/boringssl/src/include/openssl/base.h" #include "third_party/boringssl/src/include/openssl/digest.h" namespace crypto::hash { @@ -45,6 +46,13 @@ enum HashKind { kSha512, }; +// Free functions to convert to/from bssl EVP_MDs. The functions to convert to +// HashKind return optionals because HashKind can only represent a subset of the +// algorithms BoringSSL supports - specifically the ones the //crypto OWNERS +// recommend people use. +CRYPTO_EXPORT const EVP_MD* EVPMDForHashKind(HashKind k); +CRYPTO_EXPORT std::optional HashKindForEVPMD(const EVP_MD* evp_md); + inline constexpr size_t DigestSizeForHashKind(HashKind k) { switch (k) { case kSha1: diff --git a/naiveproxy/src/crypto/hkdf.h b/naiveproxy/src/crypto/hkdf.h index f4777848a9..a90f21a4d0 100644 --- a/naiveproxy/src/crypto/hkdf.h +++ b/naiveproxy/src/crypto/hkdf.h @@ -20,12 +20,14 @@ namespace crypto { +// TODO(https://issues.chromium.org/issues/430616377): delete this. CRYPTO_EXPORT std::string HkdfSha256(std::string_view secret, std::string_view salt, std::string_view info, size_t derived_key_size); +// TODO(https://issues.chromium.org/issues/430616377): delete this. template std::array HkdfSha256(base::span secret, base::span salt, diff --git a/naiveproxy/src/crypto/hmac.cc b/naiveproxy/src/crypto/hmac.cc index 72d918e6cc..3f29b59db9 100644 --- a/naiveproxy/src/crypto/hmac.cc +++ b/naiveproxy/src/crypto/hmac.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/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "crypto/hmac.h" #include @@ -16,6 +11,7 @@ #include "base/check.h" #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/notreached.h" #include "base/stl_util.h" #include "crypto/openssl_util.h" @@ -50,14 +46,15 @@ bool HMAC::Init(const unsigned char* key, size_t key_length) { // Init must not be called more than once on the same HMAC object. DCHECK(!initialized_); initialized_ = true; - key_.assign(key, key + key_length); + key_.assign(key, UNSAFE_TODO(key + key_length)); return true; } bool HMAC::Sign(std::string_view data, unsigned char* digest, size_t digest_length) const { - return Sign(base::as_byte_span(data), base::span(digest, digest_length)); + return Sign(base::as_byte_span(data), + UNSAFE_TODO(base::span(digest, digest_length))); } bool HMAC::Sign(base::span data, @@ -110,34 +107,15 @@ bool HMAC::VerifyTruncated(base::span data, namespace hmac { -namespace { - -const EVP_MD* EVPMDForHashKind(crypto::hash::HashKind kind) { - switch (kind) { - case crypto::hash::HashKind::kSha1: - return EVP_sha1(); - case crypto::hash::HashKind::kSha256: - return EVP_sha256(); - case crypto::hash::HashKind::kSha384: - return EVP_sha384(); - case crypto::hash::HashKind::kSha512: - return EVP_sha512(); - } - NOTREACHED(); -} - -} // namespace - void Sign(crypto::hash::HashKind kind, base::span key, base::span data, base::span hmac) { - const EVP_MD* md = EVPMDForHashKind(kind); + const EVP_MD* md = crypto::hash::EVPMDForHashKind(kind); CHECK_EQ(hmac.size(), EVP_MD_size(md)); bssl::ScopedHMAC_CTX ctx; - CHECK(HMAC_Init_ex(ctx.get(), key.data(), key.size(), EVPMDForHashKind(kind), - nullptr)); + CHECK(HMAC_Init_ex(ctx.get(), key.data(), key.size(), md, nullptr)); CHECK(HMAC_Update(ctx.get(), data.data(), data.size())); CHECK(HMAC_Final(ctx.get(), hmac.data(), nullptr)); } @@ -146,7 +124,7 @@ bool Verify(crypto::hash::HashKind kind, base::span key, base::span data, base::span hmac) { - const EVP_MD* md = EVPMDForHashKind(kind); + const EVP_MD* md = crypto::hash::EVPMDForHashKind(kind); CHECK_EQ(hmac.size(), EVP_MD_size(md)); std::array computed_buf; diff --git a/naiveproxy/src/crypto/kdf.cc b/naiveproxy/src/crypto/kdf.cc index 24f3711e98..6f0544def1 100644 --- a/naiveproxy/src/crypto/kdf.cc +++ b/naiveproxy/src/crypto/kdf.cc @@ -7,6 +7,7 @@ #include "base/check_op.h" #include "crypto/openssl_util.h" #include "third_party/boringssl/src/include/openssl/evp.h" +#include "third_party/boringssl/src/include/openssl/hkdf.h" namespace crypto::kdf { @@ -38,4 +39,18 @@ void DeriveKeyScrypt(const ScryptParams& params, CHECK_EQ(rv, 1); } +void Hkdf(crypto::hash::HashKind kind, + base::span secret, + base::span salt, + base::span info, + base::span out) { + // Even though ::HKDF() will fail in this situation, check it explicitly here + // to give better error info: + CHECK_LT(out.size(), 255 * crypto::hash::DigestSizeForHashKind(kind)); + CHECK_EQ(::HKDF(out.data(), out.size(), crypto::hash::EVPMDForHashKind(kind), + secret.data(), secret.size(), salt.data(), salt.size(), + info.data(), info.size()), + 1); +} + } // namespace crypto::kdf diff --git a/naiveproxy/src/crypto/kdf.h b/naiveproxy/src/crypto/kdf.h index df0162835b..b83172d44e 100644 --- a/naiveproxy/src/crypto/kdf.h +++ b/naiveproxy/src/crypto/kdf.h @@ -7,6 +7,7 @@ #include "base/containers/span.h" #include "crypto/crypto_export.h" +#include "crypto/hash.h" #include "crypto/subtle_passkey.h" namespace crypto::kdf { @@ -41,6 +42,7 @@ struct ScryptParams { // TODO(https://issues.chromium.org/issues/369653192): document constraints on // params. +// TODO(https://issues.chromium.org/issues/430635195): rename this. CRYPTO_EXPORT void DeriveKeyPbkdf2HmacSha1(const Pbkdf2HmacSha1Params& params, base::span password, base::span salt, @@ -49,6 +51,7 @@ CRYPTO_EXPORT void DeriveKeyPbkdf2HmacSha1(const Pbkdf2HmacSha1Params& params, // TODO(https://issues.chromium.org/issues/369653192): document constraints on // params. +// TODO(https://issues.chromium.org/issues/430635195): rename this. // // Note: this function CHECKs that the passed-in ScryptParams are valid. If you // are not sure if your params will be valid, consult a //crypto OWNER - the @@ -59,6 +62,34 @@ CRYPTO_EXPORT void DeriveKeyScrypt(const ScryptParams& params, base::span result, crypto::SubtlePassKey); +// Derive a key using HKDF with the specified hash kind, into the given out +// buffer, which must be the right size for that hash kind. The secret, salt, +// and info parameters have meanings as described in RFC 5869. +// +// Note that it's illegal to request more than 255 * the size of the output of +// the specified hash function. If you need large amounts of data generated from +// one key, you are better off using a keyed CSPRNG. +// +// TODO(https://issues.chromium.org/issues/431672006): recommend a specific +// keyed CSPRNG. +CRYPTO_EXPORT void Hkdf(crypto::hash::HashKind kind, + base::span secret, + base::span salt, + base::span info, + base::span out); + +// Same, but return an array containing the derived value. Templated on the +// array size. +template +std::array Hkdf(crypto::hash::HashKind kind, + base::span secret, + base::span salt, + base::span info) { + std::array out; + Hkdf(kind, secret, salt, info, out); + return out; +} + } // namespace crypto::kdf #endif // CRYPTO_KDF_H_ diff --git a/naiveproxy/src/crypto/keypair.cc b/naiveproxy/src/crypto/keypair.cc index adcfc9a1b2..a13ee6c7d0 100644 --- a/naiveproxy/src/crypto/keypair.cc +++ b/naiveproxy/src/crypto/keypair.cc @@ -6,8 +6,10 @@ #include "base/logging.h" #include "crypto/openssl_util.h" +#include "crypto/rsa_private_key.h" #include "third_party/boringssl/src/include/openssl/bn.h" #include "third_party/boringssl/src/include/openssl/bytestring.h" +#include "third_party/boringssl/src/include/openssl/curve25519.h" #include "third_party/boringssl/src/include/openssl/ec.h" #include "third_party/boringssl/src/include/openssl/evp.h" #include "third_party/boringssl/src/include/openssl/mem.h" @@ -36,7 +38,8 @@ bssl::UniquePtr GenerateRsa(size_t bits) { } bool IsSupportedEvpId(int evp_id) { - return evp_id == EVP_PKEY_RSA || evp_id == EVP_PKEY_EC; + return evp_id == EVP_PKEY_RSA || evp_id == EVP_PKEY_EC || + evp_id == EVP_PKEY_ED25519; } std::vector ExportEVPPublicKey(EVP_PKEY* pkey) { @@ -96,6 +99,20 @@ PrivateKey PrivateKey::GenerateEcP256() { return PrivateKey(std::move(key)); } +// static +PrivateKey PrivateKey::GenerateEd25519() { + OpenSSLErrStackTracer err_tracer(FROM_HERE); + + std::array unused_pubkey; + std::array privkey; + + ED25519_keypair(unused_pubkey.data(), privkey.data()); + + // EVP_PKEY_new_raw_public_key() takes only the 32-byte RFC 8032 "seed" at the + // start of the private key, not the BoringSSL-format "full" private key. + return FromEd25519PrivateKey(base::span(privkey).first<32>()); +} + // static std::optional PrivateKey::FromPrivateKeyInfo( base::span pki) { @@ -117,6 +134,20 @@ std::optional PrivateKey::FromPrivateKeyInfo( return std::optional(PrivateKey(std::move(pkey))); } +// static +PrivateKey PrivateKey::FromDeprecatedRSAPrivateKey(RSAPrivateKey* key) { + return PrivateKey(bssl::UpRef(key->key())); +} + +// static +PrivateKey PrivateKey::FromEd25519PrivateKey( + base::span key) { + bssl::UniquePtr pkey(EVP_PKEY_new_raw_private_key( + EVP_PKEY_ED25519, nullptr, key.data(), key.size())); + CHECK(pkey); + return PrivateKey(std::move(pkey)); +} + std::vector PrivateKey::ToPrivateKeyInfo() const { OpenSSLErrStackTracer err_tracer(FROM_HERE); bssl::ScopedCBB cbb; @@ -136,6 +167,15 @@ std::vector PrivateKey::ToPrivateKeyInfo() const { return result; } +std::array PrivateKey::ToEd25519PrivateKey() const { + CHECK(IsEd25519()); + std::array result; + size_t len = std::size(result); + CHECK(EVP_PKEY_get_raw_private_key(key_.get(), result.data(), &len)); + CHECK(len == std::size(result)); + return result; +} + std::vector PrivateKey::ToSubjectPublicKeyInfo() const { return ExportEVPPublicKey(key_.get()); } @@ -152,6 +192,15 @@ std::vector PrivateKey::ToUncompressedForm() const { return buf; } +std::array PrivateKey::ToEd25519PublicKey() const { + CHECK(IsEd25519()); + std::array result; + size_t len = std::size(result); + CHECK(EVP_PKEY_get_raw_public_key(key_.get(), result.data(), &len)); + CHECK(len == std::size(result)); + return result; +} + PrivateKey::PrivateKey(bssl::UniquePtr key) : key_(std::move(key)) {} bool PrivateKey::IsRsa() const { @@ -162,6 +211,10 @@ bool PrivateKey::IsEc() const { return EVP_PKEY_id(key_.get()) == EVP_PKEY_EC; } +bool PrivateKey::IsEd25519() const { + return EVP_PKEY_id(key_.get()) == EVP_PKEY_ED25519; +} + PublicKey::PublicKey(bssl::UniquePtr key, crypto::SubtlePassKey) : PublicKey(std::move(key)) {} PublicKey::~PublicKey() = default; @@ -200,6 +253,58 @@ std::optional PublicKey::FromSubjectPublicKeyInfo( return std::optional(PublicKey(std::move(pkey))); } +std::optional PublicKey::FromRsaPublicKeyComponents( + base::span n, + base::span e) { + bssl::UniquePtr bn_n(BN_bin2bn(n.data(), n.size(), nullptr)); + bssl::UniquePtr bn_e(BN_bin2bn(e.data(), e.size(), nullptr)); + if (!bn_n || !bn_e) { + return std::nullopt; + } + + bssl::UniquePtr rsa(RSA_new_public_key(bn_n.get(), bn_e.get())); + if (!rsa) { + return std::nullopt; + } + + // The only failure mode for EVP_PKEY_new() is memory allocation failures, + // and the only failure mode for EVP_PKEY_set1_RSA() is being passed a null + // key or RSA object. + bssl::UniquePtr pkey(EVP_PKEY_new()); + CHECK(pkey); + CHECK(EVP_PKEY_set1_RSA(pkey.get(), rsa.get())); + return PublicKey(std::move(pkey)); +} + +std::optional PublicKey::FromEcP256Point( + base::span p) { + bssl::UniquePtr ec(EC_KEY_new()); + CHECK(ec); + CHECK(EC_KEY_set_group(ec.get(), EC_group_p256())); + + if (!EC_KEY_oct2key(ec.get(), p.data(), p.size(), nullptr)) { + return std::nullopt; + } + + // The only failure mode for EVP_PKEY_new() is memory allocation failures, + // and the only failure mode for EVP_PKEY_set1_EC_KEY() is being passed a null + // key or EC_KEY object. + bssl::UniquePtr pkey(EVP_PKEY_new()); + CHECK(pkey); + CHECK(EVP_PKEY_set1_EC_KEY(pkey.get(), ec.get())); + return PublicKey(std::move(pkey)); +} + +// static +PublicKey PublicKey::FromEd25519PublicKey(base::span key) { + static_assert(std::size(key) == ED25519_PUBLIC_KEY_LEN); + + bssl::UniquePtr pkey(EVP_PKEY_new_raw_public_key( + EVP_PKEY_ED25519, nullptr, key.data(), key.size())); + CHECK(pkey); + return PublicKey(std::move(pkey)); +} + std::vector PublicKey::ToSubjectPublicKeyInfo() const { return ExportEVPPublicKey(key_.get()); } @@ -212,6 +317,10 @@ bool PublicKey::IsEc() const { return EVP_PKEY_id(key_.get()) == EVP_PKEY_EC; } +bool PublicKey::IsEd25519() const { + return EVP_PKEY_id(key_.get()) == EVP_PKEY_ED25519; +} + PublicKey::PublicKey(bssl::UniquePtr key) : key_(std::move(key)) {} } // namespace crypto::keypair diff --git a/naiveproxy/src/crypto/keypair.h b/naiveproxy/src/crypto/keypair.h index 4669d66087..b3b2838ade 100644 --- a/naiveproxy/src/crypto/keypair.h +++ b/naiveproxy/src/crypto/keypair.h @@ -5,6 +5,7 @@ #ifndef CRYPTO_KEYPAIR_H_ #define CRYPTO_KEYPAIR_H_ +#include #include #include "base/containers/span.h" @@ -12,6 +13,10 @@ #include "crypto/subtle_passkey.h" #include "third_party/boringssl/src/include/openssl/base.h" +namespace crypto { +class RSAPrivateKey; +} + namespace crypto::keypair { // This class wraps an EVP_PKEY containing a private key. Since EVP_PKEY is @@ -42,12 +47,25 @@ class CRYPTO_EXPORT PrivateKey { // Generates a fresh, random elliptic curve key on the NIST P-256 curve. static PrivateKey GenerateEcP256(); + // Generates a fresh, random Ed25519 key. + static PrivateKey GenerateEd25519(); + // Imports a PKCS#8 PrivateKeyInfo block. Returns nullopt if the passed-in // buffer is not a valid PrivateKeyInfo block, or if there is trailing data in // it after the PrivateKeyInfo block. static std::optional FromPrivateKeyInfo( base::span pki); + // Deprecated compatibility interface for using new signing APIs with the old + // RSAPrivateKey type. Do not add new uses. + static PrivateKey FromDeprecatedRSAPrivateKey(RSAPrivateKey* key); + + // Imports an RFC 8032-encoded Ed25519 private key. + // + // The encoding used doesn't allow for importing to fail (all input bit + // strings are potentially valid keys). + static PrivateKey FromEd25519PrivateKey(base::span key); + // Deliberately not present in this API: // ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(): imports a PKCS#8 // EncryptedPrivateKeyInfo with a hardcoded empty password. There is no reason @@ -56,6 +74,10 @@ class CRYPTO_EXPORT PrivateKey { // Exports a PKCS#8 PrivateKeyInfo block. std::vector ToPrivateKeyInfo() const; + // Exports an Ed25519 private key in RFC 8032 format. It is illegal to call + // this if !IsEd25519(). + std::array ToEd25519PrivateKey() const; + // Computes and exports an X.509 SubjectPublicKeyInfo block corresponding to // this key. std::vector ToSubjectPublicKeyInfo() const; @@ -64,11 +86,16 @@ class CRYPTO_EXPORT PrivateKey { // this on a non-EC PrivateKey. std::vector ToUncompressedForm() const; + // Exports an Ed25519 public key in RFC 8032 format. It is illegal to call + // this if !IsEd25519(). + std::array ToEd25519PublicKey() const; + EVP_PKEY* key() { return key_.get(); } const EVP_PKEY* key() const { return key_.get(); } bool IsRsa() const; bool IsEc() const; + bool IsEd25519() const; private: explicit PrivateKey(bssl::UniquePtr key); @@ -97,13 +124,42 @@ class CRYPTO_EXPORT PublicKey { static std::optional FromSubjectPublicKeyInfo( base::span spki); + // Imports a pair of big-endian big integers (n, e) to form an RSA public key. + // Returns nullopt if the parameters are invalid for some reason. + // + // Note: if you need to serialize and deserialize RSA keys, you should + // probably use SubjectPublicKeyInfo instead of rolling your own serialization + // format for the (n, e) pair. + static std::optional FromRsaPublicKeyComponents( + base::span n, + base::span e); + + // Imports a big-endian integer point to form an EC P-256 public key. Returns + // nullopt if the point is not on the curve or something else is wrong with + // it. + // + // Note: unless you *only* want an EC P-256 key, you should use + // SubjectPublicKeyInfo as a serialization format rather than inventing your + // own format. + static std::optional FromEcP256Point( + base::span point); + + // Imports an Ed25519 public key in RFC 8032 format. + // + // Note: the size is hardcoded to 32 here rather than ED25519_PUBLIC_KEY_LEN + // to avoid pulling curve25519.h into this file. Also, it's impossible for + // importing to fail. + static PublicKey FromEd25519PublicKey(base::span key); + // Exports a PublicKey as an X.509 SubjectPublicKeyInfo. std::vector ToSubjectPublicKeyInfo() const; EVP_PKEY* key() { return key_.get(); } + const EVP_PKEY* key() const { return key_.get(); } bool IsRsa() const; bool IsEc() const; + bool IsEd25519() const; private: explicit PublicKey(bssl::UniquePtr key); diff --git a/naiveproxy/src/crypto/nss_key_util.cc b/naiveproxy/src/crypto/nss_key_util.cc index 3ca325bd62..d257db903b 100644 --- a/naiveproxy/src/crypto/nss_key_util.cc +++ b/naiveproxy/src/crypto/nss_key_util.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/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "crypto/nss_key_util.h" #include @@ -18,6 +13,7 @@ #include #include +#include "base/compiler_specific.h" #include "base/logging.h" #include "crypto/nss_util.h" #include "crypto/nss_util_internal.h" @@ -101,8 +97,9 @@ bool GenerateECKeyPairNSS(PK11SlotInfo* slot, static_cast(parameters_buf.size())}; ec_parameters.data[0] = SEC_ASN1_OBJECT_ID; - ec_parameters.data[1] = oid_data->oid.len; - memcpy(ec_parameters.data + 2, oid_data->oid.data, oid_data->oid.len); + UNSAFE_TODO(ec_parameters.data[1]) = oid_data->oid.len; + UNSAFE_TODO( + memcpy(ec_parameters.data + 2, oid_data->oid.data, oid_data->oid.len)); SECKEYPublicKey* public_key_raw = nullptr; private_key->reset(PK11_GenerateKeyPair(slot, CKM_EC_KEY_PAIR_GEN, &ec_parameters, &public_key_raw, @@ -168,8 +165,8 @@ ScopedSECKEYPrivateKey FindNSSKeyFromPublicKeyInfo( int slot_count = item->module->loaded ? item->module->slotCount : 0; for (int i = 0; i < slot_count; i++) { // Look for the key in slot |i|. - ScopedSECKEYPrivateKey key( - PK11_FindKeyByKeyID(item->module->slots[i], cka_id.get(), nullptr)); + ScopedSECKEYPrivateKey key(PK11_FindKeyByKeyID( + UNSAFE_TODO(item->module->slots[i]), cka_id.get(), nullptr)); if (key) { return key; } diff --git a/naiveproxy/src/crypto/nss_util.cc b/naiveproxy/src/crypto/nss_util.cc index cd43cde2a5..00cd0c8a58 100644 --- a/naiveproxy/src/crypto/nss_util.cc +++ b/naiveproxy/src/crypto/nss_util.cc @@ -156,9 +156,6 @@ class NSSInitSingleton { } else { LOG(ERROR) << "Error opening persistent database (" << modspec << "): " << GetNSSErrorMessage(); -#if BUILDFLAG(IS_CHROMEOS) - DiagnosePublicSlotAndCrash(path); -#endif // BUILDFLAG(IS_CHROMEOS) } return ScopedPK11Slot(db_slot_info); diff --git a/naiveproxy/src/crypto/nss_util.h b/naiveproxy/src/crypto/nss_util.h index 73a68469a1..f177f5ee55 100644 --- a/naiveproxy/src/crypto/nss_util.h +++ b/naiveproxy/src/crypto/nss_util.h @@ -12,7 +12,6 @@ #include "base/functional/callback_forward.h" #include "base/threading/thread_restrictions.h" #include "build/build_config.h" -#include "components/nacl/common/buildflags.h" #include "crypto/crypto_export.h" namespace base { @@ -39,7 +38,7 @@ CRYPTO_EXPORT void EnsureNSSInit(); // A sample version string is "3.12.3". bool CheckNSSVersion(const char* version); -#if BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_MINIMAL_TOOLCHAIN) +#if BUILDFLAG(IS_CHROMEOS) // Returns true once the TPM is owned and PKCS#11 initialized with the // user and security officer PINs, and Chaps has been successfully loaded into @@ -62,19 +61,7 @@ CRYPTO_EXPORT void InitializeTPMTokenAndSystemSlot( // that no TPM system slot will be available. CRYPTO_EXPORT void FinishInitializingTPMTokenAndSystemSlot(); -// TODO(crbug.com/1163303) Remove when the bug is fixed. -// Can be used to collect additional information when public slot fails to open. -// Mainly checks the access permissions on the files and tries to read them. -// Crashes Chrome because it will crash anyway when it tries to instantiate -// NSSCertDatabase with a nullptr public slot, crashing early can provide better -// logs/stacktraces for diagnosing. -// Takes `nss_path` where NSS is supposed to be (or created). Will attempt -// creating the path if it doesn't exist (to check that it can be done). -// Theoretically the path should already exist because it's created when Chrome -// tries to open the public slot. -CRYPTO_EXPORT void DiagnosePublicSlotAndCrash(const base::FilePath& nss_path); - -#endif // BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_MINIMAL_TOOLCHAIN) +#endif // BUILDFLAG(IS_CHROMEOS) // Convert a NSS PRTime value into a base::Time object. // We use a int64_t instead of PRTime here to avoid depending on NSPR headers. diff --git a/naiveproxy/src/crypto/nss_util_chromeos.cc b/naiveproxy/src/crypto/nss_util_chromeos.cc index 3f33ccc379..15a75c25f3 100644 --- a/naiveproxy/src/crypto/nss_util_chromeos.cc +++ b/naiveproxy/src/crypto/nss_util_chromeos.cc @@ -18,7 +18,6 @@ #include "base/callback_list.h" #include "base/containers/contains.h" -#include "base/files/file_enumerator.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/functional/bind.h" @@ -613,85 +612,4 @@ void SetPrivateSoftwareSlotForChromeOSUserForTesting(ScopedPK11Slot slot) { std::move(slot)); } -namespace { -void PrintDirectoryInfo(const base::FilePath& path) { - base::stat_wrapper_t file_stat; - - if (base::File::Stat(path, &file_stat) == -1) { - base::File::Error error_code = base::File::OSErrorToFileError(errno); - LOG(ERROR) << "Failed to collect directory info, error: " << error_code; - } - - LOG(ERROR) << path << ", " << std::oct << file_stat.st_mode << std::dec - << ", " - << "uid " << file_stat.st_uid << ", " - << "gid " << file_stat.st_gid << std::endl; -} -} // namespace - -// TODO(crbug.com/1163303): Remove when the bug is fixed. -void DiagnosePublicSlotAndCrash(const base::FilePath& nss_path) { - LOG(ERROR) << "Public slot is invalid. Start collecting stats."; - // Should be something like /home/chronos/u-/.pki/nssdb . - LOG(ERROR) << "NSS path: " << nss_path; - - { - // NSS files like pkcs11.txt, cert9.db, key4.db . - base::FileEnumerator files( - nss_path, /*recursive=*/false, - /*file_type=*/base::FileEnumerator::FILES, - /*pattern=*/base::FilePath::StringType(), - base::FileEnumerator::FolderSearchPolicy::MATCH_ONLY, - base::FileEnumerator::ErrorPolicy::STOP_ENUMERATION); - LOG(ERROR) << "Public slot database files:"; - for (base::FilePath path = files.Next(); !path.empty(); - path = files.Next()) { - base::FileEnumerator::FileInfo file_info = files.GetInfo(); - - char buf[16]; - int read_result = base::ReadFile(path, buf, sizeof(buf) - 1); - - LOG(ERROR) << file_info.GetName() << ", " << std::oct - << file_info.stat().st_mode << std::dec << ", " - << "uid " << file_info.stat().st_uid << ", " - << "gid " << file_info.stat().st_gid << ", " - << file_info.stat().st_size << " bytes, " - << ((read_result > 0) ? "readable" : "not readable"); - } - LOG(ERROR) << "Enumerate error code: " << files.GetError(); - } - - // NSS directory might not be created yet, also check parent directories. - // Use u-hash directory as a comparison point for user and group ids and - // access permissions. - - base::FilePath nssdb_path = nss_path.Append(base::FilePath::kParentDirectory); - PrintDirectoryInfo(nssdb_path); - - base::FilePath pki_path = nssdb_path.Append(base::FilePath::kParentDirectory); - PrintDirectoryInfo(pki_path); - - base::FilePath u_hash_path = - pki_path.Append(base::FilePath::kParentDirectory); - PrintDirectoryInfo(u_hash_path); - - { - // Check whether the NSS path exists, and if not, check whether it's - // possible to create it. - if (base::DirectoryExists(nss_path)) { - LOG(ERROR) << "NSS path exists (as expected)."; - } else { - base::File::Error error = base::File::Error::FILE_OK; - if (base::CreateDirectoryAndGetError(nss_path, &error)) { - LOG(ERROR) << "NSS path didn't exist. Created successfully."; - } else { - LOG(ERROR) << "NSS path didn't exist. Failed to create, error: " - << error; - } - } - } - - NOTREACHED() << "Public slot is invalid."; -} - } // namespace crypto diff --git a/naiveproxy/src/crypto/nss_util_internal.h b/naiveproxy/src/crypto/nss_util_internal.h index 62be83234b..6bdb06886c 100644 --- a/naiveproxy/src/crypto/nss_util_internal.h +++ b/naiveproxy/src/crypto/nss_util_internal.h @@ -12,7 +12,6 @@ #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" #include "build/build_config.h" -#include "components/nacl/common/buildflags.h" #include "crypto/crypto_export.h" #include "crypto/scoped_nss_types.h" @@ -56,7 +55,7 @@ class CRYPTO_EXPORT AutoSECMODListReadLock { raw_ptr lock_; }; -#if BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_MINIMAL_TOOLCHAIN) +#if BUILDFLAG(IS_CHROMEOS) // Returns path to the NSS database file in the provided profile // directory. CRYPTO_EXPORT base::FilePath GetSoftwareNSSDBPath( diff --git a/naiveproxy/src/crypto/obsolete/md5.h b/naiveproxy/src/crypto/obsolete/md5.h index 9bb24b7878..8af433b11c 100644 --- a/naiveproxy/src/crypto/obsolete/md5.h +++ b/naiveproxy/src/crypto/obsolete/md5.h @@ -23,6 +23,22 @@ crypto::obsolete::Md5 MakeMd5HasherForZeroconf(); std::string ServerPrinterId(const std::string& url); } // namespace ash::printing +namespace android_tools { +crypto::obsolete::Md5 MakeMd5HasherForMd5sumTool(); +} + +namespace autofill { +crypto::obsolete::Md5 MakeMd5HasherForPasswordRequirementsSpec(); +} + +namespace bookmarks { +class BookmarkCodec; +} // namespace bookmarks + +namespace cachetool { +crypto::obsolete::Md5 MakeMd5HasherForCachetools(); +} + namespace drive::util { crypto::obsolete::Md5 MakeMd5HasherForDriveApi(); } @@ -31,6 +47,10 @@ namespace extensions::image_writer { crypto::obsolete::Md5 MakeMd5HasherForImageWriter(); } +namespace media::test { +crypto::obsolete::Md5 MakeMd5HasherForVideoFrameValidation(); +} + namespace net { crypto::obsolete::Md5 MakeMd5HasherForHttpVaryData(); } @@ -39,21 +59,18 @@ namespace policy { crypto::obsolete::Md5 MakeMd5HasherForPolicyEventId(); } -namespace web_app::internals { -crypto::obsolete::Md5 MakeMd5HasherForWebAppShortcutIcon(); -} - -namespace cachetool { -crypto::obsolete::Md5 MakeMd5HasherForCachetools(); -} - namespace trusted_vault { std::string MD5StringForTrustedVault(const std::string& local_trusted_value); } -namespace bookmarks { -class BookmarkCodec; -} // namespace bookmarks +namespace visitedlink { +crypto::obsolete::Md5 MakeMd5HasherForVisitedLink(); +} + +namespace web_app::internals { +crypto::obsolete::Md5 MakeMd5HasherForWebAppShortcutIcon(); +std::wstring Md5AsHexForUninstall(const std::wstring& data); +} namespace crypto::obsolete { @@ -87,6 +104,7 @@ class CRYPTO_EXPORT Md5 { // The friends listed here are the areas required to continue using MD5 for // compatibility with existing specs, on-disk data, or similar. + friend Md5 android_tools::MakeMd5HasherForMd5sumTool(); friend Md5 policy::MakeMd5HasherForPolicyEventId(); friend Md5 drive::util::MakeMd5HasherForDriveApi(); friend Md5 extensions::image_writer::MakeMd5HasherForImageWriter(); @@ -98,19 +116,30 @@ class CRYPTO_EXPORT Md5 { friend Md5 ash::printing::MakeMd5HasherForZeroconf(); friend std::string ash::printing::ServerPrinterId(const std::string& url); - // TODO(https://crbug.com/419853200): get rid of this. - friend Md5 net::MakeMd5HasherForHttpVaryData(); - - // TODO(https://crbug.com/416304903): get rid of this. - friend Md5 web_app::internals::MakeMd5HasherForWebAppShortcutIcon(); - - // TODO(https://crbug.com/425990763): get rid of this - friend std::string trusted_vault::MD5StringForTrustedVault( - const std::string& local_trusted_value); + // TODO(https://crbug.com/433545115): get rid of this. + friend Md5 autofill::MakeMd5HasherForPasswordRequirementsSpec(); // TODO(https://crbug.com/426243026): get rid of this. friend class bookmarks::BookmarkCodec; + // TODO(https://crbug.com/428022614): get rid of this. + friend Md5 media::test::MakeMd5HasherForVideoFrameValidation(); + + // TODO(https://crbug.com/419853200): get rid of this. + friend Md5 net::MakeMd5HasherForHttpVaryData(); + + // TODO(https://crbug.com/425990763): get rid of this. + friend std::string trusted_vault::MD5StringForTrustedVault( + const std::string& local_trusted_value); + + // TODO(https://crbug.com/427437222): get rid of this. + friend Md5 visitedlink::MakeMd5HasherForVisitedLink(); + + // TODO(https://crbug.com/416304903): get rid of this. + friend Md5 web_app::internals::MakeMd5HasherForWebAppShortcutIcon(); + friend std::wstring web_app::internals::Md5AsHexForUninstall( + const std::wstring& key); + Md5(); static std::array Hash(std::string_view data); static std::array Hash(base::span data); diff --git a/naiveproxy/src/crypto/rsa_private_key.cc b/naiveproxy/src/crypto/rsa_private_key.cc index bd53bab174..edd70d2d09 100644 --- a/naiveproxy/src/crypto/rsa_private_key.cc +++ b/naiveproxy/src/crypto/rsa_private_key.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/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "crypto/rsa_private_key.h" #include @@ -15,6 +10,7 @@ #include #include "base/check.h" +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "crypto/openssl_util.h" #include "third_party/boringssl/src/include/openssl/bn.h" @@ -25,26 +21,6 @@ namespace crypto { -// static -std::unique_ptr RSAPrivateKey::Create(uint16_t num_bits) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - - bssl::UniquePtr rsa_key(RSA_new()); - bssl::UniquePtr bn(BN_new()); - if (!rsa_key.get() || !bn.get() || !BN_set_word(bn.get(), 65537L)) - return nullptr; - - if (!RSA_generate_key_ex(rsa_key.get(), num_bits, bn.get(), nullptr)) - return nullptr; - - std::unique_ptr result(new RSAPrivateKey); - result->key_.reset(EVP_PKEY_new()); - if (!result->key_ || !EVP_PKEY_set1_RSA(result->key_.get(), rsa_key.get())) - return nullptr; - - return result; -} - // static std::unique_ptr RSAPrivateKey::CreateFromPrivateKeyInfo( base::span input) { @@ -61,16 +37,6 @@ std::unique_ptr RSAPrivateKey::CreateFromPrivateKeyInfo( return result; } -// static -std::unique_ptr RSAPrivateKey::CreateFromKey(EVP_PKEY* key) { - DCHECK(key); - if (EVP_PKEY_id(key) != EVP_PKEY_RSA) - return nullptr; - std::unique_ptr copy(new RSAPrivateKey); - copy->key_ = bssl::UpRef(key); - return copy; -} - RSAPrivateKey::RSAPrivateKey() = default; RSAPrivateKey::~RSAPrivateKey() = default; @@ -96,7 +62,7 @@ bool RSAPrivateKey::ExportPrivateKey(std::vector* output) const { !CBB_finish(cbb.get(), &der, &der_len)) { return false; } - output->assign(der, der + der_len); + output->assign(der, UNSAFE_TODO(der + der_len)); OPENSSL_free(der); return true; } @@ -111,7 +77,7 @@ bool RSAPrivateKey::ExportPublicKey(std::vector* output) const { !CBB_finish(cbb.get(), &der, &der_len)) { return false; } - output->assign(der, der + der_len); + output->assign(der, UNSAFE_TODO(der + der_len)); OPENSSL_free(der); return true; } diff --git a/naiveproxy/src/crypto/rsa_private_key.h b/naiveproxy/src/crypto/rsa_private_key.h index c85ed44622..b5f88c5f45 100644 --- a/naiveproxy/src/crypto/rsa_private_key.h +++ b/naiveproxy/src/crypto/rsa_private_key.h @@ -21,8 +21,8 @@ namespace crypto { -// Encapsulates an RSA private key. Can be used to generate new keys, export -// keys to other formats, or to extract a public key. +// Encapsulates an RSA private key. Can be used to export keys to other formats +// or to extract a public key. // TODO(https://crbug.com/425863216): Delete this. class CRYPTO_EXPORT RSAPrivateKey { public: @@ -31,20 +31,12 @@ class CRYPTO_EXPORT RSAPrivateKey { ~RSAPrivateKey(); - // Create a new random instance. Can return NULL if initialization fails. - static std::unique_ptr Create(uint16_t num_bits); - // Create a new instance by importing an existing private key. The format is // an ASN.1-encoded PrivateKeyInfo block from PKCS #8. This can return NULL if // initialization fails. static std::unique_ptr CreateFromPrivateKeyInfo( base::span input); - // Create a new instance from an existing EVP_PKEY, taking a - // reference to it. |key| must be an RSA key. Returns NULL on - // failure. - static std::unique_ptr CreateFromKey(EVP_PKEY* key); - EVP_PKEY* key() const { return key_.get(); } // Creates a copy of the object. diff --git a/naiveproxy/src/crypto/scoped_fake_apple_keychain_v2.h b/naiveproxy/src/crypto/scoped_fake_apple_keychain_v2.h deleted file mode 100644 index b4d3785a00..0000000000 --- a/naiveproxy/src/crypto/scoped_fake_apple_keychain_v2.h +++ /dev/null @@ -1,42 +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 CRYPTO_SCOPED_FAKE_APPLE_KEYCHAIN_V2_H_ -#define CRYPTO_SCOPED_FAKE_APPLE_KEYCHAIN_V2_H_ - -#include -#include - -#include "crypto/crypto_export.h" - -namespace crypto { - -class FakeAppleKeychainV2; - -// ScopedFakeAppleKeychainV2 installs itself as testing override for -// `AppleKeychainV2::GetInstance()`. -class CRYPTO_EXPORT ScopedFakeAppleKeychainV2 { - public: - // Supported types of user verification, reported by - // LAContextCanEvaluatePolicy. - enum class UVMethod { - kNone, - kPasswordOnly, - kBiometrics, - }; - - explicit ScopedFakeAppleKeychainV2(const std::string& keychain_access_group); - ~ScopedFakeAppleKeychainV2(); - - FakeAppleKeychainV2* keychain() { return keychain_.get(); } - - void SetUVMethod(UVMethod uv_method); - - private: - std::unique_ptr keychain_; -}; - -} // namespace crypto - -#endif // CRYPTO_SCOPED_FAKE_APPLE_KEYCHAIN_V2_H_ diff --git a/naiveproxy/src/crypto/scoped_fake_apple_keychain_v2.mm b/naiveproxy/src/crypto/scoped_fake_apple_keychain_v2.mm deleted file mode 100644 index 2624311710..0000000000 --- a/naiveproxy/src/crypto/scoped_fake_apple_keychain_v2.mm +++ /dev/null @@ -1,27 +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 "crypto/scoped_fake_apple_keychain_v2.h" - -#include - -#include "crypto/fake_apple_keychain_v2.h" - -namespace crypto { - -ScopedFakeAppleKeychainV2::ScopedFakeAppleKeychainV2( - const std::string& keychain_access_group) - : keychain_(std::make_unique(keychain_access_group)) { - AppleKeychainV2::SetInstanceOverride(keychain_.get()); -} - -ScopedFakeAppleKeychainV2::~ScopedFakeAppleKeychainV2() { - AppleKeychainV2::ClearInstanceOverride(); -} - -void ScopedFakeAppleKeychainV2::SetUVMethod(UVMethod uv_method) { - keychain_->set_uv_method(uv_method); -} - -} // namespace crypto diff --git a/naiveproxy/src/crypto/secure_hash.cc b/naiveproxy/src/crypto/secure_hash.cc index 61896e159f..06c3070a1c 100644 --- a/naiveproxy/src/crypto/secure_hash.cc +++ b/naiveproxy/src/crypto/secure_hash.cc @@ -2,15 +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/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "crypto/secure_hash.h" #include +#include "base/compiler_specific.h" #include "base/memory/ptr_util.h" #include "base/notimplemented.h" #include "base/pickle.h" @@ -27,7 +23,7 @@ class SecureHashSHA256 : public SecureHash { SecureHashSHA256() { SHA256_Init(&ctx_); } SecureHashSHA256(const SecureHashSHA256& other) { - memcpy(&ctx_, &other.ctx_, sizeof(ctx_)); + UNSAFE_TODO(memcpy(&ctx_, &other.ctx_, sizeof(ctx_))); } ~SecureHashSHA256() override { @@ -59,7 +55,7 @@ class SecureHashSHA512 : public SecureHash { SecureHashSHA512() { SHA512_Init(&ctx_); } SecureHashSHA512(const SecureHashSHA512& other) { - memcpy(&ctx_, &other.ctx_, sizeof(ctx_)); + UNSAFE_TODO(memcpy(&ctx_, &other.ctx_, sizeof(ctx_))); } ~SecureHashSHA512() override { OPENSSL_cleanse(&ctx_, sizeof(ctx_)); } diff --git a/naiveproxy/src/crypto/sign.cc b/naiveproxy/src/crypto/sign.cc index 7535dee37d..f23bd110f3 100644 --- a/naiveproxy/src/crypto/sign.cc +++ b/naiveproxy/src/crypto/sign.cc @@ -14,14 +14,31 @@ namespace crypto::sign { namespace { -bool CanUseKeyForSignatureKind(SignatureKind kind, - const crypto::keypair::PrivateKey& key) { - return true; -} +enum SignatureMode { + kOneShot, + kStreaming, +}; bool CanUseKeyForSignatureKind(SignatureKind kind, - const crypto::keypair::PublicKey& key) { - return true; + const EVP_PKEY* key, + SignatureMode mode) { + // There is a separate EVP_PKEY_RSA_PSS value that this can return for + // PSS-specific keys, but it's not used by PublicKey or PrivateKey. + const int id = EVP_PKEY_id(key); + switch (kind) { + case RSA_PKCS1_SHA1: + case RSA_PKCS1_SHA256: + case RSA_PSS_SHA256: + // There exists an EVP_PKEY_RSA_PSS key type for RSA-PSS-specific keys, + // but BoringSSL doesn't implement it and Chromium doesn't use it. + return id == EVP_PKEY_RSA; + case ECDSA_SHA256: + return id == EVP_PKEY_EC; + case ED25519: + return id == EVP_PKEY_ED25519 && mode == kOneShot; + } + + return false; } const EVP_MD* DigestForSignatureKind(SignatureKind kind) { @@ -34,6 +51,16 @@ const EVP_MD* DigestForSignatureKind(SignatureKind kind) { return EVP_sha256(); case ECDSA_SHA256: return EVP_sha256(); + case ED25519: + return nullptr; + } +} + +void ConfigurePkeyCtx(EVP_PKEY_CTX* pkctx, SignatureKind kind) { + if (kind == RSA_PSS_SHA256) { + CHECK(EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING)); + CHECK(EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, DigestForSignatureKind(kind))); + CHECK(EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, RSA_PSS_SALTLEN_DIGEST)); } } @@ -42,36 +69,51 @@ const EVP_MD* DigestForSignatureKind(SignatureKind kind) { std::vector Sign(SignatureKind kind, const crypto::keypair::PrivateKey& key, base::span data) { - Signer signer(kind, key); - signer.Update(data); - return signer.Finish(); + CHECK(CanUseKeyForSignatureKind(kind, key.key(), kOneShot)); + + const EVP_MD* const md = DigestForSignatureKind(kind); + EVP_PKEY_CTX* pkctx; + bssl::UniquePtr context(EVP_MD_CTX_new()); + CHECK(EVP_DigestSignInit(context.get(), &pkctx, md, nullptr, + const_cast(key.key()))); + ConfigurePkeyCtx(pkctx, kind); + + size_t len = 0; + CHECK(EVP_DigestSign(context.get(), nullptr, &len, data.data(), data.size())); + std::vector result(len); + CHECK(EVP_DigestSign(context.get(), result.data(), &len, data.data(), + data.size())); + result.resize(len); + return result; } bool Verify(SignatureKind kind, const crypto::keypair::PublicKey& key, base::span data, base::span signature) { - Verifier verifier(kind, key, signature); - verifier.Update(data); - return verifier.Finish(); + CHECK(CanUseKeyForSignatureKind(kind, key.key(), kOneShot)); + + const EVP_MD* const md = DigestForSignatureKind(kind); + EVP_PKEY_CTX* pkctx; + bssl::UniquePtr context(EVP_MD_CTX_new()); + CHECK(EVP_DigestVerifyInit(context.get(), &pkctx, md, nullptr, + const_cast(key.key()))); + ConfigurePkeyCtx(pkctx, kind); + + return EVP_DigestVerify(context.get(), signature.data(), signature.size(), + data.data(), data.size()) == 1; } Signer::Signer(SignatureKind kind, crypto::keypair::PrivateKey key) : key_(key), sign_context_(EVP_MD_CTX_new()) { - CHECK(CanUseKeyForSignatureKind(kind, key)); + CHECK(CanUseKeyForSignatureKind(kind, key.key(), kStreaming)); OpenSSLErrStackTracer err_tracer(FROM_HERE); const EVP_MD* const md = DigestForSignatureKind(kind); EVP_PKEY_CTX* pkctx; CHECK( EVP_DigestSignInit(sign_context_.get(), &pkctx, md, nullptr, key.key())); - - if (kind == RSA_PSS_SHA256) { - CHECK(EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING)); - CHECK(EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, md)); - // -1 here means "use digest's length" - CHECK(EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, -1)); - } + ConfigurePkeyCtx(pkctx, kind); } Signer::~Signer() = default; @@ -97,7 +139,7 @@ Verifier::Verifier(SignatureKind kind, base::span signature) : key_(key), verify_context_(EVP_MD_CTX_new()) { OpenSSLErrStackTracer err_tracer(FROM_HERE); - CHECK(CanUseKeyForSignatureKind(kind, key)); + CHECK(CanUseKeyForSignatureKind(kind, key.key(), kStreaming)); signature_.resize(signature.size()); base::span(signature_).copy_from(signature); @@ -105,13 +147,7 @@ Verifier::Verifier(SignatureKind kind, const EVP_MD* const md = DigestForSignatureKind(kind); CHECK(EVP_DigestVerifyInit(verify_context_.get(), &pkctx, md, nullptr, key.key())); - - if (kind == RSA_PSS_SHA256) { - CHECK(EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING)); - CHECK(EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, md)); - // -1 here means "use digest's length" - CHECK(EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, -1)); - } + ConfigurePkeyCtx(pkctx, kind); } Verifier::~Verifier() = default; diff --git a/naiveproxy/src/crypto/sign.h b/naiveproxy/src/crypto/sign.h index 40d7255e0d..beeba622e1 100644 --- a/naiveproxy/src/crypto/sign.h +++ b/naiveproxy/src/crypto/sign.h @@ -20,6 +20,10 @@ enum SignatureKind { // salt length of 32. RSA_PSS_SHA256, ECDSA_SHA256, + + // Note: Ed25519 cannot be used in streaming modes and has to be passed the + // entire message to sign; it does not take a separate hash function. + ED25519, }; // One-shot signature function: produce a signature of `data` using `key`. diff --git a/naiveproxy/src/crypto/signature_creator.cc b/naiveproxy/src/crypto/signature_creator.cc deleted file mode 100644 index 6a4ea1f700..0000000000 --- a/naiveproxy/src/crypto/signature_creator.cc +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "crypto/signature_creator.h" - -#include -#include - -#include "base/check.h" -#include "crypto/openssl_util.h" -#include "crypto/rsa_private_key.h" -#include "third_party/boringssl/src/include/openssl/evp.h" -#include "third_party/boringssl/src/include/openssl/rsa.h" - -namespace crypto { - -namespace { - -const EVP_MD* ToOpenSSLDigest(SignatureCreator::HashAlgorithm hash_alg) { - switch (hash_alg) { - case SignatureCreator::SHA1: - return EVP_sha1(); - case SignatureCreator::SHA256: - return EVP_sha256(); - } - return nullptr; -} - -int ToOpenSSLDigestType(SignatureCreator::HashAlgorithm hash_alg) { - switch (hash_alg) { - case SignatureCreator::SHA1: - return NID_sha1; - case SignatureCreator::SHA256: - return NID_sha256; - } - return NID_undef; -} - -} // namespace - -SignatureCreator::~SignatureCreator() = default; - -// static -std::unique_ptr SignatureCreator::Create( - RSAPrivateKey* key, - HashAlgorithm hash_alg) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - std::unique_ptr result(new SignatureCreator); - const EVP_MD* const digest = ToOpenSSLDigest(hash_alg); - DCHECK(digest); - if (!digest) { - return nullptr; - } - if (!EVP_DigestSignInit(result->sign_context_.get(), nullptr, digest, nullptr, - key->key())) { - return nullptr; - } - return result; -} - -// static -bool SignatureCreator::Sign(RSAPrivateKey* key, - HashAlgorithm hash_alg, - const uint8_t* data, - int data_len, - std::vector* signature) { - bssl::UniquePtr rsa_key(EVP_PKEY_get1_RSA(key->key())); - if (!rsa_key) - return false; - signature->resize(RSA_size(rsa_key.get())); - - unsigned int len = 0; - if (!RSA_sign(ToOpenSSLDigestType(hash_alg), data, data_len, - signature->data(), &len, rsa_key.get())) { - signature->clear(); - return false; - } - signature->resize(len); - return true; -} - -bool SignatureCreator::Update(const uint8_t* data_part, int data_part_len) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - return !!EVP_DigestSignUpdate(sign_context_.get(), data_part, data_part_len); -} - -bool SignatureCreator::Final(std::vector* signature) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - - // Determine the maximum length of the signature. - size_t len = 0; - if (!EVP_DigestSignFinal(sign_context_.get(), nullptr, &len)) { - signature->clear(); - return false; - } - signature->resize(len); - - // Sign it. - if (!EVP_DigestSignFinal(sign_context_.get(), signature->data(), &len)) { - signature->clear(); - return false; - } - signature->resize(len); - return true; -} - -SignatureCreator::SignatureCreator() : sign_context_(EVP_MD_CTX_new()) {} - -} // namespace crypto diff --git a/naiveproxy/src/crypto/signature_creator.h b/naiveproxy/src/crypto/signature_creator.h deleted file mode 100644 index 88fcc24dfe..0000000000 --- a/naiveproxy/src/crypto/signature_creator.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// This interface is deprecated and being removed: https://crbug.com/406190025. -// New users should use crypto/sign instead. - -#ifndef CRYPTO_SIGNATURE_CREATOR_H_ -#define CRYPTO_SIGNATURE_CREATOR_H_ - -#include - -#include -#include - -#include "build/build_config.h" -#include "crypto/crypto_export.h" -#include "third_party/boringssl/src/include/openssl/base.h" - -namespace crypto { - -class RSAPrivateKey; - -// Signs data using a bare private key (as opposed to a full certificate). -// Currently can only sign data using SHA-1 or SHA-256 with RSA PKCS#1v1.5. -// TODO(https://crbug.com/406190025): Delete this. -class CRYPTO_EXPORT SignatureCreator { - public: - // The set of supported hash functions. Extend as required. - enum HashAlgorithm { - SHA1, - SHA256, - }; - - SignatureCreator(const SignatureCreator&) = delete; - SignatureCreator& operator=(const SignatureCreator&) = delete; - - ~SignatureCreator(); - - // Create an instance. The caller must ensure that the provided PrivateKey - // instance outlives the created SignatureCreator. Uses the HashAlgorithm - // specified. - static std::unique_ptr Create(RSAPrivateKey* key, - HashAlgorithm hash_alg); - - // Signs the precomputed |hash_alg| digest |data| using private |key| as - // specified in PKCS #1 v1.5. - static bool Sign(RSAPrivateKey* key, - HashAlgorithm hash_alg, - const uint8_t* data, - int data_len, - std::vector* signature); - - // Update the signature with more data. - bool Update(const uint8_t* data_part, int data_part_len); - - // Finalize the signature. - bool Final(std::vector* signature); - - private: - // Private constructor. Use the Create() method instead. - SignatureCreator(); - - bssl::UniquePtr sign_context_; -}; - -} // namespace crypto - -#endif // CRYPTO_SIGNATURE_CREATOR_H_ diff --git a/naiveproxy/src/crypto/signature_verifier.cc b/naiveproxy/src/crypto/signature_verifier.cc index 833a3dfb25..126027bb5e 100644 --- a/naiveproxy/src/crypto/signature_verifier.cc +++ b/naiveproxy/src/crypto/signature_verifier.cc @@ -2,16 +2,12 @@ // 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 #include "base/check_op.h" +#include "base/compiler_specific.h" #include "crypto/openssl_util.h" #include "third_party/boringssl/src/include/openssl/bytestring.h" #include "third_party/boringssl/src/include/openssl/digest.h" @@ -57,7 +53,8 @@ bool SignatureVerifier::VerifyInit(SignatureAlgorithm signature_algorithm, return false; verify_context_ = std::make_unique(); - signature_.assign(signature.data(), signature.data() + signature.size()); + signature_.assign(signature.data(), + UNSAFE_TODO(signature.data() + signature.size())); CBS cbs; CBS_init(&cbs, public_key_info.data(), public_key_info.size()); diff --git a/naiveproxy/src/crypto/unexportable_key_mac.mm b/naiveproxy/src/crypto/unexportable_key_mac.mm index 750ce17bb3..ad232acc16 100644 --- a/naiveproxy/src/crypto/unexportable_key_mac.mm +++ b/naiveproxy/src/crypto/unexportable_key_mac.mm @@ -34,8 +34,8 @@ #include "base/strings/stringprintf.h" #include "base/strings/sys_string_conversions.h" #include "base/threading/scoped_blocking_call.h" -#include "crypto/apple_keychain_util.h" -#include "crypto/apple_keychain_v2.h" +#include "crypto/apple/keychain_util.h" +#include "crypto/apple/keychain_v2.h" #include "crypto/signature_verifier.h" #include "crypto/unexportable_key_mac.h" #include "crypto/unexportable_key_metrics.h" @@ -130,9 +130,9 @@ class UnexportableSigningKeyMac : public UnexportableSigningKey { key_attributes, kSecAttrApplicationLabel))) { base::apple::ScopedCFTypeRef public_key( - AppleKeychainV2::GetInstance().KeyCopyPublicKey(key_.get())); + crypto::apple::KeychainV2::GetInstance().KeyCopyPublicKey(key_.get())); base::apple::ScopedCFTypeRef x962_bytes( - AppleKeychainV2::GetInstance().KeyCopyExternalRepresentation( + crypto::apple::KeychainV2::GetInstance().KeyCopyExternalRepresentation( public_key.get(), /*error=*/nil)); CHECK(x962_bytes); base::span x962_span = @@ -168,7 +168,7 @@ class UnexportableSigningKeyMac : public UnexportableSigningKey { NSData* nsdata = [NSData dataWithBytes:data.data() length:data.size()]; base::apple::ScopedCFTypeRef error; base::apple::ScopedCFTypeRef signature( - AppleKeychainV2::GetInstance().KeyCreateSignature( + crypto::apple::KeychainV2::GetInstance().KeyCreateSignature( key_.get(), algorithm, NSToCFPtrCast(nsdata), error.InitializeInto())); if (!signature) { @@ -292,7 +292,7 @@ UnexportableKeyProviderMac::GenerateSigningKeySlowly( base::apple::ScopedCFTypeRef error; base::apple::ScopedCFTypeRef private_key( - AppleKeychainV2::GetInstance().KeyCreateRandomKey( + crypto::apple::KeychainV2::GetInstance().KeyCreateRandomKey( NSToCFPtrCast(attributes), error.InitializeInto())); if (!private_key) { LOG(ERROR) << "Could not create private key: " << error.get(); @@ -300,7 +300,8 @@ UnexportableKeyProviderMac::GenerateSigningKeySlowly( return nullptr; } base::apple::ScopedCFTypeRef key_metadata = - AppleKeychainV2::GetInstance().KeyCopyAttributes(private_key.get()); + crypto::apple::KeychainV2::GetInstance().KeyCopyAttributes( + private_key.get()); return std::make_unique(std::move(private_key), key_metadata.get()); } @@ -330,7 +331,7 @@ UnexportableKeyProviderMac::FromWrappedSigningKeySlowly( if (lacontext) { query[CFToNSPtrCast(kSecUseAuthenticationContext)] = lacontext; } - OSStatus status = AppleKeychainV2::GetInstance().ItemCopyMatching( + OSStatus status = crypto::apple::KeychainV2::GetInstance().ItemCopyMatching( NSToCFPtrCast(query), key_data.InitializeInto()); CFDictionaryRef key_attributes = base::apple::CFCast(key_data.get()); @@ -360,7 +361,7 @@ bool UnexportableKeyProviderMac::DeleteSigningKeySlowly( [NSData dataWithBytes:wrapped_key.data() length:wrapped_key.size()], }; OSStatus result = - AppleKeychainV2::GetInstance().ItemDelete(NSToCFPtrCast(query)); + crypto::apple::KeychainV2::GetInstance().ItemDelete(NSToCFPtrCast(query)); return result == errSecSuccess; } @@ -369,14 +370,14 @@ std::unique_ptr GetUnexportableKeyProviderMac( CHECK(!config.keychain_access_group.empty()) << "A keychain access group must be set when using unexportable keys on " "macOS"; - if (![AppleKeychainV2::GetInstance().GetTokenIDs() + if (![crypto::apple::KeychainV2::GetInstance().GetTokenIDs() containsObject:CFToNSPtrCast(kSecAttrTokenIDSecureEnclave)]) { return nullptr; } // Inspecting the binary for the entitlement is not available on iOS, assume // it is available. #if !BUILDFLAG(IS_IOS) - if (!ExecutableHasKeychainAccessGroupEntitlement( + if (!crypto::apple::ExecutableHasKeychainAccessGroupEntitlement( config.keychain_access_group)) { return nullptr; } diff --git a/naiveproxy/src/crypto/user_verifying_key_mac.mm b/naiveproxy/src/crypto/user_verifying_key_mac.mm index 06509149d1..900b3c07fc 100644 --- a/naiveproxy/src/crypto/user_verifying_key_mac.mm +++ b/naiveproxy/src/crypto/user_verifying_key_mac.mm @@ -21,7 +21,7 @@ #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/apple/keychain_v2.h" #include "crypto/scoped_lacontext.h" #include "crypto/unexportable_key.h" #include "crypto/unexportable_key_mac.h" @@ -239,7 +239,7 @@ void AreMacUnexportableKeysAvailable(UserVerifyingKeyProvider::Config config, return; } std::move(callback).Run( - AppleKeychainV2::GetInstance().LAContextCanEvaluatePolicy( + crypto::apple::KeychainV2::GetInstance().LAContextCanEvaluatePolicy( LAPolicyDeviceOwnerAuthentication, /*error=*/nil)); } diff --git a/naiveproxy/src/extensions/buildflags/BUILD.gn b/naiveproxy/src/extensions/buildflags/BUILD.gn new file mode 100644 index 0000000000..cda6c650f7 --- /dev/null +++ b/naiveproxy/src/extensions/buildflags/BUILD.gn @@ -0,0 +1,23 @@ +# Copyright 2016 The Chromium Authors +# 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("//extensions/buildflags/buildflags.gni") + +# TODO(crbug.com/41324418): Assert that extensions are enabled. + +# This file is in a separate directory so all targets in the build can refer to +# the buildflag header to get the necessary preprocessor defines without +# bringing in all of extensions. Other targets can depend on this target +# regardless of whether extensions are enabled. + +buildflag_header("buildflags") { + header = "buildflags.h" + flags = [ + "ENABLE_EXTENSIONS=$enable_extensions", + "ENABLE_DESKTOP_ANDROID_EXTENSIONS=$enable_desktop_android_extensions", + "ENABLE_EXTENSIONS_CORE=$enable_extensions_core", + "ENABLE_PLATFORM_APPS=$enable_platform_apps", + ] +} diff --git a/naiveproxy/src/extensions/buildflags/buildflags.gni b/naiveproxy/src/extensions/buildflags/buildflags.gni new file mode 100644 index 0000000000..5cba68c398 --- /dev/null +++ b/naiveproxy/src/extensions/buildflags/buildflags.gni @@ -0,0 +1,49 @@ +# Copyright 2016 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/cast.gni") +import("//build/config/chrome_build.gni") + +declare_args() { + # `enable_extensions` controls whether the full and stable extensions platform + # is compiled. + enable_extensions = !is_android && !is_ios && !is_castos && !is_fuchsia + + # `enable_desktop_android_extensions` is an experimental flag used in + # prototypes of desktop-focused android-powered builds. This is very much + # in-development, non-stable, and likely to crash at any given moment. + # + # Introducing a separate flag like this has the unfortunate effect of leading + # to a lot of `if BUILDFLAG(ENABLE_EXTENSIONS)` checks in extensions code + # itself, since those checks are instead the equivalent of + # `if BUILDFLAG(ENABLE_FULL_EXTENSIONS_SYSTEM)`. However, we don't want to + # change the stable, production-utilized `enable_extensions` flag for this + # experimental build. + # + # As the experimental build progresses, there should be fewer of those + # checks littered around the extensions codebase, since more and more of + # the extensions code will be included in the desktop android variant. + # + # TODO(https://crbug.com/356905053): Continue expanding the scope of + # enable_desktop_android_extensions. + enable_desktop_android_extensions = is_desktop_android +} + +# Note: GN forbids relying on args from the same declare_args() block, so we +# need this separate from the block above. +declare_args() { + # A control for whether support for platform apps should be compiled into the + # browser. + # TODO(https://crbug.com/41407868): This doesn't belong here; extensions code + # shouldn't rely on platform apps at all. But at least this lets it be + # toggled / if-def'd. + enable_platform_apps = enable_extensions + + # Whether the core extensions system is enabled. This prevents many callsites + # from needing blocks for + # `if (enable_extensions || enable_desktop_android_extensions)`, since the + # core handling in each of these implementations is similar. + enable_extensions_core = + enable_extensions || enable_desktop_android_extensions +} diff --git a/naiveproxy/src/ios/features.gni b/naiveproxy/src/ios/features.gni index 2e029796e1..14fd64fee4 100644 --- a/naiveproxy/src/ios/features.gni +++ b/naiveproxy/src/ios/features.gni @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/apple/mobile_config.gni") + declare_args() { # Control whether only WebKit is build. This is used by bots building # WebKit for mac but incorrectly setting `target_os="ios"`. @@ -19,7 +21,8 @@ declare_args() { # Control whether //ios/chrome and //ios/web targets are build. This # is used by bots from projects based on top of Chromium that want to # only reuse shared code (//ios/net, //remoting/ios, ...). - ios_build_chrome = true + # This is false by default on iOS-based platforms like tvOS. + ios_build_chrome = target_platform == "iphoneos" # Controls whether universal links are blocked from opening native apps # when the user is browsing in off the record mode. diff --git a/naiveproxy/src/net/BUILD.gn b/naiveproxy/src/net/BUILD.gn index c1febca710..da122b4419 100644 --- a/naiveproxy/src/net/BUILD.gn +++ b/naiveproxy/src/net/BUILD.gn @@ -299,7 +299,6 @@ component("net") { "base/task/task_runner.cc", "base/task/task_runner.h", "base/trace_event_stub.h", - "base/tracing.h", "base/transport_info.cc", "base/transport_info.h", "base/upload_bytes_element_reader.cc", @@ -456,6 +455,7 @@ component("net") { "cookies/static_cookie_policy.h", "cookies/unique_cookie_key.cc", "cookies/unique_cookie_key.h", + "device_bound_sessions/deletion_reason.h", "device_bound_sessions/session_access.cc", "device_bound_sessions/session_access.h", "device_bound_sessions/session_key.cc", @@ -723,7 +723,6 @@ component("net") { "http/transport_security_persister.cc", "http/transport_security_persister.h", "http/transport_security_state.h", - "http/transport_security_state_source.cc", "http/transport_security_state_source.h", "http/url_security_manager.cc", "http/url_security_manager.h", @@ -871,6 +870,8 @@ component("net") { "quic/quic_crypto_client_config_handle.h", "quic/quic_crypto_client_stream_factory.cc", "quic/quic_crypto_client_stream_factory.h", + "quic/quic_endpoint.cc", + "quic/quic_endpoint.h", "quic/quic_event_logger.cc", "quic/quic_event_logger.h", "quic/quic_http3_logger.cc", @@ -889,6 +890,10 @@ component("net") { "quic/quic_session_alias_key.h", "quic/quic_session_attempt.cc", "quic/quic_session_attempt.h", + "quic/quic_session_attempt_manager.cc", + "quic/quic_session_attempt_manager.h", + "quic/quic_session_attempt_request.cc", + "quic/quic_session_attempt_request.h", "quic/quic_session_key.cc", "quic/quic_session_key.h", "quic/quic_session_pool.cc", @@ -1150,7 +1155,7 @@ component("net") { "//components/miracle_parameter/common", "//components/network_time/time_tracker", "//net/http:transport_security_state_generated_files", - "//third_party/simdutf:simdutf", + "//third_party/simdutf", ] public_deps = [ @@ -1222,6 +1227,8 @@ component("net") { sources += [ "device_bound_sessions/cookie_craving.cc", "device_bound_sessions/cookie_craving.h", + "device_bound_sessions/host_patterns.cc", + "device_bound_sessions/host_patterns.h", "device_bound_sessions/jwk_utils.cc", "device_bound_sessions/jwk_utils.h", "device_bound_sessions/registration_fetcher.cc", @@ -1259,8 +1266,8 @@ component("net") { deps += [ ":device_bound_sessions_storage_proto", "//components/sqlite_proto", - "//components/unexportable_keys:unexportable_keys", - "//sql:sql", + "//components/unexportable_keys", + "//sql", ] } @@ -1778,13 +1785,18 @@ component("net") { sources += [ "disk_cache/sql/cache_entry_key.cc", "disk_cache/sql/cache_entry_key.h", + "disk_cache/sql/exclusive_operation_coordinator.cc", + "disk_cache/sql/exclusive_operation_coordinator.h", "disk_cache/sql/sql_backend_constants.h", "disk_cache/sql/sql_backend_impl.cc", "disk_cache/sql/sql_backend_impl.h", + "disk_cache/sql/sql_entry_impl.cc", + "disk_cache/sql/sql_entry_impl.h", "disk_cache/sql/sql_persistent_store.cc", "disk_cache/sql/sql_persistent_store.h", + "disk_cache/sql/sql_persistent_store_queries.h", ] - deps += [ "//sql:sql" ] + deps += [ "//sql" ] } } diff --git a/naiveproxy/src/net/android/BUILD.gn b/naiveproxy/src/net/android/BUILD.gn index 1abc97e929..bb8c0ff767 100644 --- a/naiveproxy/src/net/android/BUILD.gn +++ b/naiveproxy/src/net/android/BUILD.gn @@ -186,9 +186,6 @@ android_apk("net_test_support_apk") { # Used as an additional_apk in test scripts. never_incremental = true - # Required on Android Q+ to read from /sdcard when installing certs. - target_sdk_version = 28 - deps = [ ":net_java_test_support", ":net_test_support_provider_java", diff --git a/naiveproxy/src/net/android/http_auth_negotiate_android.cc b/naiveproxy/src/net/android/http_auth_negotiate_android.cc index eb5cf7f30b..12e2ba744f 100644 --- a/naiveproxy/src/net/android/http_auth_negotiate_android.cc +++ b/naiveproxy/src/net/android/http_auth_negotiate_android.cc @@ -38,7 +38,6 @@ JavaNegotiateResultWrapper::JavaNegotiateResultWrapper( JavaNegotiateResultWrapper::~JavaNegotiateResultWrapper() = default; void JavaNegotiateResultWrapper::SetResult(JNIEnv* env, - const JavaParamRef& obj, int result, const JavaParamRef& token) { // This will be called on the UI thread, so we have to post a task back to the diff --git a/naiveproxy/src/net/android/http_auth_negotiate_android.h b/naiveproxy/src/net/android/http_auth_negotiate_android.h index 42b766603b..7fde8ccf40 100644 --- a/naiveproxy/src/net/android/http_auth_negotiate_android.h +++ b/naiveproxy/src/net/android/http_auth_negotiate_android.h @@ -48,7 +48,6 @@ class NET_EXPORT_PRIVATE JavaNegotiateResultWrapper { base::OnceCallback thread_safe_callback); void SetResult(JNIEnv* env, - const base::android::JavaParamRef& obj, int result, const base::android::JavaParamRef& token); diff --git a/naiveproxy/src/net/android/network_change_notifier_delegate_android.cc b/naiveproxy/src/net/android/network_change_notifier_delegate_android.cc index 75a9dcc4e9..b23af7ea07 100644 --- a/naiveproxy/src/net/android/network_change_notifier_delegate_android.cc +++ b/naiveproxy/src/net/android/network_change_notifier_delegate_android.cc @@ -197,7 +197,6 @@ bool NetworkChangeNotifierDelegateAndroid::IsDefaultNetworkActive() { void NetworkChangeNotifierDelegateAndroid::NotifyConnectionCostChanged( JNIEnv* env, - const JavaParamRef& obj, jint new_connection_cost) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); const ConnectionCost actual_connection_cost = @@ -210,7 +209,6 @@ void NetworkChangeNotifierDelegateAndroid::NotifyConnectionCostChanged( void NetworkChangeNotifierDelegateAndroid::NotifyConnectionTypeChanged( JNIEnv* env, - const JavaParamRef& obj, jint new_connection_type, jlong default_netid) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); @@ -258,7 +256,6 @@ jint NetworkChangeNotifierDelegateAndroid::GetConnectionCost(JNIEnv*, jobject) { void NetworkChangeNotifierDelegateAndroid::NotifyConnectionSubtypeChanged( JNIEnv* env, - const JavaParamRef& obj, jint subtype) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); double new_max_bandwidth = @@ -275,7 +272,6 @@ void NetworkChangeNotifierDelegateAndroid::NotifyConnectionSubtypeChanged( void NetworkChangeNotifierDelegateAndroid::NotifyOfNetworkConnect( JNIEnv* env, - const JavaParamRef& obj, jlong net_id, jint connection_type) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); @@ -303,7 +299,6 @@ void NetworkChangeNotifierDelegateAndroid::NotifyOfNetworkConnect( void NetworkChangeNotifierDelegateAndroid::NotifyOfNetworkSoonToDisconnect( JNIEnv* env, - const JavaParamRef& obj, jlong net_id) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); handles::NetworkHandle network = net_id; @@ -319,7 +314,6 @@ void NetworkChangeNotifierDelegateAndroid::NotifyOfNetworkSoonToDisconnect( void NetworkChangeNotifierDelegateAndroid::NotifyOfNetworkDisconnect( JNIEnv* env, - const JavaParamRef& obj, jlong net_id) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); handles::NetworkHandle network = net_id; @@ -337,7 +331,6 @@ void NetworkChangeNotifierDelegateAndroid::NotifyOfNetworkDisconnect( void NetworkChangeNotifierDelegateAndroid::NotifyPurgeActiveNetworkList( JNIEnv* env, - const JavaParamRef& obj, const JavaParamRef& active_networks) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); NetworkList active_network_list; @@ -360,7 +353,7 @@ void NetworkChangeNotifierDelegateAndroid::NotifyPurgeActiveNetworkList( } } for (auto disconnected_network : disconnected_networks) - NotifyOfNetworkDisconnect(env, obj, disconnected_network); + NotifyOfNetworkDisconnect(env, disconnected_network); } void NetworkChangeNotifierDelegateAndroid::NotifyOfDefaultNetworkActive( diff --git a/naiveproxy/src/net/android/network_change_notifier_delegate_android.h b/naiveproxy/src/net/android/network_change_notifier_delegate_android.h index cb100075df..36ca4ffdb0 100644 --- a/naiveproxy/src/net/android/network_change_notifier_delegate_android.h +++ b/naiveproxy/src/net/android/network_change_notifier_delegate_android.h @@ -78,21 +78,16 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierDelegateAndroid { // the connection type changes. This updates the current connection type seen // by this class and forwards the notification to the observers that // subscribed through RegisterObserver(). - void NotifyConnectionTypeChanged( - JNIEnv* env, - const base::android::JavaParamRef& obj, - jint new_connection_type, - jlong default_netid); + void NotifyConnectionTypeChanged(JNIEnv* env, + jint new_connection_type, + jlong default_netid); jint GetConnectionType(JNIEnv* env, jobject obj) const; // Called from NetworkChangeNotifier.java on the JNI thread whenever // the connection cost changes. This updates the current connection cost seen // by this class and forwards the notification to the observers that // subscribed through RegisterObserver(). - void NotifyConnectionCostChanged( - JNIEnv* env, - const base::android::JavaParamRef& obj, - jint new_connection_cost); + void NotifyConnectionCostChanged(JNIEnv* env, jint new_connection_cost); jint GetConnectionCost(JNIEnv* env, jobject obj); // Called from NetworkChangeNotifier.java on the JNI thread whenever @@ -100,10 +95,7 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierDelegateAndroid { // max bandwidth and connection subtype seen by this class and forwards the // max bandwidth change to the observers that subscribed through // RegisterObserver(). - void NotifyConnectionSubtypeChanged( - JNIEnv* env, - const base::android::JavaParamRef& obj, - jint subtype); + void NotifyConnectionSubtypeChanged(JNIEnv* env, jint subtype); // Called from NetworkChangeNotifier.java on the JNI thread to push // down notifications of network connectivity events. These functions in @@ -115,20 +107,12 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierDelegateAndroid { // For descriptions of what individual calls mean, see // NetworkChangeNotifierAutoDetect.Observer functions of the same names. void NotifyOfNetworkConnect(JNIEnv* env, - const base::android::JavaParamRef& obj, jlong net_id, jint connection_type); - void NotifyOfNetworkSoonToDisconnect( - JNIEnv* env, - const base::android::JavaParamRef& obj, - jlong net_id); - void NotifyOfNetworkDisconnect( - JNIEnv* env, - const base::android::JavaParamRef& obj, - jlong net_id); + void NotifyOfNetworkSoonToDisconnect(JNIEnv* env, jlong net_id); + void NotifyOfNetworkDisconnect(JNIEnv* env, jlong net_id); void NotifyPurgeActiveNetworkList( JNIEnv* env, - const base::android::JavaParamRef& obj, const base::android::JavaParamRef& active_networks); // Called from NetworkActiveNotifier.java on the JNI thread to push down diff --git a/naiveproxy/src/net/base/address_list.h b/naiveproxy/src/net/base/address_list.h index c832d92333..8087e7b981 100644 --- a/naiveproxy/src/net/base/address_list.h +++ b/naiveproxy/src/net/base/address_list.h @@ -18,10 +18,6 @@ struct addrinfo; -namespace base { -class Value; -} - namespace net { class IPAddress; @@ -78,6 +74,7 @@ class NET_EXPORT AddressList { using iterator = std::vector::iterator; using const_iterator = std::vector::const_iterator; + using value_type = IPEndPoint; size_t size() const { return endpoints_.size(); } bool empty() const { return endpoints_.empty(); } diff --git a/naiveproxy/src/net/base/apple/url_conversions.h b/naiveproxy/src/net/base/apple/url_conversions.h index 3cf655cbf9..36eab18ecd 100644 --- a/naiveproxy/src/net/base/apple/url_conversions.h +++ b/naiveproxy/src/net/base/apple/url_conversions.h @@ -13,13 +13,16 @@ class GURL; namespace net { // Method for creating a valid NSURL (compliant with RFC 1738/1808/2396) from a -// valid GURL. This method will return nil if the |url| is not valid. +// valid GURL. This method will return nil if `url.is_valid() == false`. +// As GURL and NSURL valid URL sets do not match, it is possible that this +// function returns nil even if `url.is_valid() == true`. The result must always +// be checked for nullity. // Note that NSURLs should *always* be created from GURLs, so that GURL // sanitization rules are applied everywhere. NET_EXPORT NSURL* NSURLWithGURL(const GURL& url); // Method for creating a valid GURL from a NSURL. This method will return an -// empty GURL if the |url| is nil. +// empty GURL if the `url` is nil and can return an invalid GURL. NET_EXPORT GURL GURLWithNSURL(NSURL* url); } // namespace net diff --git a/naiveproxy/src/net/base/cache_type.h b/naiveproxy/src/net/base/cache_type.h index dee7e269fb..11648d1501 100644 --- a/naiveproxy/src/net/base/cache_type.h +++ b/naiveproxy/src/net/base/cache_type.h @@ -5,6 +5,8 @@ #ifndef NET_BASE_CACHE_TYPE_H_ #define NET_BASE_CACHE_TYPE_H_ +#include "net/disk_cache/buildflags.h" + namespace net { // The types of caches that can be created. @@ -16,7 +18,6 @@ enum CacheType { // cases where auto-eviction is not desired: // e.g. cache_storage, service worker script cache SHADER_CACHE, // Backing store for the GL shader cache. - PNACL_CACHE, // Backing store the PNaCl translation cache GENERATED_BYTE_CODE_CACHE, // Backing store for renderer generated data like // bytecode for JavaScript. GENERATED_NATIVE_CODE_CACHE, // Backing store for renderer generated data @@ -30,7 +31,10 @@ enum CacheType { enum BackendType { CACHE_BACKEND_DEFAULT, CACHE_BACKEND_BLOCKFILE, // The |BackendImpl|. - CACHE_BACKEND_SIMPLE // The |SimpleBackendImpl|. + CACHE_BACKEND_SIMPLE, // The |SimpleBackendImpl|. +#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND) + CACHE_BACKEND_EXPERIMENTAL_SQL, +#endif // ENABLE_DISK_CACHE_SQL_BACKEND }; } // namespace net diff --git a/naiveproxy/src/net/base/connection_endpoint_metadata.cc b/naiveproxy/src/net/base/connection_endpoint_metadata.cc index b9085dd705..88a13af147 100644 --- a/naiveproxy/src/net/base/connection_endpoint_metadata.cc +++ b/naiveproxy/src/net/base/connection_endpoint_metadata.cc @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -39,6 +40,14 @@ ConnectionEndpointMetadata::ConnectionEndpointMetadata( ConnectionEndpointMetadata::ConnectionEndpointMetadata( ConnectionEndpointMetadata&&) = default; +bool ConnectionEndpointMetadata::operator<( + const ConnectionEndpointMetadata& other) const { + return std::tie(supported_protocol_alpns, ech_config_list, target_name, + trust_anchor_ids) < + std::tie(other.supported_protocol_alpns, other.ech_config_list, + other.target_name, other.trust_anchor_ids); +} + base::Value ConnectionEndpointMetadata::ToValue() const { base::Value::Dict dict; diff --git a/naiveproxy/src/net/base/connection_endpoint_metadata.h b/naiveproxy/src/net/base/connection_endpoint_metadata.h index dd92144007..93c7fecf8b 100644 --- a/naiveproxy/src/net/base/connection_endpoint_metadata.h +++ b/naiveproxy/src/net/base/connection_endpoint_metadata.h @@ -39,13 +39,22 @@ struct NET_EXPORT_PRIVATE ConnectionEndpointMetadata { ConnectionEndpointMetadata& operator=(ConnectionEndpointMetadata&&) = default; bool operator==(const ConnectionEndpointMetadata& other) const = default; + // Needed to be an element of std::set. + bool operator<(const ConnectionEndpointMetadata& other) const; base::Value ToValue() const; static std::optional FromValue( const base::Value& value); + // Returns true if this metadata describes an alternative endpoint (that is, + // from an HTTPS/SVCB record) and false if it is an authority endpoint (that + // is, fetching A/AAAA from the host directory). "Authority" in here refers to + // the addresses coming directly from the authority portion of the URL. See + // Section 1.3 of RFC 9460. + bool IsAlternative() const { return !supported_protocol_alpns.empty(); } + // ALPN strings for protocols supported by the endpoint. Empty for default - // non-protocol endpoint. + // authority endpoint, i.e. fetching A/AAAA directly without HTTPS/SVCB. std::vector supported_protocol_alpns; // If not empty, TLS Encrypted Client Hello config for the service. diff --git a/naiveproxy/src/net/base/data_url.cc b/naiveproxy/src/net/base/data_url.cc index e43507e909..a6bdeb4400 100644 --- a/naiveproxy/src/net/base/data_url.cc +++ b/naiveproxy/src/net/base/data_url.cc @@ -116,18 +116,6 @@ bool DataURL::Parse(const GURL& url, // The caller may not be interested in receiving the data. if (data) { - // Preserve spaces if dealing with text or xml input, same as mozilla: - // https://bugzilla.mozilla.org/show_bug.cgi?id=138052 - // but strip them otherwise: - // https://bugzilla.mozilla.org/show_bug.cgi?id=37200 - // (Spaces in a data URL should be escaped, which is handled below, so any - // spaces now are wrong. People expect to be able to enter them in the URL - // bar for text, and it can't hurt, so we allow it.) - // - // TODO(mmenke): Is removing all spaces reasonable? GURL removes trailing - // spaces itself, anyways. Should we just trim leading spaces instead? - // Allowing random intermediary spaces seems unnecessary. - std::string_view raw_body = media_type_and_body->second; // For base64, we may have url-escaped whitespace which is not part @@ -205,11 +193,10 @@ bool DataURL::Parse(const GURL& url, // `temp`'s storage needs to be outside feature check since `raw_body` is // a string_view. std::string temp; - // Strip whitespace for non-text MIME types. This is controlled either by - // the feature (finch kill switch) or an enterprise policy which sets the - // command line flag. - if (!base::FeatureList::IsEnabled(features::kKeepWhitespaceForDataUrls) || - HasRemoveWhitespaceCommandLineFlag()) { + // Strip whitespace for non-text MIME types if there's a command line flag + // indicating this needs to be done. The flag may be set by an enterprise + // policy. + if (HasRemoveWhitespaceCommandLineFlag()) { if (!(mime_type_value.compare(0, 5, "text/") == 0 || mime_type_value.find("xml") != std::string::npos)) { temp = std::string(raw_body); diff --git a/naiveproxy/src/net/base/data_url.h b/naiveproxy/src/net/base/data_url.h index e6d3d06733..f7d7c8e54f 100644 --- a/naiveproxy/src/net/base/data_url.h +++ b/naiveproxy/src/net/base/data_url.h @@ -18,9 +18,9 @@ namespace net { class HttpResponseHeaders; -// This command line switch provides a means to disable data URL whitespace -// kKeepWhitespaceForDataUrls feature flag. This is set part of an enterprise -// policy and is intended as a kill switch. +// When enabled, whitespace is removed from non-Base64 data URLs. This was the +// behavior of older versions of Chrome, and can be set part of an enterprise +// policy. inline constexpr std::string_view kRemoveWhitespaceForDataURLs = "remove-keep-whitespace-for-data-urls"; diff --git a/naiveproxy/src/net/base/features.cc b/naiveproxy/src/net/base/features.cc index fe35c6362b..91a1e8fbe4 100644 --- a/naiveproxy/src/net/base/features.cc +++ b/naiveproxy/src/net/base/features.cc @@ -10,6 +10,7 @@ #include "base/feature_list.h" #include "build/build_config.h" #include "net/base/cronet_buildflags.h" +#include "net/disk_cache/buildflags.h" #include "net/net_buildflags.h" #if BUILDFLAG(IS_WIN) @@ -144,6 +145,14 @@ BASE_FEATURE(kPartitionConnectionsByNetworkIsolationKey, "PartitionConnectionsByNetworkIsolationKey", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kPrefixCookieHttp, + "PrefixCookieHttp", + base::FEATURE_ENABLED_BY_DEFAULT); + +BASE_FEATURE(kPrefixCookieHostHttp, + "PrefixCookieHostHttp", + base::FEATURE_ENABLED_BY_DEFAULT); + BASE_FEATURE(kSearchEnginePreconnectInterval, "SearchEnginePreconnectInterval", base::FEATURE_DISABLED_BY_DEFAULT); @@ -181,6 +190,12 @@ BASE_FEATURE_PARAM(std::string, "QuicConnectionOptions", ""); +BASE_FEATURE_PARAM(bool, + kFallbackInLowPowerMode, + &kSearchEnginePreconnect2, + "FallbackInLowPowerMode", + false); + BASE_FEATURE(kShortLaxAllowUnsafeThreshold, "ShortLaxAllowUnsafeThreshold", base::FEATURE_DISABLED_BY_DEFAULT); @@ -536,8 +551,17 @@ const base::FeatureParam kIpPrivacyDisableForEnterpriseByDefault{ const base::FeatureParam kIpPrivacyEnableIppInDevTools{ &kEnableIpProtectionProxy, /*name=*/"IpPrivacyEnableIppInDevTools", + /*default_value=*/true}; + +const base::FeatureParam kIpPrivacyEnableIppPanelInDevTools{ + &kEnableIpProtectionProxy, + /*name=*/"kIpPrivacyEnableIppPanelInDevTools", /*default_value=*/false}; +BASE_FEATURE(kEnableIpPrivacyProxyAdvancedFallbackLogic, + "EnableIpPrivacyProxyAdvancedFallbackLogic", + base::FEATURE_ENABLED_BY_DEFAULT); + BASE_FEATURE(kExcludeLargeBodyReports, "ExcludeLargeReportBodies", base::FEATURE_ENABLED_BY_DEFAULT); @@ -657,6 +681,9 @@ BASE_FEATURE_PARAM(bool, BASE_FEATURE(kDeviceBoundSessionsRefreshQuota, "DeviceBoundSessionsRefreshQuota", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kDeviceBoundSessionsOriginTrialFeedback, + "DeviceBoundSessionsOriginTrialFeedback", + base::FEATURE_DISABLED_BY_DEFAULT); BASE_FEATURE(kPartitionProxyChains, "PartitionProxyChains", @@ -684,24 +711,21 @@ BASE_FEATURE(kReportingApiEnableEnterpriseCookieIssues, BASE_FEATURE(kSimdutfBase64Support, "SimdutfBase64Support", - base::FEATURE_DISABLED_BY_DEFAULT); +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) + base::FEATURE_ENABLED_BY_DEFAULT +#else + base::FEATURE_DISABLED_BY_DEFAULT +#endif +); BASE_FEATURE(kFurtherOptimizeParsingDataUrls, "FurtherOptimizeParsingDataUrls", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kKeepWhitespaceForDataUrls, - "KeepWhitespaceForDataUrls", - base::FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE(kNoVarySearchIgnoreUnrecognizedKeys, "NoVarySearchIgnoreUnrecognizedKeys", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kEncryptedAndPlaintextValuesAreInvalid, - "EncryptedAndPlaintextValuesAreInvalid", - base::FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE(kEnableStaticCTAPIEnforcement, "EnableStaticCTAPIEnforcement", base::FEATURE_ENABLED_BY_DEFAULT); @@ -711,11 +735,15 @@ BASE_FEATURE(kDiskCacheBackendExperiment, base::FEATURE_DISABLED_BY_DEFAULT); constexpr base::FeatureParam::Option kDiskCacheBackendOptions[] = { + {DiskCacheBackend::kDefault, "default"}, {DiskCacheBackend::kSimple, "simple"}, {DiskCacheBackend::kBlockfile, "blockfile"}, +#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND) + {DiskCacheBackend::kSql, "sql"}, +#endif // ENABLE_DISK_CACHE_SQL_BACKEND }; const base::FeatureParam kDiskCacheBackendParam{ - &kDiskCacheBackendExperiment, "backend", DiskCacheBackend::kBlockfile, + &kDiskCacheBackendExperiment, "backend", DiskCacheBackend::kDefault, &kDiskCacheBackendOptions}; BASE_FEATURE(kIgnoreHSTSForLocalhost, @@ -749,6 +777,12 @@ BASE_FEATURE(kHstsTopLevelNavigationsOnly, "HstsTopLevelNavigationsOnly", base::FEATURE_DISABLED_BY_DEFAULT); +#if BUILDFLAG(IS_WIN) +BASE_FEATURE(kHttpCacheMappedFileFlushWin, + "HttpCacheMappedFileFlushWin", + base::FEATURE_DISABLED_BY_DEFAULT); +#endif + BASE_FEATURE(kHttpCacheNoVarySearch, "HttpCacheNoVarySearch", base::FEATURE_DISABLED_BY_DEFAULT); @@ -759,6 +793,26 @@ BASE_FEATURE_PARAM(size_t, "max_entries", 1000); +// TODO(crbug.com/433551601): Change the default to `true` once it has been +// verified working. +BASE_FEATURE_PARAM(bool, + kHttpCacheNoVarySearchApplyToExternalHits, + &kHttpCacheNoVarySearch, + "apply_to_external_hits", + false); + +BASE_FEATURE_PARAM(bool, + kHttpCacheNoVarySearchPersistenceEnabled, + &kHttpCacheNoVarySearch, + "persistence_enabled", + true); + +BASE_FEATURE_PARAM(bool, + kHttpCacheNoVarySearchFakePersistence, + &kHttpCacheNoVarySearch, + "fake_persistence", + false); + BASE_FEATURE(kReportingApiCorsOriginHeader, "ReportingApiCorsOriginHeader", base::FEATURE_ENABLED_BY_DEFAULT); @@ -811,4 +865,48 @@ BASE_FEATURE_PARAM(int, "TcpConnectionPoolSizeTrialWebSocket", 256); +BASE_FEATURE(kNetTaskScheduler, + "NetTaskScheduler", + base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE_PARAM(bool, + kNetTaskSchedulerHttpProxyConnectJob, + &kNetTaskScheduler, + "http_proxy_connect_job", + false); +BASE_FEATURE_PARAM(bool, + kNetTaskSchedulerHttpCacheTransaction, + &kNetTaskScheduler, + "http_cache_transaction", + false); +BASE_FEATURE_PARAM(bool, + kNetTaskSchedulerHttpStreamFactoryJob, + &kNetTaskScheduler, + "http_stream_factory_job", + false); +BASE_FEATURE_PARAM(bool, + kNetTaskSchedulerHttpStreamFactoryJobController, + &kNetTaskScheduler, + "http_stream_factory_job_controller", + false); +BASE_FEATURE_PARAM(bool, + kNetTaskSchedulerURLRequestErrorJob, + &kNetTaskScheduler, + "url_request_error_job", + false); +BASE_FEATURE_PARAM(bool, + kNetTaskSchedulerURLRequestHttpJob, + &kNetTaskScheduler, + "url_request_http_job", + false); +BASE_FEATURE_PARAM(bool, + kNetTaskSchedulerURLRequestJob, + &kNetTaskScheduler, + "url_request_job", + false); +BASE_FEATURE_PARAM(bool, + kNetTaskSchedulerURLRequestRedirectJob, + &kNetTaskScheduler, + "url_request_redirect_job", + false); + } // namespace net::features diff --git a/naiveproxy/src/net/base/features.h b/naiveproxy/src/net/base/features.h index 26e2073efa..018f2d9bb1 100644 --- a/naiveproxy/src/net/base/features.h +++ b/naiveproxy/src/net/base/features.h @@ -16,6 +16,7 @@ #include "build/build_config.h" #include "crypto/crypto_buildflags.h" #include "net/base/net_export.h" +#include "net/disk_cache/buildflags.h" #include "net/net_buildflags.h" namespace net::features { @@ -174,6 +175,14 @@ NET_EXPORT BASE_DECLARE_FEATURE(kSplitCodeCacheByNetworkIsolationKey); // See https://github.com/MattMenke2/Explainer---Partition-Network-State. NET_EXPORT BASE_DECLARE_FEATURE(kPartitionConnectionsByNetworkIsolationKey); +// "__Http-" prefix for cookies. +// https://github.com/httpwg/http-extensions/pull/3110 +NET_EXPORT BASE_DECLARE_FEATURE(kPrefixCookieHttp); + +// "__HostHttp-" prefix for cookies. +// https://github.com/httpwg/http-extensions/issues/3111 +NET_EXPORT BASE_DECLARE_FEATURE(kPrefixCookieHostHttp); + // Changes the interval between two search engine preconnect attempts. NET_EXPORT BASE_DECLARE_FEATURE(kSearchEnginePreconnectInterval); @@ -201,6 +210,10 @@ NET_EXPORT BASE_DECLARE_FEATURE_PARAM(int, kPingIntervalInSeconds); // (e.g. "ABCD,EFGH"). NET_EXPORT BASE_DECLARE_FEATURE_PARAM(std::string, kQuicConnectionOptions); +// Whether to fallback to the old preconnect interval when the device is in low +// power mode. +NET_EXPORT BASE_DECLARE_FEATURE_PARAM(bool, kFallbackInLowPowerMode); + // When enabled, the time threshold for Lax-allow-unsafe cookies will be lowered // from 2 minutes to 10 seconds. This time threshold refers to the age cutoff // for which cookies that default into SameSite=Lax, which are newer than the @@ -404,18 +417,24 @@ NET_EXPORT extern const base::FeatureParam NET_EXPORT extern const base::FeatureParam kProbabilisticRevealTokenFetchOnly; -// If true, probabilistic reveal tokens can be attached to non-proxied requests -// as well. PRTs will still only be attached to requests if the -// `ProbabilisticRevealTokensAddHeaderToProxiedRequests` flag is true and the -// request is being sent to a registered domain, but this flag can be used in -// combination with `BypassProbabilisticRevealTokenRegistry` or -// `CustomProbabilisticRevealTokenRegistry`. This is intended to be used for -// developer testing only. +// If true, PRTs are attached to the non-proxied requests satisfying the +// right conditions specified by other PRT flags, in addition to the proxied +// ones. NET_EXPORT extern const base::FeatureParam kEnableProbabilisticRevealTokensForNonProxiedRequests; -// If true, probabilistic reveal tokens header will be added to proxied -// requests. +// TODO(crbug.com/425905281): Rename feature flag +// `kProbabilisticRevealTokensAddHeaderToProxiedRequests` +// +// Despite its name this flag controls whether the PRT header should be added to +// a given request, independent of the request being proxied or not. The +// decision on enabling PRTs for non-proxied requests is controlled with +// `kEnableProbabilisticRevealTokensForNonProxiedRequests`. +// +// If true, PRT header will be added to the not necessarily proxied requests +// satisfying the right conditions specified by other PRT flags, i.e., whether +// PRTs are enabled for the request/session, destination domain is eligible and +// kProbabilisticRevealTokenFetchOnly is false. NET_EXPORT extern const base::FeatureParam kProbabilisticRevealTokensAddHeaderToProxiedRequests; @@ -575,6 +594,16 @@ NET_EXPORT extern const base::FeatureParam // the Network panel. Tracked at https://crbug.com/425645896. NET_EXPORT extern const base::FeatureParam kIpPrivacyEnableIppInDevTools; +// Enables the ability for IP protection features to be gated in the Privacy +// and Security Panel within DevTools. When this flag is disabled, the IP +// Protection section will not be shown in the DevTools panel, allowing testing +// and development of the IP Protection features before public release. +NET_EXPORT extern const base::FeatureParam + kIpPrivacyEnableIppPanelInDevTools; + +// Enables more advanced handling of IP Protection proxy request failures. +NET_EXPORT BASE_DECLARE_FEATURE(kEnableIpPrivacyProxyAdvancedFallbackLogic); + // Maximum report body size (KB) to include in serialized reports. Bodies // exceeding this are omitted when kExcludeLargeBodyReports is enabled. Use // Reporting.ReportBodySize UMA histogram to monitor report body sizes and @@ -667,6 +696,12 @@ NET_EXPORT BASE_DECLARE_FEATURE_PARAM( // This behavior is expected by default; disabling it should only be for // testing purposes. NET_EXPORT BASE_DECLARE_FEATURE(kDeviceBoundSessionsRefreshQuota); +// This feature will enable breaking changes to Device Bound Session +// Credentials from after the Origin Trial started. This is disabled by +// default to facilitate implementation of feedback from the Origin +// Trial while still being able to get consistent metrics across Chrome +// releases. +NET_EXPORT BASE_DECLARE_FEATURE(kDeviceBoundSessionsOriginTrialFeedback); // When enabled, all proxies in a proxy chain are partitioned by the NAK for the // endpoint of the connection. When disabled, proxies carrying tunnels to other @@ -704,17 +739,10 @@ NET_EXPORT BASE_DECLARE_FEATURE(kSimdutfBase64Support); // Further optimize parsing data: URLs. NET_EXPORT BASE_DECLARE_FEATURE(kFurtherOptimizeParsingDataUrls); -// Keep whitespace for non-base64 encoded data: URLs. -NET_EXPORT BASE_DECLARE_FEATURE(kKeepWhitespaceForDataUrls); - // If enabled, unrecognized keys in a No-Vary-Search header will be ignored. // Otherwise, unrecognized keys are treated as if the header was invalid. NET_EXPORT BASE_DECLARE_FEATURE(kNoVarySearchIgnoreUnrecognizedKeys); -// If enabled, then a cookie entry containing both encrypted and plaintext -// values is considered invalid, and the entire eTLD group will be dropped. -NET_EXPORT BASE_DECLARE_FEATURE(kEncryptedAndPlaintextValuesAreInvalid); - // Kill switch for Static CT Log (aka Tiled Log aka Sunlight) // enforcements in Certificate Transparency policy checks. If disabled, SCTs // from Static CT Logs will simply be ignored. @@ -722,8 +750,12 @@ NET_EXPORT BASE_DECLARE_FEATURE(kEnableStaticCTAPIEnforcement); // Finch experiment to select a disk cache backend. enum class DiskCacheBackend { + kDefault, kSimple, kBlockfile, +#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND) + kSql, +#endif // ENABLE_DISK_CACHE_SQL_BACKEND }; NET_EXPORT BASE_DECLARE_FEATURE(kDiskCacheBackendExperiment); NET_EXPORT extern const base::FeatureParam @@ -753,12 +785,35 @@ NET_EXPORT BASE_DECLARE_FEATURE(kNewClientCertPathBuilding); // When enabled HSTS upgrades will only apply to top-level navigations. NET_EXPORT BASE_DECLARE_FEATURE(kHstsTopLevelNavigationsOnly); +#if BUILDFLAG(IS_WIN) +// Whether or not to flush on MappedFile::Flush(). +NET_EXPORT BASE_DECLARE_FEATURE(kHttpCacheMappedFileFlushWin); +#endif + // Whether or not to apply No-Vary-Search processing in the HTTP disk cache. NET_EXPORT BASE_DECLARE_FEATURE(kHttpCacheNoVarySearch); NET_EXPORT BASE_DECLARE_FEATURE_PARAM(size_t, kHttpCacheNoVarySearchCacheMaxEntries); +// Whether the NoVarySearchCache should be consulted in +// HttpCache::OnExternalCacheHit(). +NET_EXPORT BASE_DECLARE_FEATURE_PARAM( + bool, + kHttpCacheNoVarySearchApplyToExternalHits); + +// Whether persistence is enabled in on-the-record profiles. True by default. +NET_EXPORT BASE_DECLARE_FEATURE_PARAM(bool, + kHttpCacheNoVarySearchPersistenceEnabled); + +// If true, the persisted files will be created with valid but empty contents at +// startup and after that closed and never used. Has no effect if +// "persistence_enabled" is false. Causes "HttpCache.NoVarySearch.LoadResult" to +// log "SnapshotLoadFailed" as there is no point in adding a new enum value for +// this temporary feature. +NET_EXPORT BASE_DECLARE_FEATURE_PARAM(bool, + kHttpCacheNoVarySearchFakePersistence); + // Enables sending the CORS Origin header on the POST request for Reporting API // report uploads. NET_EXPORT BASE_DECLARE_FEATURE(kReportingApiCorsOriginHeader); @@ -822,6 +877,25 @@ NET_EXPORT BASE_DECLARE_FEATURE_PARAM(int, kTcpConnectionPoolSizeTrialNormal); NET_EXPORT BASE_DECLARE_FEATURE_PARAM(int, kTcpConnectionPoolSizeTrialWebSocket); +// These parameters control whether the Network Service Task Scheduler is used +// for specific classes. +NET_EXPORT BASE_DECLARE_FEATURE(kNetTaskScheduler); +NET_EXPORT BASE_DECLARE_FEATURE_PARAM(bool, + kNetTaskSchedulerHttpCacheTransaction); +NET_EXPORT BASE_DECLARE_FEATURE_PARAM(bool, + kNetTaskSchedulerHttpProxyConnectJob); +NET_EXPORT BASE_DECLARE_FEATURE_PARAM(bool, + kNetTaskSchedulerHttpStreamFactoryJob); +NET_EXPORT BASE_DECLARE_FEATURE_PARAM( + bool, + kNetTaskSchedulerHttpStreamFactoryJobController); +NET_EXPORT BASE_DECLARE_FEATURE_PARAM(bool, + kNetTaskSchedulerURLRequestErrorJob); +NET_EXPORT BASE_DECLARE_FEATURE_PARAM(bool, kNetTaskSchedulerURLRequestHttpJob); +NET_EXPORT BASE_DECLARE_FEATURE_PARAM(bool, kNetTaskSchedulerURLRequestJob); +NET_EXPORT BASE_DECLARE_FEATURE_PARAM(bool, + kNetTaskSchedulerURLRequestRedirectJob); + } // namespace net::features #endif // NET_BASE_FEATURES_H_ diff --git a/naiveproxy/src/net/base/hash_value.cc b/naiveproxy/src/net/base/hash_value.cc index 84844d16ce..bcc8f91506 100644 --- a/naiveproxy/src/net/base/hash_value.cc +++ b/naiveproxy/src/net/base/hash_value.cc @@ -81,6 +81,11 @@ base::span HashValue::span() const { NOTREACHED(); } +const SHA256HashValue& HashValue::sha256hashvalue() const { + CHECK(tag_ == HASH_VALUE_SHA256); + return fingerprint.sha256; +} + bool operator==(const HashValue& lhs, const HashValue& rhs) { if (lhs.tag_ != rhs.tag_) return false; diff --git a/naiveproxy/src/net/base/hash_value.h b/naiveproxy/src/net/base/hash_value.h index e45c468df4..14aa85bdea 100644 --- a/naiveproxy/src/net/base/hash_value.h +++ b/naiveproxy/src/net/base/hash_value.h @@ -58,6 +58,9 @@ class NET_EXPORT HashValue { base::span span(); base::span span() const; + // Returns the SHA256 byte array. CHECK-fails if tag() != HASH_VALUE_SHA256; + const SHA256HashValue& sha256hashvalue() const; + HashValueTag tag() const { return tag_; } NET_EXPORT friend bool operator==(const HashValue& lhs, const HashValue& rhs); diff --git a/naiveproxy/src/net/base/isolation_info.cc b/naiveproxy/src/net/base/isolation_info.cc index 18e210df71..dbfa295add 100644 --- a/naiveproxy/src/net/base/isolation_info.cc +++ b/naiveproxy/src/net/base/isolation_info.cc @@ -165,10 +165,10 @@ IsolationInfo IsolationInfo::CreateForInternalRequest( } IsolationInfo IsolationInfo::CreateTransient( - const std::optional& nonce) { + std::optional nonce) { url::Origin opaque_origin; return IsolationInfo(RequestType::kOther, opaque_origin, opaque_origin, - SiteForCookies(), /*nonce=*/nonce, + SiteForCookies(), /*nonce=*/std::move(nonce), NetworkIsolationPartition::kGeneral, /*frame_ancestor_relation=*/std::nullopt); } @@ -214,10 +214,10 @@ std::optional IsolationInfo::Deserialize( IsolationInfo IsolationInfo::Create( RequestType request_type, - const url::Origin& top_frame_origin, - const url::Origin& frame_origin, - const SiteForCookies& site_for_cookies, - const std::optional& nonce, + url::Origin top_frame_origin, + url::Origin frame_origin, + SiteForCookies site_for_cookies, + std::optional nonce, NetworkIsolationPartition network_isolation_partition, std::optional frame_ancestor_relation) { // TODO(crbug.com/420876079): Remove this "recovery" and force all callers to @@ -226,8 +226,9 @@ IsolationInfo IsolationInfo::Create( if (request_type == RequestType::kMainFrame && !frame_ancestor_relation) { frame_ancestor_relation = FrameAncestorRelation::kSameOrigin; } - return IsolationInfo(request_type, top_frame_origin, frame_origin, - site_for_cookies, nonce, network_isolation_partition, + return IsolationInfo(request_type, std::move(top_frame_origin), + std::move(frame_origin), std::move(site_for_cookies), + std::move(nonce), network_isolation_partition, frame_ancestor_relation); } @@ -264,10 +265,10 @@ IsolationInfo IsolationInfo::DoNotUseCreatePartialFromNak( std::optional IsolationInfo::CreateIfConsistent( RequestType request_type, - const std::optional& top_frame_origin, - const std::optional& frame_origin, - const SiteForCookies& site_for_cookies, - const std::optional& nonce, + std::optional top_frame_origin, + std::optional frame_origin, + SiteForCookies site_for_cookies, + std::optional nonce, NetworkIsolationPartition network_isolation_partition, std::optional frame_ancestor_relation) { // TODO(crbug.com/420876079): Remove this "recovery" and force all callers to @@ -280,9 +281,10 @@ std::optional IsolationInfo::CreateIfConsistent( site_for_cookies, nonce, frame_ancestor_relation)) { return std::nullopt; } - return IsolationInfo(request_type, top_frame_origin, frame_origin, - site_for_cookies, nonce, network_isolation_partition, - std::move(frame_ancestor_relation)); + return IsolationInfo(request_type, std::move(top_frame_origin), + std::move(frame_origin), std::move(site_for_cookies), + std::move(nonce), network_isolation_partition, + frame_ancestor_relation); } IsolationInfo IsolationInfo::CreateForRedirect( @@ -460,34 +462,34 @@ std::string_view IsolationInfo::FrameAncestorRelationString( IsolationInfo::IsolationInfo( RequestType request_type, - const std::optional& top_frame_origin, - const std::optional& frame_origin, - const SiteForCookies& site_for_cookies, - const std::optional& nonce, + std::optional top_frame_origin, + std::optional frame_origin, + SiteForCookies site_for_cookies, + std::optional nonce, NetworkIsolationPartition network_isolation_partition, std::optional frame_ancestor_relation) : request_type_(request_type), - top_frame_origin_(top_frame_origin), - frame_origin_(frame_origin), + top_frame_origin_(std::move(top_frame_origin)), + frame_origin_(std::move(frame_origin)), frame_ancestor_relation_(frame_ancestor_relation), network_isolation_key_( - !top_frame_origin + !top_frame_origin_ ? NetworkIsolationKey() - : NetworkIsolationKey(SchemefulSite(*top_frame_origin), - SchemefulSite(*frame_origin), + : NetworkIsolationKey(SchemefulSite(*top_frame_origin_), + SchemefulSite(*frame_origin_), nonce, network_isolation_partition)), network_anonymization_key_( - !top_frame_origin ? NetworkAnonymizationKey() - : NetworkAnonymizationKey::CreateFromFrameSite( - SchemefulSite(*top_frame_origin), - SchemefulSite(*frame_origin), - nonce, - network_isolation_partition)), - site_for_cookies_(site_for_cookies), - nonce_(nonce) { + !top_frame_origin_ ? NetworkAnonymizationKey() + : NetworkAnonymizationKey::CreateFromFrameSite( + SchemefulSite(*top_frame_origin_), + SchemefulSite(*frame_origin_), + nonce, + network_isolation_partition)), + site_for_cookies_(std::move(site_for_cookies)), + nonce_(std::move(nonce)) { DCHECK(IsConsistent(request_type_, top_frame_origin_, frame_origin_, - site_for_cookies_, nonce, frame_ancestor_relation_)); + site_for_cookies_, nonce_, frame_ancestor_relation_)); } } // namespace net diff --git a/naiveproxy/src/net/base/isolation_info.h b/naiveproxy/src/net/base/isolation_info.h index ffdb7705b0..32e933bf82 100644 --- a/naiveproxy/src/net/base/isolation_info.h +++ b/naiveproxy/src/net/base/isolation_info.h @@ -173,7 +173,7 @@ class NET_EXPORT IsolationInfo { // Note: error pages resulting from a failed navigation should always use a // transient IsolationInfo with no nonce. static IsolationInfo CreateTransient( - const std::optional& nonce); + std::optional nonce); // Creates an IsolationInfo from the serialized contents. Returns a nullopt // if deserialization fails or if data is inconsistent. @@ -200,10 +200,10 @@ class NET_EXPORT IsolationInfo { // `site_for_cookies` is not HTTP/HTTPS. static IsolationInfo Create( RequestType request_type, - const url::Origin& top_frame_origin, - const url::Origin& frame_origin, - const SiteForCookies& site_for_cookies, - const std::optional& nonce = std::nullopt, + url::Origin top_frame_origin, + url::Origin frame_origin, + SiteForCookies site_for_cookies, + std::optional nonce = std::nullopt, NetworkIsolationPartition network_isolation_partition = NetworkIsolationPartition::kGeneral, std::optional frame_ancestor_relation = @@ -222,10 +222,10 @@ class NET_EXPORT IsolationInfo { // Intended for use by cross-process deserialization. static std::optional CreateIfConsistent( RequestType request_type, - const std::optional& top_frame_origin, - const std::optional& frame_origin, - const SiteForCookies& site_for_cookies, - const std::optional& nonce = std::nullopt, + std::optional top_frame_origin, + std::optional frame_origin, + SiteForCookies site_for_cookies, + std::optional nonce = std::nullopt, NetworkIsolationPartition network_isolation_partition = NetworkIsolationPartition::kGeneral, std::optional frame_ancestor_relation = @@ -296,10 +296,10 @@ class NET_EXPORT IsolationInfo { private: IsolationInfo(RequestType request_type, - const std::optional& top_frame_origin, - const std::optional& frame_origin, - const SiteForCookies& site_for_cookies, - const std::optional& nonce, + std::optional top_frame_origin, + std::optional frame_origin, + SiteForCookies site_for_cookies, + std::optional nonce, NetworkIsolationPartition network_isolation_partition, std::optional frame_ancestor_relation); diff --git a/naiveproxy/src/net/base/mime_util.cc b/naiveproxy/src/net/base/mime_util.cc index 3e198e6865..0347fffd0e 100644 --- a/naiveproxy/src/net/base/mime_util.cc +++ b/naiveproxy/src/net/base/mime_util.cc @@ -10,12 +10,12 @@ #include #include #include +#include #include #include "base/base64.h" #include "base/check_op.h" #include "base/containers/span.h" -#include "base/lazy_instance.h" #include "base/memory/raw_ptr_exclusion.h" #include "base/no_destructor.h" #include "base/rand_util.h" @@ -45,6 +45,14 @@ std::string& GetOverridingMimeType() { // Singleton utility class for mime types. class MimeUtil : public PlatformMimeUtil { public: + static MimeUtil& Get() { + // This variable is leaky because we need to access it from WorkerPool + // threads. Trivially destructible, so no NoDestructor. + static_assert(std::is_trivially_destructible::value); + static MimeUtil mime_util; + return mime_util; + } + bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext, std::string* mime_type) const; @@ -72,8 +80,6 @@ class MimeUtil : public PlatformMimeUtil { bool IsValidTopLevelMimeType(std::string_view type_string) const; private: - friend struct base::LazyInstanceTraitsBase; - MimeUtil(); bool GetMimeTypeFromExtensionHelper(const base::FilePath::StringType& ext, @@ -81,10 +87,6 @@ class MimeUtil : public PlatformMimeUtil { std::string* mime_type) const; }; // class MimeUtil -// This variable is Leaky because we need to access it from WorkerPool threads. -static base::LazyInstance::Leaky g_mime_util = - LAZY_INSTANCE_INITIALIZER; - struct MimeInfo { const std::string_view mime_type; @@ -659,46 +661,45 @@ bool MimeUtil::IsValidTopLevelMimeType(std::string_view type_string) const { bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext, std::string* mime_type) { - return g_mime_util.Get().GetMimeTypeFromExtension(ext, mime_type); + return MimeUtil::Get().GetMimeTypeFromExtension(ext, mime_type); } bool GetMimeTypeFromFile(const base::FilePath& file_path, std::string* mime_type) { - return g_mime_util.Get().GetMimeTypeFromFile(file_path, mime_type); + return MimeUtil::Get().GetMimeTypeFromFile(file_path, mime_type); } bool GetWellKnownMimeTypeFromExtension(const base::FilePath::StringType& ext, std::string* mime_type) { - return g_mime_util.Get().GetWellKnownMimeTypeFromExtension(ext, mime_type); + return MimeUtil::Get().GetWellKnownMimeTypeFromExtension(ext, mime_type); } bool GetWellKnownMimeTypeFromFile(const base::FilePath& file_path, std::string* mime_type) { - return g_mime_util.Get().GetWellKnownMimeTypeFromFile(file_path, mime_type); + return MimeUtil::Get().GetWellKnownMimeTypeFromFile(file_path, mime_type); } bool GetPreferredExtensionForMimeType(std::string_view mime_type, base::FilePath::StringType* extension) { - return g_mime_util.Get().GetPreferredExtensionForMimeType(mime_type, - extension); + return MimeUtil::Get().GetPreferredExtensionForMimeType(mime_type, extension); } bool MatchesMimeType(std::string_view mime_type_pattern, std::string_view mime_type, bool validate_mime_type) { - return g_mime_util.Get().MatchesMimeType(mime_type_pattern, mime_type, - validate_mime_type); + return MimeUtil::Get().MatchesMimeType(mime_type_pattern, mime_type, + validate_mime_type); } bool ParseMimeTypeWithoutParameter(std::string_view type_string, std::string* top_level_type, std::string* subtype) { - return g_mime_util.Get().ParseMimeTypeWithoutParameter( - type_string, top_level_type, subtype); + return MimeUtil::Get().ParseMimeTypeWithoutParameter(type_string, + top_level_type, subtype); } bool IsValidTopLevelMimeType(std::string_view type_string) { - return g_mime_util.Get().IsValidTopLevelMimeType(type_string); + return MimeUtil::Get().IsValidTopLevelMimeType(type_string); } namespace { @@ -819,8 +820,7 @@ void GetExtensionsHelper( const std::string& leading_mime_type, std::unordered_set* extensions) { for (auto* standard_type : standard_types) { - g_mime_util.Get().GetPlatformExtensionsForMimeType(standard_type, - extensions); + MimeUtil::Get().GetPlatformExtensionsForMimeType(standard_type, extensions); } // Also look up the extensions from hard-coded mappings in case that some @@ -886,8 +886,8 @@ void GetExtensionsForMimeType( leading_mime_type, &unique_extensions); } else { - g_mime_util.Get().GetPlatformExtensionsForMimeType(mime_type, - &unique_extensions); + MimeUtil::Get().GetPlatformExtensionsForMimeType(mime_type, + &unique_extensions); // Also look up the extensions from hard-coded mappings in case that some // supported extensions are not registered in the system registry, like ogg. diff --git a/naiveproxy/src/net/base/net_error_list.h b/naiveproxy/src/net/base/net_error_list.h index 8885bd0741..e9840288ec 100644 --- a/naiveproxy/src/net/base/net_error_list.h +++ b/naiveproxy/src/net/base/net_error_list.h @@ -171,7 +171,8 @@ NET_ERROR(ADDRESS_UNREACHABLE, -109) // The server requested a client certificate for SSL client authentication. NET_ERROR(SSL_CLIENT_AUTH_CERT_NEEDED, -110) -// A tunnel connection through the proxy could not be established. +// A tunnel connection through the proxy could not be established. For more info +// see the comment on PROXY_UNABLE_TO_CONNECT_TO_DESTINATION. NET_ERROR(TUNNEL_CONNECTION_FAILED, -111) // No SSL protocol versions are enabled. @@ -444,6 +445,23 @@ NET_ERROR(ECH_NOT_NEGOTIATED, -183) // and additionally did not present a certificate valid for the public name. NET_ERROR(ECH_FALLBACK_CERTIFICATE_INVALID, -184) +// Error -185 was removed (PROXY_TUNNEL_REQUEST_FAILED). + +// An attempt to proxy a request failed because the proxy wasn't able to +// successfully connect to the destination. This likely indicates an issue with +// the request itself (for instance, the hostname failed to resolve to an IP +// address or the destination server refused the connection). This error code +// is used to indicate that the error is outside the control of the proxy server +// and thus the proxy chain should not be marked as bad. This is in contrast to +// ERR_TUNNEL_CONNECTION_FAILED which is used for general purpose errors +// connecting to the proxy and by the proxy request response handling when a +// proxy delegate doesn't indicate via a different error code whether proxy +// fallback should occur. Note that for IP Protection proxies this error code +// causes the proxy to be marked as bad since the preference is to fail open for +// general purpose errors, but for other proxies this error does not cause the +// proxy to be marked as bad. +NET_ERROR(PROXY_UNABLE_TO_CONNECT_TO_DESTINATION, -186) + // Certificate error codes // // The values of certificate error codes must be consecutive. diff --git a/naiveproxy/src/net/base/net_string_util_icu_alternatives_android.cc b/naiveproxy/src/net/base/net_string_util_icu_alternatives_android.cc index cf8c047f95..f7c99d6875 100644 --- a/naiveproxy/src/net/base/net_string_util_icu_alternatives_android.cc +++ b/naiveproxy/src/net/base/net_string_util_icu_alternatives_android.cc @@ -23,7 +23,7 @@ namespace { ScopedJavaLocalRef ConvertToJstring(std::string_view text, const char* charset) { JNIEnv* env = base::android::AttachCurrentThread(); - ScopedJavaLocalRef java_byte_buffer( + auto java_byte_buffer = ScopedJavaLocalRef::Adopt( env, env->NewDirectByteBuffer(const_cast(text.data()), text.length())); base::android::CheckException(env); @@ -41,7 +41,7 @@ ScopedJavaLocalRef ConvertToJstring(std::string_view text, ScopedJavaLocalRef ConvertToNormalizedJstring(std::string_view text, const char* charset) { JNIEnv* env = base::android::AttachCurrentThread(); - ScopedJavaLocalRef java_byte_buffer( + auto java_byte_buffer = ScopedJavaLocalRef::Adopt( env, env->NewDirectByteBuffer(const_cast(text.data()), text.length())); base::android::CheckException(env); @@ -59,7 +59,7 @@ ScopedJavaLocalRef ConvertToJstringWithSubstitutions( std::string_view text, const char* charset) { JNIEnv* env = base::android::AttachCurrentThread(); - ScopedJavaLocalRef java_byte_buffer( + auto java_byte_buffer = ScopedJavaLocalRef::Adopt( env, env->NewDirectByteBuffer(const_cast(text.data()), text.length())); base::android::CheckException(env); @@ -126,7 +126,7 @@ bool ConvertToUTF16WithSubstitutions(std::string_view text, bool ToUpperUsingLocale(std::u16string_view str, std::u16string* output) { output->clear(); JNIEnv* env = base::android::AttachCurrentThread(); - ScopedJavaLocalRef java_new_str( + auto java_new_str = ScopedJavaLocalRef::Adopt( env, env->NewString(reinterpret_cast(str.data()), str.length())); if (java_new_str.is_null()) diff --git a/naiveproxy/src/net/base/network_change_notifier.cc b/naiveproxy/src/net/base/network_change_notifier.cc index 230d559e66..854171a43c 100644 --- a/naiveproxy/src/net/base/network_change_notifier.cc +++ b/naiveproxy/src/net/base/network_change_notifier.cc @@ -21,10 +21,10 @@ #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" #include "base/timer/timer.h" +#include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "net/base/network_change_notifier_factory.h" #include "net/base/network_interfaces.h" -#include "net/base/tracing.h" #include "net/base/url_util.h" #include "net/dns/dns_config.h" #include "net/dns/dns_config_service.h" @@ -847,7 +847,8 @@ NetworkChangeNotifier::NetworkChangeNotifier( /*= NetworkChangeCalculatorParams()*/, SystemDnsConfigChangeNotifier* system_dns_config_notifier /*= nullptr */, bool omit_observers_in_constructor_for_testing /*= false */) - : system_dns_config_notifier_(system_dns_config_notifier), + : track_("NetworkChangeNotifier"), + system_dns_config_notifier_(system_dns_config_notifier), system_dns_config_observer_(std::make_unique()) { { base::AutoLock auto_lock(NetworkChangeNotifierCreationLock()); @@ -1021,7 +1022,7 @@ void NetworkChangeNotifier::StopSystemDnsConfigNotifier() { } void NetworkChangeNotifier::NotifyObserversOfIPAddressChangeImpl() { - TRACE_EVENT_INSTANT("net", "NetworkChangeNotifier::IPAddressChange"); + TRACE_EVENT_INSTANT("net", "NetworkChangeNotifier::IPAddressChange", track_); GetObserverList().ip_address_observer_list_->Notify( FROM_HERE, &IPAddressObserver::OnIPAddressChanged); } @@ -1029,21 +1030,21 @@ void NetworkChangeNotifier::NotifyObserversOfIPAddressChangeImpl() { void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeImpl( ConnectionType type) { TRACE_EVENT_INSTANT("net", "NetworkChangeNotifier::ConnectionTypeChange", - "type", type); + track_, "type", type); GetObserverList().connection_type_observer_list_->Notify( FROM_HERE, &ConnectionTypeObserver::OnConnectionTypeChanged, type); } void NetworkChangeNotifier::NotifyObserversOfNetworkChangeImpl( ConnectionType type) { - TRACE_EVENT_INSTANT("net", "NetworkChangeNotifier::NetworkChange", "type", - type); + TRACE_EVENT_INSTANT("net", "NetworkChangeNotifier::NetworkChange", track_, + "type", type); GetObserverList().network_change_observer_list_->Notify( FROM_HERE, &NetworkChangeObserver::OnNetworkChanged, type); } void NetworkChangeNotifier::NotifyObserversOfDNSChangeImpl() { - TRACE_EVENT_INSTANT("net", "NetworkChangeNotifier::DnsChange"); + TRACE_EVENT_INSTANT("net", "NetworkChangeNotifier::DnsChange", track_); GetObserverList().resolver_state_observer_list_->Notify( FROM_HERE, &DNSObserver::OnDNSChanged); } @@ -1052,7 +1053,7 @@ void NetworkChangeNotifier::NotifyObserversOfMaxBandwidthChangeImpl( double max_bandwidth_mbps, ConnectionType type) { TRACE_EVENT_INSTANT("net", "NetworkChangeNotifier::MaxBandwidthChange", - "bandwidth", max_bandwidth_mbps, "type", type); + track_, "bandwidth", max_bandwidth_mbps, "type", type); GetObserverList().max_bandwidth_observer_list_->Notify( FROM_HERE, &MaxBandwidthObserver::OnMaxBandwidthChanged, max_bandwidth_mbps, type); @@ -1062,7 +1063,7 @@ void NetworkChangeNotifier::NotifyObserversOfSpecificNetworkChangeImpl( NetworkChangeType type, handles::NetworkHandle network) { TRACE_EVENT_INSTANT("net", "NetworkChangeNotifier::SpecificNetworkChange", - "type", type, "network", network); + track_, "type", type, "network", network); switch (type) { case NetworkChangeType::kConnected: GetObserverList().network_observer_list_->Notify( @@ -1086,13 +1087,14 @@ void NetworkChangeNotifier::NotifyObserversOfSpecificNetworkChangeImpl( void NetworkChangeNotifier::NotifyObserversOfConnectionCostChangeImpl( ConnectionCost cost) { TRACE_EVENT_INSTANT("net", "NetworkChangeNotifier::ConnectionCostChange", - "cost", cost); + track_, "cost", cost); GetObserverList().connection_cost_observer_list_->Notify( FROM_HERE, &ConnectionCostObserver::OnConnectionCostChanged, cost); } void NetworkChangeNotifier::NotifyObserversOfDefaultNetworkActiveImpl() { - TRACE_EVENT_INSTANT("net", "NetworkChangeNotifier::DefaultNetworkActive"); + TRACE_EVENT_INSTANT("net", "NetworkChangeNotifier::DefaultNetworkActive", + track_); GetObserverList().default_network_active_observer_list_->Notify( FROM_HERE, &DefaultNetworkActiveObserver::OnDefaultNetworkActive); } diff --git a/naiveproxy/src/net/base/network_change_notifier.h b/naiveproxy/src/net/base/network_change_notifier.h index 322b49b256..8801c263de 100644 --- a/naiveproxy/src/net/base/network_change_notifier.h +++ b/naiveproxy/src/net/base/network_change_notifier.h @@ -18,6 +18,7 @@ #include "build/build_config.h" #include "net/base/net_export.h" #include "net/base/network_handle.h" +#include "third_party/perfetto/include/perfetto/tracing/track.h" #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) #include "net/base/address_map_linux.h" @@ -708,6 +709,8 @@ class NET_EXPORT NetworkChangeNotifier { void NotifyObserversOfConnectionCostChangeImpl(ConnectionCost cost); void NotifyObserversOfDefaultNetworkActiveImpl(); + const perfetto::NamedTrack track_; + raw_ptr system_dns_config_notifier_; std::unique_ptr system_dns_config_observer_; diff --git a/naiveproxy/src/net/base/network_delegate.cc b/naiveproxy/src/net/base/network_delegate.cc index 12127359e0..2aae6f06a2 100644 --- a/naiveproxy/src/net/base/network_delegate.cc +++ b/naiveproxy/src/net/base/network_delegate.cc @@ -9,10 +9,10 @@ #include "base/logging.h" #include "base/threading/thread_checker.h" +#include "base/trace_event/trace_event.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" #include "net/base/trace_constants.h" -#include "net/base/tracing.h" #include "net/cookies/cookie_setting_override.h" #include "net/cookies/cookie_util.h" #include "net/proxy_resolution/proxy_info.h" diff --git a/naiveproxy/src/net/base/network_interfaces_win.cc b/naiveproxy/src/net/base/network_interfaces_win.cc index 8a571e165b..d273eaaf76 100644 --- a/naiveproxy/src/net/base/network_interfaces_win.cc +++ b/naiveproxy/src/net/base/network_interfaces_win.cc @@ -7,12 +7,13 @@ #include #include #include +#include #include "base/compiler_specific.h" #include "base/containers/heap_array.h" #include "base/containers/span.h" #include "base/files/file_path.h" -#include "base/lazy_instance.h" +#include "base/no_destructor.h" #include "base/strings/escape.h" #include "base/strings/string_util.h" #include "base/strings/sys_string_conversions.h" @@ -101,11 +102,10 @@ GetConnectionAttributes() { namespace internal { -base::LazyInstance::Leaky lazy_wlanapi = - LAZY_INSTANCE_INITIALIZER; - WlanApi& WlanApi::GetInstance() { - return lazy_wlanapi.Get(); + static_assert(std::is_trivially_destructible::value); + static WlanApi wlan_api; + return wlan_api; } WlanApi::WlanApi() : initialized(false) { diff --git a/naiveproxy/src/net/base/pickle_base_types.h b/naiveproxy/src/net/base/pickle_base_types.h index 713458e247..0911a98e91 100644 --- a/naiveproxy/src/net/base/pickle_base_types.h +++ b/naiveproxy/src/net/base/pickle_base_types.h @@ -19,7 +19,7 @@ namespace net { template <> struct PickleTraits { - static void Serialize(base::Pickle& pickle, const base::Time& time) { + static void Serialize(base::Pickle& pickle, base::Time time) { // For compatibility with existing serialization code in //net, use the // deprecated `ToInternalValue()` method. pickle.WriteInt64(time.ToInternalValue()); @@ -33,7 +33,7 @@ struct PickleTraits { return base::Time::FromInternalValue(time_as_int64); } - static size_t PickleSize(const base::Time& time) { + static size_t PickleSize(base::Time time) { return EstimatePickleSize(int64_t{0}); } }; diff --git a/naiveproxy/src/net/base/port_util.cc b/naiveproxy/src/net/base/port_util.cc index 02197cea24..49d0f744cc 100644 --- a/naiveproxy/src/net/base/port_util.cc +++ b/naiveproxy/src/net/base/port_util.cc @@ -10,7 +10,6 @@ #include "base/containers/fixed_flat_map.h" #include "base/containers/flat_set.h" #include "base/feature_list.h" -#include "base/lazy_instance.h" #include "base/logging.h" #include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_functions.h" @@ -116,8 +115,10 @@ const int kRestrictedPorts[] = { 10080, // Amanda }; -base::LazyInstance>::Leaky g_explicitly_allowed_ports = - LAZY_INSTANCE_INITIALIZER; +std::multiset& GetExplicitlyAllowedPorts() { + static base::NoDestructor> explicitly_allowed_ports; + return *explicitly_allowed_ports; +} // List of ports which are permitted to be reenabled despite being in // kRestrictedList. When adding an port to this list you should also update the @@ -169,8 +170,9 @@ bool IsPortAllowedForScheme(int port, std::string_view url_scheme) { return false; // Allow explicitly allowed ports for any scheme. - if (g_explicitly_allowed_ports.Get().count(port) > 0) + if (GetExplicitlyAllowedPorts().count(port) > 0) { return true; + } // Finally check against the generic list of restricted ports for all // schemes. @@ -211,7 +213,7 @@ bool IsPortAllowedForIpEndpoint(const IPEndPoint& endpoint) { int port = endpoint.port(); // Allow explicitly allowed ports. - if (g_explicitly_allowed_ports.Get().count(port) > 0) { + if (GetExplicitlyAllowedPorts().count(port) > 0) { return true; } @@ -234,24 +236,24 @@ bool IsPortAllowedForIpEndpoint(const IPEndPoint& endpoint) { } size_t GetCountOfExplicitlyAllowedPorts() { - return g_explicitly_allowed_ports.Get().size(); + return GetExplicitlyAllowedPorts().size(); } // Specifies a comma separated list of port numbers that should be accepted // despite bans. If the string is invalid no allowed ports are stored. void SetExplicitlyAllowedPorts(base::span allowed_ports) { std::multiset ports(allowed_ports.begin(), allowed_ports.end()); - g_explicitly_allowed_ports.Get() = std::move(ports); + GetExplicitlyAllowedPorts() = std::move(ports); } ScopedPortException::ScopedPortException(int port) : port_(port) { - g_explicitly_allowed_ports.Get().insert(port); + GetExplicitlyAllowedPorts().insert(port); } ScopedPortException::~ScopedPortException() { - auto it = g_explicitly_allowed_ports.Get().find(port_); - if (it != g_explicitly_allowed_ports.Get().end()) { - g_explicitly_allowed_ports.Get().erase(it); + auto it = GetExplicitlyAllowedPorts().find(port_); + if (it != GetExplicitlyAllowedPorts().end()) { + GetExplicitlyAllowedPorts().erase(it); } else { NOTREACHED(); } diff --git a/naiveproxy/src/net/base/proxy_chain.cc b/naiveproxy/src/net/base/proxy_chain.cc index 37c8e76caa..ede3c9bd9b 100644 --- a/naiveproxy/src/net/base/proxy_chain.cc +++ b/naiveproxy/src/net/base/proxy_chain.cc @@ -31,9 +31,7 @@ bool ShouldAllowQuicForAllChains() { } } // namespace -ProxyChain::ProxyChain() { - proxy_server_list_ = std::nullopt; -} +ProxyChain::ProxyChain() = default; ProxyChain::ProxyChain(const ProxyChain& other) = default; ProxyChain::ProxyChain(ProxyChain&& other) noexcept = default; @@ -56,25 +54,30 @@ ProxyChain::ProxyChain(std::vector proxy_server_list) } } -bool ProxyChain::InitFromPickle(base::PickleIterator* pickle_iter) { - if (!pickle_iter->ReadInt(&ip_protection_chain_id_)) { - return false; +// static +std::optional ProxyChain::InitFromPickle( + base::PickleIterator& pickle_iter) { + int ip_protection_chain_id; + if (!pickle_iter.ReadInt(&ip_protection_chain_id)) { + return std::nullopt; } size_t chain_length = 0; - if (!pickle_iter->ReadLength(&chain_length)) { - return false; + if (!pickle_iter.ReadLength(&chain_length)) { + return std::nullopt; } 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.push_back(ProxyServer::CreateFromPickle(&pickle_iter)); } - proxy_server_list_ = std::move(proxy_server_list); - if (!IsValidInternal()) { - proxy_server_list_ = std::nullopt; - return false; + + ProxyChain chain = + ProxyChain(std::move(proxy_server_list), ip_protection_chain_id, + /*opaque_data=*/std::nullopt); + if (!chain.IsValid()) { + return std::nullopt; } - return true; + return chain; } void ProxyChain::Persist(base::Pickle* pickle) const { @@ -107,15 +110,19 @@ std::pair ProxyChain::SplitLast() const { ProxyChain new_chain = ProxyChain({proxy_server_list_->begin(), proxy_server_list_->end() - 1}, ip_protection_chain_id_, opaque_data_); - return std::make_pair(new_chain, std::ref(proxy_server_list_->back())); + CHECK(new_chain.IsValid()); + return std::make_pair(std::move(new_chain), + std::ref(proxy_server_list_->back())); } ProxyChain ProxyChain::Prefix(size_t len) const { DCHECK(IsValid()); DCHECK_LE(len, length()); - return ProxyChain( + auto new_chain = ProxyChain( {proxy_server_list_->begin(), proxy_server_list_->begin() + len}, ip_protection_chain_id_, opaque_data_); + CHECK(new_chain.IsValid()); + return new_chain; } const ProxyServer& ProxyChain::First() const { @@ -162,7 +169,9 @@ ProxyChain::ProxyChain(std::vector proxy_server_list, : proxy_server_list_(std::move(proxy_server_list)), ip_protection_chain_id_(ip_protection_chain_id), opaque_data_(opaque_data) { - CHECK(IsValidInternal()); + if (!IsValidInternal()) { + *this = ProxyChain(); + } } bool ProxyChain::IsValidInternal() const { diff --git a/naiveproxy/src/net/base/proxy_chain.h b/naiveproxy/src/net/base/proxy_chain.h index dd1c2199ad..8b8d3eefc4 100644 --- a/naiveproxy/src/net/base/proxy_chain.h +++ b/naiveproxy/src/net/base/proxy_chain.h @@ -74,6 +74,8 @@ class NET_EXPORT ProxyChain { // Creates a `ProxyChain` for use by the IP Protection feature. This is used // for metrics collection and for special handling. If not given, the // chain_id defaults to 0 which corresponds to an un-identified chain. + // If the resulting `ProxyChain` is deemed to be invalid, an invalid + // `ProxyChain` is returned and `chain_id` is not used. static ProxyChain ForIpProtection(std::vector proxy_server_list, int chain_id = 0) { return ProxyChain(std::move(proxy_server_list), chain_id, @@ -81,7 +83,9 @@ class NET_EXPORT ProxyChain { } // Creates a `ProxyChain` with `opaque_data` attached to it. This can be later - // on retrieved via `opaque_data()`. + // on retrieved via `opaque_data()`. If the resulting `ProxyChain` is deemed + // to be invalid, an invalid `ProxyChain` is returned and `opaque_data` is not + // used. static ProxyChain WithOpaqueData(std::vector proxy_server_list, int opaque_data) { return ProxyChain(std::move(proxy_server_list), @@ -89,11 +93,12 @@ class NET_EXPORT ProxyChain { opaque_data); } - // Initialize from a pickle that contains data generated by a call to the - // `Persist` method. + // Attempt to create a new `ProxyChain` 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); + // Returns a `ProxyChain` upon success, otherwise returns `std::nullopt`. + static std::optional InitFromPickle( + base::PickleIterator& pickle_iter); // Call this method to persist `ProxyChain`. Illegal to call this on an // invalid object. diff --git a/naiveproxy/src/net/base/request_priority.h b/naiveproxy/src/net/base/request_priority.h index 66c2d1a92f..f0ba5e6f00 100644 --- a/naiveproxy/src/net/base/request_priority.h +++ b/naiveproxy/src/net/base/request_priority.h @@ -17,6 +17,14 @@ namespace net { // // This enum should be synchronized with the enum NetRequestPriority in // tools/metrics/histograms/enums.xml. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +// +// TODO(crbug.com/421051258): Convert this to an enum class, and use the kXXX +// naming convention. +// +// LINT.IfChange(RequestPriority) enum RequestPriority { THROTTLED = 0, // Used to signal that resources // should be reserved for following @@ -30,7 +38,11 @@ enum RequestPriority { MEDIUM = 4, HIGHEST = 5, MAXIMUM_PRIORITY = HIGHEST, + // Define `kMaxValue` for histograms. Clang automatically checks that + // kMaxValue is correctly set for the enum. + kMaxValue = HIGHEST, }; +// LINT.ThenChange(//tools/metrics/histograms/metadata/net/enums.xml:RequestPriority) // For simplicity, one can assume that one can index into array of // NUM_PRIORITIES elements with a RequestPriority (i.e., diff --git a/naiveproxy/src/net/base/task/README.md b/naiveproxy/src/net/base/task/README.md index 1eb0c1ac33..504586edbb 100644 --- a/naiveproxy/src/net/base/task/README.md +++ b/naiveproxy/src/net/base/task/README.md @@ -23,12 +23,12 @@ interacting closely with network operations) to post tasks with a specific ## Integration with Network Service Scheduler -The `NetworkServiceScheduler` (located in `//services/network/scheduler/`) is +The `NetworkServiceTaskScheduler` (located in `//services/network/scheduler/`) is responsible for setting up and managing the actual task queues on the network service thread, including a high-priority queue. During its initialization (specifically in `SetupNetTaskRunners()`), the -`NetworkServiceScheduler` populates +`NetworkServiceTaskScheduler` populates `net::internal::GetTaskRunnerGlobals().high_priority_task_runner` with the task runner associated with its own high-priority queue. diff --git a/naiveproxy/src/net/base/task/task_runner.cc b/naiveproxy/src/net/base/task/task_runner.cc index 692bdf572f..d230080ed0 100644 --- a/naiveproxy/src/net/base/task/task_runner.cc +++ b/naiveproxy/src/net/base/task/task_runner.cc @@ -4,12 +4,26 @@ #include "net/base/task/task_runner.h" +#include "base/metrics/histogram_functions.h" #include "base/no_destructor.h" +#include "base/rand_util.h" namespace net { +namespace { +base::MetricsSubSampler& GetMetricsSubSampler() { + static base::MetricsSubSampler sampler; + return sampler; +} + +} // namespace + const scoped_refptr& GetTaskRunner( RequestPriority priority) { + // Sample with a 0.001 probability to reduce metrics overhead. + if (GetMetricsSubSampler().ShouldSample(0.001)) { + base::UmaHistogramEnumeration("Net.TaskRunner.RequestPriority", priority); + } if (priority == RequestPriority::HIGHEST && internal::GetTaskRunnerGlobals().high_priority_task_runner) { return internal::GetTaskRunnerGlobals().high_priority_task_runner; diff --git a/naiveproxy/src/net/base/task/task_runner.h b/naiveproxy/src/net/base/task/task_runner.h index 849efea271..434ad1217a 100644 --- a/naiveproxy/src/net/base/task/task_runner.h +++ b/naiveproxy/src/net/base/task/task_runner.h @@ -18,7 +18,7 @@ namespace net { // runners that are integrated with the network service's scheduling mechanism // (or other embedder's scheduling). For `RequestPriority::HIGHEST`, this may // return a special high-priority task runner if one has been configured (e.g., -// by the NetworkServiceScheduler). For other priorities, or if no special +// by the NetworkServiceTaskScheduler). For other priorities, or if no special // runner is configured, it typically returns the current thread's default task // runner. NET_EXPORT const scoped_refptr& GetTaskRunner( @@ -34,7 +34,7 @@ struct NET_EXPORT TaskRunnerGlobals { ~TaskRunnerGlobals(); // Task runner specifically for `net::RequestPriority::HIGHEST` tasks. - // This is set by the embedder (e.g., NetworkServiceScheduler). + // This is set by the embedder (e.g., NetworkServiceTaskScheduler). scoped_refptr high_priority_task_runner; }; diff --git a/naiveproxy/src/net/base/tracing.h b/naiveproxy/src/net/base/tracing.h deleted file mode 100644 index 4b9f7a9c04..0000000000 --- a/naiveproxy/src/net/base/tracing.h +++ /dev/null @@ -1,12 +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_BASE_TRACING_H_ -#define NET_BASE_TRACING_H_ - -#include "base/trace_event/trace_event.h" // IWYU pragma: export -#include "build/build_config.h" -#include "net/base/cronet_buildflags.h" - -#endif // NET_BASE_TRACING_H_ diff --git a/naiveproxy/src/net/base/upload_file_element_reader.cc b/naiveproxy/src/net/base/upload_file_element_reader.cc index d49a770504..190975446c 100644 --- a/naiveproxy/src/net/base/upload_file_element_reader.cc +++ b/naiveproxy/src/net/base/upload_file_element_reader.cc @@ -30,7 +30,7 @@ UploadFileElementReader::UploadFileElementReader( const base::FilePath& path, uint64_t range_offset, uint64_t range_length, - const base::Time& expected_modification_time) + base::Time expected_modification_time) : task_runner_(task_runner), path_(path), range_offset_(range_offset), @@ -46,7 +46,7 @@ UploadFileElementReader::UploadFileElementReader( const base::FilePath& path, uint64_t range_offset, uint64_t range_length, - const base::Time& expected_modification_time) + base::Time expected_modification_time) : task_runner_(task_runner), path_(path), range_offset_(range_offset), diff --git a/naiveproxy/src/net/base/upload_file_element_reader.h b/naiveproxy/src/net/base/upload_file_element_reader.h index 3beaacc57b..a7784f2412 100644 --- a/naiveproxy/src/net/base/upload_file_element_reader.h +++ b/naiveproxy/src/net/base/upload_file_element_reader.h @@ -43,7 +43,7 @@ class NET_EXPORT UploadFileElementReader : public UploadElementReader { const base::FilePath& path, uint64_t range_offset, uint64_t range_length, - const base::Time& expected_modification_time); + base::Time expected_modification_time); // Same a above, but takes a FilePath instead. // TODO(mmenke): Remove if all consumers can be switched to the first @@ -52,7 +52,7 @@ class NET_EXPORT UploadFileElementReader : public UploadElementReader { const base::FilePath& path, uint64_t range_offset, uint64_t range_length, - const base::Time& expected_modification_time); + base::Time expected_modification_time); UploadFileElementReader(const UploadFileElementReader&) = delete; UploadFileElementReader& operator=(const UploadFileElementReader&) = delete; @@ -61,7 +61,7 @@ class NET_EXPORT UploadFileElementReader : public UploadElementReader { const base::FilePath& path() const { return path_; } uint64_t range_offset() const { return range_offset_; } uint64_t range_length() const { return range_length_; } - const base::Time& expected_modification_time() const { + base::Time expected_modification_time() const { return expected_modification_time_; } diff --git a/naiveproxy/src/net/base/url_util.cc b/naiveproxy/src/net/base/url_util.cc index 8ca6cffff2..493ae4ca73 100644 --- a/naiveproxy/src/net/base/url_util.cc +++ b/naiveproxy/src/net/base/url_util.cc @@ -187,7 +187,9 @@ bool GetValueForKeyInQuery(const GURL& url, std::string* out_value) { for (QueryIterator it(url); !it.IsAtEnd(); it.Advance()) { if (it.GetKey() == search_key) { - *out_value = it.GetUnescapedValue(); + if (out_value) { + *out_value = it.GetUnescapedValue(); + } return true; } } diff --git a/naiveproxy/src/net/base/url_util.h b/naiveproxy/src/net/base/url_util.h index a2f0a20b28..f88e5b417a 100644 --- a/naiveproxy/src/net/base/url_util.h +++ b/naiveproxy/src/net/base/url_util.h @@ -107,9 +107,9 @@ class NET_EXPORT QueryIterator { std::string unescaped_value_; }; -// Looks for |search_key| in the query portion of |url|. Returns true if the -// key is found and sets |out_value| to the unescaped value for the key. -// Returns false if the key is not found. +// Looks for |search_key| in the query portion of |url|. Returns true if the key +// is found, false otherwise. If the key is found and |out_value| is not null, +// sets its contents to the unescaped value for the key. NET_EXPORT bool GetValueForKeyInQuery(const GURL& url, std::string_view search_key, std::string* out_value); diff --git a/naiveproxy/src/net/base/winsock_init.cc b/naiveproxy/src/net/base/winsock_init.cc index 0d26d6ae4c..bb4e34fd89 100644 --- a/naiveproxy/src/net/base/winsock_init.cc +++ b/naiveproxy/src/net/base/winsock_init.cc @@ -6,8 +6,10 @@ #include +#include + #include "base/check.h" -#include "base/lazy_instance.h" +#include "base/no_destructor.h" namespace { @@ -32,17 +34,15 @@ class WinsockInitSingleton { } }; -// Worker pool threads that use the Windows Sockets API may still be running at -// shutdown. Leak instance and skip cleanup. -static base::LazyInstance::Leaky - g_winsock_init_singleton = LAZY_INSTANCE_INITIALIZER; - } // namespace namespace net { void EnsureWinsockInit() { - g_winsock_init_singleton.Get(); + // Worker pool threads that use the Windows Sockets API may still be running + // at shutdown. Leak instance and skip cleanup. + static_assert(std::is_trivially_destructible::value); + static WinsockInitSingleton singleton; } } // namespace net diff --git a/naiveproxy/src/net/cert/BUILD.gn b/naiveproxy/src/net/cert/BUILD.gn index 2f92a78693..fa587f6293 100644 --- a/naiveproxy/src/net/cert/BUILD.gn +++ b/naiveproxy/src/net/cert/BUILD.gn @@ -12,7 +12,7 @@ proto_library("root_store_proto_full") { # should not be linked into the browser. If a browser target needs this # protobuf, use the _lite target below. use_protobuf_full = true - visibility = [ "//net/tools/root_store_tool:root_store_tool" ] + visibility = [ "//net/tools/root_store_tool" ] } proto_library("root_store_proto_lite") { diff --git a/naiveproxy/src/net/cert/cert_verify_proc.cc b/naiveproxy/src/net/cert/cert_verify_proc.cc index ea3ededed3..b9cc2e026b 100644 --- a/naiveproxy/src/net/cert/cert_verify_proc.cc +++ b/naiveproxy/src/net/cert/cert_verify_proc.cc @@ -244,7 +244,7 @@ void BestEffortCheckOCSP(const std::string& raw_response, // |spki_hashes| - that is, situations in which the OS methods of detecting // a known root flag a certificate as known, but its hash is not known as part // of the built-in list. -void RecordTrustAnchorHistogram(const HashValueVector& spki_hashes, +void RecordTrustAnchorHistogram(const std::vector& spki_hashes, bool is_issued_by_known_root) { int32_t id = 0; for (const auto& hash : spki_hashes) { @@ -480,6 +480,10 @@ int CertVerifyProc::Verify(X509Certificate* cert, verify_result, net_log); CHECK(verify_result->verified_cert); + if (rv == OK) { + CHECK_EQ(verify_result->verified_cert->intermediate_buffers().size() + 1, + verify_result->public_key_hashes.size()); + } // Check for mismatched signature algorithms and unknown signature algorithms // in the chain. Also fills in the has_* booleans for the digest algorithms @@ -504,10 +508,7 @@ int CertVerifyProc::Verify(X509Certificate* cert, // Check to see if the connection is being intercepted. for (const auto& hash : verify_result->public_key_hashes) { - if (hash.tag() != HASH_VALUE_SHA256) { - continue; - } - if (!crl_set()->IsKnownInterceptionKey(hash.span())) { + if (!crl_set()->IsKnownInterceptionKey(hash)) { continue; } @@ -725,7 +726,7 @@ static bool CheckNameConstraints(const std::vector& dns_names, // static bool CertVerifyProc::HasNameConstraintsViolation( - const HashValueVector& public_key_hashes, + const std::vector& public_key_hashes, const std::string& common_name, const std::vector& dns_names, const std::vector& ip_addrs) { @@ -783,9 +784,7 @@ bool CertVerifyProc::HasNameConstraintsViolation( for (const auto& limit : kLimits) { for (const auto& hash : public_key_hashes) { - if (hash.tag() != HASH_VALUE_SHA256) - continue; - if (hash.span() != limit.public_key_hash) { + if (hash != limit.public_key_hash) { continue; } if (dns_names.empty() && ip_addrs.empty()) { @@ -805,8 +804,8 @@ bool CertVerifyProc::HasNameConstraintsViolation( // static bool CertVerifyProc::HasTooLongValidity(const X509Certificate& cert) { - const base::Time& start = cert.valid_start(); - const base::Time& expiry = cert.valid_expiry(); + base::Time start = cert.valid_start(); + base::Time expiry = cert.valid_expiry(); if (start.is_max() || start.is_null() || expiry.is_max() || expiry.is_null() || start > expiry) { return true; diff --git a/naiveproxy/src/net/cert/cert_verify_proc.h b/naiveproxy/src/net/cert/cert_verify_proc.h index 2eaa4a1349..e98d860239 100644 --- a/naiveproxy/src/net/cert/cert_verify_proc.h +++ b/naiveproxy/src/net/cert/cert_verify_proc.h @@ -332,7 +332,7 @@ class NET_EXPORT CertVerifyProc // (which are hashes of SubjectPublicKeyInfo structures) has name constraints // imposed on it and the names in |dns_names| are not permitted. static bool HasNameConstraintsViolation( - const HashValueVector& public_key_hashes, + const std::vector& public_key_hashes, const std::string& common_name, const std::vector& dns_names, const std::vector& ip_addrs); diff --git a/naiveproxy/src/net/cert/cert_verify_proc_android.cc b/naiveproxy/src/net/cert/cert_verify_proc_android.cc index 261af23998..3c223d6aa9 100644 --- a/naiveproxy/src/net/cert/cert_verify_proc_android.cc +++ b/naiveproxy/src/net/cert/cert_verify_proc_android.cc @@ -16,9 +16,9 @@ #include "base/metrics/histogram_macros.h" #include "base/notreached.h" #include "crypto/hash.h" -#include "crypto/sha2.h" #include "net/android/cert_verify_result_android.h" #include "net/android/network_library.h" +#include "net/base/hash_value.h" #include "net/base/net_errors.h" #include "net/cert/asn1_util.h" #include "net/cert/cert_net_fetcher.h" @@ -257,7 +257,8 @@ bool VerifyFromAndroidTrustManager( int flags, scoped_refptr cert_net_fetcher, CertVerifyResult* verify_result) { - android::CertVerifyStatusAndroid status; + android::CertVerifyStatusAndroid status = + android::CERT_VERIFY_STATUS_ANDROID_FAILED; std::vector verified_chain; android::VerifyX509CertChain( @@ -307,6 +308,12 @@ bool VerifyFromAndroidTrustManager( verify_result->verified_cert = std::move(verified_cert); else verify_result->cert_status |= CERT_STATUS_INVALID; + } else if (!IsCertStatusError(verify_result->cert_status)) { + // If the verified chain is empty and the return status was OK, that's + // actually an error. But don't add the cert_status flag if the chain is + // empty and it already was marked as an error, since that would hide the + // actual error reason. + verify_result->cert_status |= CERT_STATUS_INVALID; } // Extract the public key hashes and check whether or not any are known @@ -319,7 +326,8 @@ bool VerifyFromAndroidTrustManager( continue; } - HashValue sha256(crypto::hash::Sha256(base::as_byte_span(spki_bytes))); + SHA256HashValue sha256( + crypto::hash::Sha256(base::as_byte_span(spki_bytes))); verify_result->public_key_hashes.push_back(sha256); if (!verify_result->is_issued_by_known_root) { diff --git a/naiveproxy/src/net/cert/cert_verify_proc_builtin.cc b/naiveproxy/src/net/cert/cert_verify_proc_builtin.cc index d446221983..6ff42c3492 100644 --- a/naiveproxy/src/net/cert/cert_verify_proc_builtin.cc +++ b/naiveproxy/src/net/cert/cert_verify_proc_builtin.cc @@ -303,19 +303,13 @@ bool IsSelfSignedCertOnLocalNetwork(const X509Certificate* cert, return X509Certificate::IsSelfSigned(cert->cert_buffer()); } -// Appends the SHA256 hashes of |spki_bytes| to |*hashes|. -void AppendPublicKeyHashes(const bssl::der::Input& spki_bytes, - HashValueVector* hashes) { - hashes->emplace_back(crypto::hash::Sha256(spki_bytes)); -} - // Appends the SubjectPublicKeyInfo hashes for all certificates in // |path| to |*hashes|. void AppendPublicKeyHashes(const bssl::CertPathBuilderResultPath& path, - HashValueVector* hashes) { + std::vector* hashes) { for (const std::shared_ptr& cert : path.certs) { - AppendPublicKeyHashes(cert->tbs().spki_tlv, hashes); + hashes->emplace_back(crypto::hash::Sha256(cert->tbs().spki_tlv)); } } @@ -568,7 +562,7 @@ class PathBuilderDelegateImpl : public bssl::SimplePathBuilderDelegate { // TODO(crbug.com/41392053): The SPKI hashes are calculated here, during // CRLSet checks, and in AssignVerifyResult. Calculate once and cache in // delegate_data so that it can be reused. - HashValueVector public_key_hashes; + std::vector public_key_hashes; AppendPublicKeyHashes(*path, &public_key_hashes); bool is_issued_by_known_root = false; diff --git a/naiveproxy/src/net/cert/cert_verify_proc_ios.cc b/naiveproxy/src/net/cert/cert_verify_proc_ios.cc index b6d135c980..0ff2584b5d 100644 --- a/naiveproxy/src/net/cert/cert_verify_proc_ios.cc +++ b/naiveproxy/src/net/cert/cert_verify_proc_ios.cc @@ -15,7 +15,7 @@ #include "base/logging.h" #include "base/notreached.h" #include "base/strings/string_view_util.h" -#include "crypto/sha2.h" +#include "crypto/hash.h" #include "net/base/net_errors.h" #include "net/cert/asn1_util.h" #include "net/cert/cert_verify_result.h" @@ -261,9 +261,8 @@ void GetCertChainInfo(CFArrayRef cert_chain, CertVerifyResult* verify_result) { return; } - HashValue sha256(HASH_VALUE_SHA256); - CC_SHA256(spki_bytes.data(), spki_bytes.size(), sha256.span().data()); - verify_result->public_key_hashes.push_back(sha256); + verify_result->public_key_hashes.push_back( + crypto::hash::Sha256(base::as_byte_span(spki_bytes))); } if (!verified_cert.get()) { NOTREACHED(); diff --git a/naiveproxy/src/net/cert/cert_verify_result.cc b/naiveproxy/src/net/cert/cert_verify_result.cc index 465f2e2422..18d249c0b6 100644 --- a/naiveproxy/src/net/cert/cert_verify_result.cc +++ b/naiveproxy/src/net/cert/cert_verify_result.cc @@ -56,7 +56,7 @@ base::Value::Dict CertVerifyResult::NetLogParams(int net_error) const { base::Value::List hashes; for (const auto& public_key_hash : public_key_hashes) - hashes.Append(public_key_hash.ToString()); + hashes.Append(HashValue(public_key_hash).ToString()); dict.Set("public_key_hashes", std::move(hashes)); dict.Set("scts", net::NetLogSignedCertificateTimestampParams(&scts)); diff --git a/naiveproxy/src/net/cert/cert_verify_result.h b/naiveproxy/src/net/cert/cert_verify_result.h index 2e91bc1765..183d3551c2 100644 --- a/naiveproxy/src/net/cert/cert_verify_result.h +++ b/naiveproxy/src/net/cert/cert_verify_result.h @@ -69,9 +69,9 @@ class NET_EXPORT CertVerifyResult { // hashes for all of the SubjectPublicKeyInfos of the chain (target, // intermediates, and trust anchor) // - // The ordering of the hashes in this vector is unspecified. Both the SHA1 - // and SHA256 hash will be present for each certificate. - HashValueVector public_key_hashes; + // The ordering of the hashes matches the order of the |verified_cert| chain + // (leaf to root). + std::vector public_key_hashes; // is_issued_by_known_root is true if we recognise the root CA as a standard // root. If it isn't then it's probably the case that this certificate was diff --git a/naiveproxy/src/net/cert/crl_set.cc b/naiveproxy/src/net/cert/crl_set.cc index 580f13604d..673c67e9a2 100644 --- a/naiveproxy/src/net/cert/crl_set.cc +++ b/naiveproxy/src/net/cert/crl_set.cc @@ -12,10 +12,10 @@ #include "base/json/json_reader.h" #include "base/strings/string_view_util.h" #include "base/time/time.h" +#include "base/trace_event/trace_event.h" #include "base/values.h" #include "crypto/sha2.h" #include "net/base/trace_constants.h" -#include "net/base/tracing.h" #include "third_party/boringssl/src/include/openssl/bytestring.h" #include "third_party/boringssl/src/include/openssl/mem.h" diff --git a/naiveproxy/src/net/cert/ct_log_verifier.cc b/naiveproxy/src/net/cert/ct_log_verifier.cc index 9d8373c3ab..32e2f98c11 100644 --- a/naiveproxy/src/net/cert/ct_log_verifier.cc +++ b/naiveproxy/src/net/cert/ct_log_verifier.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/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "net/cert/ct_log_verifier.h" #include @@ -15,8 +10,10 @@ #include #include +#include "base/compiler_specific.h" #include "base/logging.h" #include "base/notreached.h" +#include "crypto/evp.h" #include "crypto/openssl_util.h" #include "crypto/sha2.h" #include "net/cert/ct_log_verifier_util.h" @@ -24,7 +21,6 @@ #include "net/cert/merkle_audit_proof.h" #include "net/cert/merkle_consistency_proof.h" #include "net/cert/signed_tree_head.h" -#include "third_party/boringssl/src/include/openssl/bytestring.h" #include "third_party/boringssl/src/include/openssl/evp.h" namespace net { @@ -96,8 +92,9 @@ bool CTLogVerifier::VerifySignedTreeHead( if (signed_tree_head.tree_size == 0) { // Root hash must equate SHA256 hash of the empty string. - return memcmp(signed_tree_head.sha256_root_hash, kSHA256EmptyStringHash, - ct::kSthRootHashLength) == 0; + return UNSAFE_TODO(memcmp(signed_tree_head.sha256_root_hash, + kSHA256EmptyStringHash, + ct::kSthRootHashLength)) == 0; } return true; @@ -271,12 +268,10 @@ CTLogVerifier::~CTLogVerifier() = default; bool CTLogVerifier::Init(std::string_view public_key) { crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); - CBS cbs; - CBS_init(&cbs, reinterpret_cast(public_key.data()), - public_key.size()); - public_key_.reset(EVP_parse_public_key(&cbs)); - if (!public_key_ || CBS_len(&cbs) != 0) + public_key_ = crypto::evp::PublicKeyFromBytes(base::as_byte_span(public_key)); + if (!public_key_) { return false; + } key_id_ = crypto::SHA256HashString(public_key); diff --git a/naiveproxy/src/net/cert/ct_log_verifier_util.cc b/naiveproxy/src/net/cert/ct_log_verifier_util.cc index d7230ef9ee..3230372a30 100644 --- a/naiveproxy/src/net/cert/ct_log_verifier_util.cc +++ b/naiveproxy/src/net/cert/ct_log_verifier_util.cc @@ -4,24 +4,23 @@ #include "net/cert/ct_log_verifier_util.h" -#include +#include -#include "base/strings/string_util.h" -#include "crypto/secure_hash.h" -#include "crypto/sha2.h" +#include "base/containers/span.h" +#include "crypto/hash.h" namespace net::ct::internal { std::string HashNodes(const std::string& lh, const std::string& rh) { - std::unique_ptr hash( - crypto::SecureHash::Create(crypto::SecureHash::SHA256)); + static constexpr std::array kTag = {0x01}; - hash->Update("\01", 1); - hash->Update(lh.data(), lh.size()); - hash->Update(rh.data(), rh.size()); + crypto::hash::Hasher hash(crypto::hash::kSha256); + hash.Update(kTag); + hash.Update(lh); + hash.Update(rh); - std::string result(crypto::kSHA256Length, '\0'); - hash->Finish(result.data(), result.size()); + std::string result(crypto::hash::kSha256Size, '\0'); + hash.Finish(base::as_writable_byte_span(result)); return result; } diff --git a/naiveproxy/src/net/cert/ct_objects_extractor.cc b/naiveproxy/src/net/cert/ct_objects_extractor.cc index e542c9cd8e..f1de10f72e 100644 --- a/naiveproxy/src/net/cert/ct_objects_extractor.cc +++ b/naiveproxy/src/net/cert/ct_objects_extractor.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/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "net/cert/ct_objects_extractor.h" #include @@ -49,7 +44,8 @@ const uint8_t kSHA256Oid[] = {0x60, 0x86, 0x48, 0x01, 0x65, bool StringEqualToCBS(const std::string& value1, const CBS* value2) { if (CBS_len(value2) != value1.size()) return false; - return memcmp(value1.data(), CBS_data(value2), CBS_len(value2)) == 0; + return UNSAFE_TODO( + memcmp(value1.data(), CBS_data(value2), CBS_len(value2))) == 0; } bool SkipElements(CBS* cbs, int count) { diff --git a/naiveproxy/src/net/cert/ct_serialization.cc b/naiveproxy/src/net/cert/ct_serialization.cc index 4530b7c9f1..ab4d749677 100644 --- a/naiveproxy/src/net/cert/ct_serialization.cc +++ b/naiveproxy/src/net/cert/ct_serialization.cc @@ -227,7 +227,7 @@ static bool ReadTimeSinceEpoch(CBS* input, base::Time* output) { return true; } -static bool WriteTimeSinceEpoch(const base::Time& timestamp, CBB* output) { +static bool WriteTimeSinceEpoch(base::Time timestamp, CBB* output) { base::TimeDelta time_since_epoch = timestamp - base::Time::UnixEpoch(); return CBB_add_u64(output, time_since_epoch.InMilliseconds()); } @@ -252,7 +252,7 @@ bool EncodeTreeLeaf(const MerkleTreeLeaf& leaf, std::string* output) { return true; } -bool EncodeV1SCTSignedData(const base::Time& timestamp, +bool EncodeV1SCTSignedData(base::Time timestamp, const std::string& serialized_log_entry, const std::string& extensions, std::string* output) { diff --git a/naiveproxy/src/net/cert/ct_serialization.h b/naiveproxy/src/net/cert/ct_serialization.h index fd438544f6..f51a4e78e4 100644 --- a/naiveproxy/src/net/cert/ct_serialization.h +++ b/naiveproxy/src/net/cert/ct_serialization.h @@ -54,7 +54,7 @@ NET_EXPORT bool EncodeTreeLeaf(const MerkleTreeLeaf& leaf, std::string* output); // Returns true if the extensions' length does not exceed // kMaxExtensionsLength, false otherwise. NET_EXPORT_PRIVATE bool EncodeV1SCTSignedData( - const base::Time& timestamp, + base::Time timestamp, const std::string& serialized_log_entry, const std::string& extensions, std::string* output); diff --git a/naiveproxy/src/net/cert/ev_root_ca_metadata.cc b/naiveproxy/src/net/cert/ev_root_ca_metadata.cc index 30a627f0af..25be2e5ff9 100644 --- a/naiveproxy/src/net/cert/ev_root_ca_metadata.cc +++ b/naiveproxy/src/net/cert/ev_root_ca_metadata.cc @@ -7,8 +7,8 @@ #include #include "base/containers/contains.h" -#include "base/lazy_instance.h" #include "base/logging.h" +#include "base/no_destructor.h" #include "build/build_config.h" #include "third_party/boringssl/src/pki/input.h" #if defined(PLATFORM_USES_CHROMIUM_EV_METADATA) @@ -41,12 +41,10 @@ struct EVMetadata { #endif // defined(PLATFORM_USES_CHROMIUM_EV_METADATA) } // namespace -static base::LazyInstance::Leaky g_ev_root_ca_metadata = - LAZY_INSTANCE_INITIALIZER; - // static EVRootCAMetadata* EVRootCAMetadata::GetInstance() { - return g_ev_root_ca_metadata.Pointer(); + static base::NoDestructor ev_root_ca_metadata; + return ev_root_ca_metadata.get(); } #if defined(PLATFORM_USES_CHROMIUM_EV_METADATA) diff --git a/naiveproxy/src/net/cert/ev_root_ca_metadata.h b/naiveproxy/src/net/cert/ev_root_ca_metadata.h index 3ccefd852e..53c3ec91d5 100644 --- a/naiveproxy/src/net/cert/ev_root_ca_metadata.h +++ b/naiveproxy/src/net/cert/ev_root_ca_metadata.h @@ -5,13 +5,13 @@ #ifndef NET_CERT_EV_ROOT_CA_METADATA_H_ #define NET_CERT_EV_ROOT_CA_METADATA_H_ -#include "build/build_config.h" - #include #include #include #include +#include "base/no_destructor.h" +#include "build/build_config.h" #include "crypto/crypto_buildflags.h" #include "net/base/net_export.h" #include "net/cert/x509_certificate.h" @@ -23,11 +23,6 @@ #define PLATFORM_USES_CHROMIUM_EV_METADATA #endif -namespace base { -template -struct LazyInstanceTraitsBase; -} // namespace base - namespace bssl { namespace der { class Input; @@ -63,7 +58,7 @@ class NET_EXPORT_PRIVATE EVRootCAMetadata { bool RemoveEVCA(const SHA256HashValue& fingerprint); private: - friend struct base::LazyInstanceTraitsBase; + friend class base::NoDestructor; EVRootCAMetadata(); ~EVRootCAMetadata(); diff --git a/naiveproxy/src/net/cert/internal/system_trust_store.cc b/naiveproxy/src/net/cert/internal/system_trust_store.cc index 97b5663bb6..6187b2b653 100644 --- a/naiveproxy/src/net/cert/internal/system_trust_store.cc +++ b/naiveproxy/src/net/cert/internal/system_trust_store.cc @@ -38,7 +38,6 @@ #include "net/cert/internal/trust_store_mac.h" #include "net/cert/x509_util_apple.h" #elif BUILDFLAG(IS_FUCHSIA) -#include "base/lazy_instance.h" #include "third_party/boringssl/src/include/openssl/pool.h" #elif BUILDFLAG(IS_WIN) #include "net/cert/internal/trust_store_win.h" @@ -292,8 +291,10 @@ class FuchsiaSystemCerts { bssl::TrustStoreInMemory system_trust_store_; }; -base::LazyInstance::Leaky g_root_certs_fuchsia = - LAZY_INSTANCE_INITIALIZER; +FuchsiaSystemCerts& GetFuchsiaRootCerts() { + static base::NoDestructor certs; + return *certs; +} } // namespace @@ -302,12 +303,11 @@ class SystemTrustStoreFuchsia : public SystemTrustStore { SystemTrustStoreFuchsia() = default; bssl::TrustStore* GetTrustStore() override { - return g_root_certs_fuchsia.Get().system_trust_store(); + return GetFuchsiaRootCerts().system_trust_store(); } bool IsKnownRoot(const bssl::ParsedCertificate* trust_anchor) const override { - return g_root_certs_fuchsia.Get().system_trust_store()->Contains( - trust_anchor); + return GetFuchsiaRootCerts().system_trust_store()->Contains(trust_anchor); } }; diff --git a/naiveproxy/src/net/cert/internal/trust_store_chrome.cc b/naiveproxy/src/net/cert/internal/trust_store_chrome.cc index 0d4c711239..a6288be581 100644 --- a/naiveproxy/src/net/cert/internal/trust_store_chrome.cc +++ b/naiveproxy/src/net/cert/internal/trust_store_chrome.cc @@ -74,29 +74,16 @@ ChromeRootStoreData::Anchor::Anchor( : ChromeRootStoreData::Anchor::Anchor( certificate, constraints, - /*eutl=*/false, /*enforce_anchor_expiry=*/false, /*enforce_anchor_constraints=*/false) {} ChromeRootStoreData::Anchor::Anchor( std::shared_ptr certificate, std::vector constraints, - bool eutl) - : ChromeRootStoreData::Anchor::Anchor( - certificate, - constraints, - eutl, - /*enforce_anchor_expiry=*/false, - /*enforce_anchor_constraints=*/false) {} -ChromeRootStoreData::Anchor::Anchor( - std::shared_ptr certificate, - std::vector constraints, - bool eutl, bool enforce_anchor_expiry, bool enforce_anchor_constraints) : certificate(std::move(certificate)), constraints(std::move(constraints)), - eutl(eutl), enforce_anchor_expiry(enforce_anchor_expiry), enforce_anchor_constraints(enforce_anchor_constraints) {} ChromeRootStoreData::Anchor::~Anchor() = default; @@ -168,9 +155,9 @@ std::optional CreateChromeRootStoreDataAnchor( min_version, max_version_exclusive, base::ToVector(constraint.permitted_dns_names())); } - return ChromeRootStoreData::Anchor( - std::move(parsed), std::move(constraints), anchor.eutl(), - anchor.enforce_anchor_expiry(), anchor.enforce_anchor_constraints()); + return ChromeRootStoreData::Anchor(std::move(parsed), std::move(constraints), + anchor.enforce_anchor_expiry(), + anchor.enforce_anchor_constraints()); } } // namespace @@ -189,6 +176,10 @@ ChromeRootStoreData::CreateFromRootStoreProto( if (!chrome_root_store_data_anchor) { return std::nullopt; } + if (anchor.eutl()) { + root_store_data.eutl_certs_.emplace_back( + chrome_root_store_data_anchor.value()); + } root_store_data.trust_anchors_.emplace_back( std::move(chrome_root_store_data_anchor.value())); } @@ -200,12 +191,13 @@ ChromeRootStoreData::CreateFromRootStoreProto( if (!chrome_root_store_data_anchor) { return std::nullopt; } + if (anchor.eutl()) { + root_store_data.eutl_certs_.emplace_back( + chrome_root_store_data_anchor.value()); + } if (anchor.tls_trust_anchor()) { root_store_data.trust_anchors_.emplace_back( std::move(chrome_root_store_data_anchor.value())); - } else { - root_store_data.additional_certs_.emplace_back( - std::move(chrome_root_store_data_anchor.value())); } } @@ -263,7 +255,7 @@ ChromeRootStoreData::ChromeRootStoreData( cert_constraints.emplace_back(constraint); } trust_anchors_.emplace_back(std::move(parsed), std::move(cert_constraints), - /*eutl=*/false, cert_info.enforce_anchor_expiry, + cert_info.enforce_anchor_expiry, cert_info.enforce_anchor_constraints); } @@ -278,9 +270,8 @@ ChromeRootStoreData::ChromeRootStoreData( auto parsed = bssl::ParsedCertificate::Create( std::move(cert), x509_util::DefaultParseCertificateOptions(), &errors); CHECK(parsed); - additional_certs_.emplace_back(std::move(parsed), - std::vector(), - /*eutl=*/true); + eutl_certs_.emplace_back(std::move(parsed), + std::vector()); } } @@ -316,15 +307,9 @@ TrustStoreChrome::TrustStoreChrome(const ChromeRootStoreData& root_store_data, certificate_trust = certificate_trust.WithEnforceAnchorConstraints(); } trust_store_.AddCertificate(anchor.certificate, certificate_trust); - - if (anchor.eutl) { - eutl_trust_store_.AddTrustAnchor(anchor.certificate); - } } - for (const auto& anchor : root_store_data.additional_certs()) { - if (anchor.eutl) { - eutl_trust_store_.AddTrustAnchor(anchor.certificate); - } + for (const auto& anchor : root_store_data.eutl_certs()) { + eutl_trust_store_.AddTrustAnchor(anchor.certificate); } constraints_ = base::flat_map(std::move(constraints)); diff --git a/naiveproxy/src/net/cert/internal/trust_store_chrome.h b/naiveproxy/src/net/cert/internal/trust_store_chrome.h index f67d211497..24db98717a 100644 --- a/naiveproxy/src/net/cert/internal/trust_store_chrome.h +++ b/naiveproxy/src/net/cert/internal/trust_store_chrome.h @@ -17,7 +17,6 @@ #include "third_party/boringssl/src/pki/trust_store.h" #include "third_party/boringssl/src/pki/trust_store_in_memory.h" -// Forward declares this so root_store.pb.h would not be a public dependency. namespace chrome_root_store { class RootStore; } @@ -87,10 +86,6 @@ class NET_EXPORT ChromeRootStoreData { std::vector constraints); Anchor(std::shared_ptr certificate, std::vector constraints, - bool eutl); - Anchor(std::shared_ptr certificate, - std::vector constraints, - bool eutl, bool enforce_anchor_expiry, bool enforce_anchor_constraints); ~Anchor(); @@ -102,7 +97,6 @@ class NET_EXPORT ChromeRootStoreData { std::shared_ptr certificate; std::vector constraints; - bool eutl; bool enforce_anchor_expiry; // True if the certificate verifier should enforce X.509 constraints encoded // in the certificate. @@ -133,9 +127,7 @@ class NET_EXPORT ChromeRootStoreData { ChromeRootStoreData& operator=(ChromeRootStoreData&& other); const std::vector& trust_anchors() const { return trust_anchors_; } - const std::vector& additional_certs() const { - return additional_certs_; - } + const std::vector& eutl_certs() const { return eutl_certs_; } int64_t version() const { return version_; } private: @@ -146,7 +138,7 @@ class NET_EXPORT ChromeRootStoreData { int64_t version); std::vector trust_anchors_; - std::vector additional_certs_; + std::vector eutl_certs_; int64_t version_; }; diff --git a/naiveproxy/src/net/cert/internal/trust_store_mac.cc b/naiveproxy/src/net/cert/internal/trust_store_mac.cc index 3841adf003..0c870fc7d3 100644 --- a/naiveproxy/src/net/cert/internal/trust_store_mac.cc +++ b/naiveproxy/src/net/cert/internal/trust_store_mac.cc @@ -4,6 +4,7 @@ #include "net/cert/internal/trust_store_mac.h" +#include #include #include @@ -13,7 +14,6 @@ #include "base/apple/foundation_util.h" #include "base/apple/osstatus_logging.h" #include "base/apple/scoped_cftyperef.h" -#include "base/atomicops.h" #include "base/callback_list.h" #include "base/containers/contains.h" #include "base/containers/flat_map.h" @@ -537,7 +537,7 @@ class KeychainObserver { // Returns the current iteration count, which is incremented every time // keychain trust settings change. This may be called from any thread. - int64_t Iteration() const { return base::subtle::Acquire_Load(&iteration_); } + int64_t Iteration() const { return iteration_.load(std::memory_order_acquire); } private: void RegisterCallbackOnNotificationThread() { @@ -547,12 +547,12 @@ class KeychainObserver { &KeychainObserver::Increment, base::Unretained(this))); } - void Increment() { base::subtle::Barrier_AtomicIncrement(&iteration_, 1); } + void Increment() { iteration_.fetch_add(1); } // Only accessed on the notification thread. base::CallbackListSubscription subscription_; - base::subtle::Atomic64 iteration_ = 0; + std::atomic iteration_{0}; }; using KeychainTrustObserver = diff --git a/naiveproxy/src/net/cert/known_roots.cc b/naiveproxy/src/net/cert/known_roots.cc index cbae1a6771..17f8fffdd5 100644 --- a/naiveproxy/src/net/cert/known_roots.cc +++ b/naiveproxy/src/net/cert/known_roots.cc @@ -17,23 +17,18 @@ namespace net { namespace { // Comparator-predicate that serves as a < function for comparing a -// RootCertData to a HashValue +// RootCertData to a SHA256HashValue. struct HashValueToRootCertDataComp { - bool operator()(const HashValue& hash, const RootCertData& root_cert) { - DCHECK_EQ(HASH_VALUE_SHA256, hash.tag()); - return hash.span() < root_cert.sha256_spki_hash; + bool operator()(const SHA256HashValue& hash, const RootCertData& root_cert) { + return hash < base::span(root_cert.sha256_spki_hash); } - bool operator()(const RootCertData& root_cert, const HashValue& hash) { - DCHECK_EQ(HASH_VALUE_SHA256, hash.tag()); - return root_cert.sha256_spki_hash < hash.span(); + bool operator()(const RootCertData& root_cert, const SHA256HashValue& hash) { + return base::span(root_cert.sha256_spki_hash) < hash; } }; -const RootCertData* GetRootCertData(const HashValue& spki_hash) { - if (spki_hash.tag() != HASH_VALUE_SHA256) - return nullptr; - +const RootCertData* GetRootCertData(const SHA256HashValue& spki_hash) { auto* it = std::lower_bound(std::begin(kRootCerts), std::end(kRootCerts), spki_hash, HashValueToRootCertDataComp()); if (it == std::end(kRootCerts) || @@ -45,7 +40,7 @@ const RootCertData* GetRootCertData(const HashValue& spki_hash) { } // namespace -int32_t GetNetTrustAnchorHistogramIdForSPKI(const HashValue& spki_hash) { +int32_t GetNetTrustAnchorHistogramIdForSPKI(const SHA256HashValue& spki_hash) { const RootCertData* root_data = GetRootCertData(spki_hash); if (!root_data) return 0; diff --git a/naiveproxy/src/net/cert/known_roots.h b/naiveproxy/src/net/cert/known_roots.h index 44ecb76d3a..6ebffc9251 100644 --- a/naiveproxy/src/net/cert/known_roots.h +++ b/naiveproxy/src/net/cert/known_roots.h @@ -8,17 +8,16 @@ #include #include "build/build_config.h" +#include "net/base/hash_value.h" #include "net/base/net_export.h" namespace net { -class HashValue; - // Returns a value within the NetRootCert histogram enum indicating the // ID of the trust anchor whose subjectPublicKeyInfo hash is |spki_hash|, or // 0 if it cannot be found. NET_EXPORT int32_t -GetNetTrustAnchorHistogramIdForSPKI(const HashValue& spki_hash); +GetNetTrustAnchorHistogramIdForSPKI(const SHA256HashValue& spki_hash); } // namespace net diff --git a/naiveproxy/src/net/cert/multi_threaded_cert_verifier.cc b/naiveproxy/src/net/cert/multi_threaded_cert_verifier.cc index d8bd03f9b8..1809802335 100644 --- a/naiveproxy/src/net/cert/multi_threaded_cert_verifier.cc +++ b/naiveproxy/src/net/cert/multi_threaded_cert_verifier.cc @@ -13,9 +13,9 @@ #include "base/task/thread_pool.h" #include "base/threading/thread_restrictions.h" #include "base/timer/elapsed_timer.h" +#include "base/trace_event/trace_event.h" #include "net/base/net_errors.h" #include "net/base/trace_constants.h" -#include "net/base/tracing.h" #include "net/base/url_util.h" #include "net/cert/cert_verify_proc.h" #include "net/cert/cert_verify_result.h" diff --git a/naiveproxy/src/net/cert/require_ct_delegate.cc b/naiveproxy/src/net/cert/require_ct_delegate.cc index b1ec56d279..e891057507 100644 --- a/naiveproxy/src/net/cert/require_ct_delegate.cc +++ b/naiveproxy/src/net/cert/require_ct_delegate.cc @@ -11,7 +11,7 @@ ct::CTRequirementsStatus RequireCTDelegate::CheckCTRequirements( const RequireCTDelegate* delegate, std::string_view host, bool is_issued_by_known_root, - const HashValueVector& public_key_hashes, + const std::vector& public_key_hashes, const X509Certificate* validated_certificate_chain, ct::CTPolicyCompliance policy_compliance) { // CT is not required if the certificate does not chain to a publicly diff --git a/naiveproxy/src/net/cert/require_ct_delegate.h b/naiveproxy/src/net/cert/require_ct_delegate.h index eb7d5088ad..8c89095457 100644 --- a/naiveproxy/src/net/cert/require_ct_delegate.h +++ b/naiveproxy/src/net/cert/require_ct_delegate.h @@ -38,13 +38,12 @@ class NET_EXPORT RequireCTDelegate // the default handling of Certificate Transparency requirements, if // desired. // |hostname| contains the host being contacted, serving the certificate - // |chain|, with the set of hashes |hashes|. Note that |hashes| and - // |chain| are not guaranteed to be in the same order - that is, the first - // hash in |hashes| is NOT guaranteed to be for the leaf cert in |chain|. + // |chain|, with the hashes |hashes| which must be in the same order as the + // certificate chain (leaf to root). virtual CTRequirementLevel IsCTRequiredForHost( std::string_view hostname, const X509Certificate* chain, - const HashValueVector& hashes) const = 0; + const std::vector& hashes) const = 0; // Returns CT_REQUIREMENTS_NOT_MET if a connection violates CT policy // requirements: that is, if a connection to |host|, using the validated @@ -53,12 +52,15 @@ class NET_EXPORT RequireCTDelegate // connection's CTPolicyEnforcer and |policy_compliance| indicates that // the connection does not comply. // + // |public_key_hashes| must be in the same order as the certificate chain + // (leaf to root). + // // If |delegate| is null, CT will not be required. static ct::CTRequirementsStatus CheckCTRequirements( const RequireCTDelegate* delegate, std::string_view host, bool is_issued_by_known_root, - const HashValueVector& public_key_hashes, + const std::vector& public_key_hashes, const X509Certificate* validated_certificate_chain, ct::CTPolicyCompliance policy_compliance); diff --git a/naiveproxy/src/net/cert/signed_tree_head.cc b/naiveproxy/src/net/cert/signed_tree_head.cc index 1d725f5e9c..9ffc2cb44f 100644 --- a/naiveproxy/src/net/cert/signed_tree_head.cc +++ b/naiveproxy/src/net/cert/signed_tree_head.cc @@ -19,7 +19,7 @@ SignedTreeHead::SignedTreeHead() = default; SignedTreeHead::SignedTreeHead( Version version, - const base::Time& timestamp, + base::Time timestamp, uint64_t tree_size, base::span sha256_root_hash, const DigitallySigned& signature, diff --git a/naiveproxy/src/net/cert/signed_tree_head.h b/naiveproxy/src/net/cert/signed_tree_head.h index d8fcc28bf6..7fce78ea1d 100644 --- a/naiveproxy/src/net/cert/signed_tree_head.h +++ b/naiveproxy/src/net/cert/signed_tree_head.h @@ -28,7 +28,7 @@ struct NET_EXPORT SignedTreeHead { SignedTreeHead(); SignedTreeHead(Version version, - const base::Time& timestamp, + base::Time timestamp, uint64_t tree_size, base::span sha256_root_hash, const DigitallySigned& signature, diff --git a/naiveproxy/src/net/cert/test_root_certs.cc b/naiveproxy/src/net/cert/test_root_certs.cc index dca48d5c11..b434fac85d 100644 --- a/naiveproxy/src/net/cert/test_root_certs.cc +++ b/naiveproxy/src/net/cert/test_root_certs.cc @@ -20,9 +20,6 @@ namespace { bool g_has_instance = false; -base::LazyInstance::Leaky - g_test_root_certs = LAZY_INSTANCE_INITIALIZER; - } // namespace bool ThreadSafeTrustStoreInMemory::IsEmpty() const { @@ -57,7 +54,8 @@ bssl::CertificateTrust ThreadSafeTrustStoreInMemory::GetTrust( // static TestRootCerts* TestRootCerts::GetInstance() { - return g_test_root_certs.Pointer(); + static base::NoDestructor test_root_certs; + return test_root_certs.get(); } bool TestRootCerts::HasInstance() { diff --git a/naiveproxy/src/net/cert/test_root_certs.h b/naiveproxy/src/net/cert/test_root_certs.h index 49742accc9..874274aa32 100644 --- a/naiveproxy/src/net/cert/test_root_certs.h +++ b/naiveproxy/src/net/cert/test_root_certs.h @@ -8,8 +8,8 @@ #include #include "base/containers/span.h" -#include "base/lazy_instance.h" #include "base/memory/scoped_refptr.h" +#include "base/no_destructor.h" #include "base/synchronization/lock.h" #include "build/build_config.h" #include "net/base/net_export.h" @@ -82,7 +82,7 @@ class NET_EXPORT TestRootCerts { bssl::TrustStore* test_trust_store() { return &test_trust_store_; } private: - friend struct base::LazyInstanceTraitsBase; + friend class base::NoDestructor; friend class ScopedTestRoot; friend class ScopedTestKnownRoot; diff --git a/naiveproxy/src/net/cert/time_conversions.cc b/naiveproxy/src/net/cert/time_conversions.cc index 885f3bb987..12022b6deb 100644 --- a/naiveproxy/src/net/cert/time_conversions.cc +++ b/naiveproxy/src/net/cert/time_conversions.cc @@ -12,7 +12,7 @@ namespace net { -bool EncodeTimeAsGeneralizedTime(const base::Time& time, +bool EncodeTimeAsGeneralizedTime(base::Time time, bssl::der::GeneralizedTime* generalized_time) { return bssl::der::EncodePosixTimeAsGeneralizedTime( (time - base::Time::UnixEpoch()).InSecondsFloored(), generalized_time); diff --git a/naiveproxy/src/net/cert/time_conversions.h b/naiveproxy/src/net/cert/time_conversions.h index 37a1030fb4..6c75b64ef3 100644 --- a/naiveproxy/src/net/cert/time_conversions.h +++ b/naiveproxy/src/net/cert/time_conversions.h @@ -28,7 +28,7 @@ namespace net { // the time is not representable as a Generalized time.The millisecond component // of |time| is discarded. NET_EXPORT bool EncodeTimeAsGeneralizedTime( - const base::Time& time, + base::Time time, bssl::der::GeneralizedTime* generalized_time); // Converts a GeneralizedTime struct to a base::Time, returning true on success diff --git a/naiveproxy/src/net/cert/two_qwac.cc b/naiveproxy/src/net/cert/two_qwac.cc index e5ae44e4ff..3cafa1bf7d 100644 --- a/naiveproxy/src/net/cert/two_qwac.cc +++ b/naiveproxy/src/net/cert/two_qwac.cc @@ -9,10 +9,10 @@ #include "base/containers/contains.h" #include "base/json/json_reader.h" #include "base/strings/string_split.h" +#include "crypto/evp.h" #include "crypto/signature_verifier.h" #include "net/cert/asn1_util.h" #include "net/cert/x509_util.h" -#include "third_party/boringssl/src/include/openssl/bytestring.h" #include "third_party/boringssl/src/include/openssl/ec.h" #include "third_party/boringssl/src/include/openssl/ec_key.h" @@ -414,9 +414,7 @@ namespace { // Given a SPKI, returns whether the public key is an ECDSA key on the curve // P-256. bool IsKeyP256(base::span spki) { - CBS cbs; - CBS_init(&cbs, spki.data(), spki.size()); - bssl::UniquePtr public_key(EVP_parse_public_key(&cbs)); + bssl::UniquePtr public_key = crypto::evp::PublicKeyFromBytes(spki); if (!public_key) { return false; } @@ -446,7 +444,7 @@ bool TwoQwacCertBinding::VerifySignature() { // attempt to apply the processes that it describes generically for AdES // signatures, we encounter a problem in the cryptographic validation building // block in clause 5.2.7.4. That clause states that the technical details on - // how to perform the cryptogrpahic validation are out of scope, and to see + // how to perform the cryptographic validation are out of scope, and to see // other documents for details. None of the listed documents provide any // details about JAdES signatures or JWSs. // diff --git a/naiveproxy/src/net/cert/x509_certificate.cc b/naiveproxy/src/net/cert/x509_certificate.cc index d2481ae117..789e8e69e2 100644 --- a/naiveproxy/src/net/cert/x509_certificate.cc +++ b/naiveproxy/src/net/cert/x509_certificate.cc @@ -22,10 +22,11 @@ #include "base/strings/string_util.h" #include "base/strings/string_view_util.h" #include "base/time/time.h" +#include "base/trace_event/trace_event.h" +#include "crypto/evp.h" #include "crypto/hash.h" #include "crypto/openssl_util.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" -#include "net/base/tracing.h" #include "net/base/url_util.h" #include "net/cert/asn1_util.h" #include "net/cert/time_conversions.h" @@ -613,11 +614,9 @@ void X509Certificate::GetPublicKeyInfo(const CRYPTO_BUFFER* cert_buffer, return; } - bssl::UniquePtr pkey; crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); - CBS cbs; - CBS_init(&cbs, reinterpret_cast(spki.data()), spki.size()); - pkey.reset(EVP_parse_public_key(&cbs)); + bssl::UniquePtr pkey = + crypto::evp::PublicKeyFromBytes(base::as_byte_span(spki)); if (!pkey) return; diff --git a/naiveproxy/src/net/cert/x509_certificate.h b/naiveproxy/src/net/cert/x509_certificate.h index 60470fdd71..eb20e40456 100644 --- a/naiveproxy/src/net/cert/x509_certificate.h +++ b/naiveproxy/src/net/cert/x509_certificate.h @@ -172,8 +172,15 @@ class NET_EXPORT X509Certificate // the |valid_expiry| date. // If we were unable to parse either date from the certificate (or if the cert // lacks either date), the date will be null (i.e., is_null() will be true). - const base::Time& valid_start() const { return parsed_.valid_start_; } - const base::Time& valid_expiry() const { return parsed_.valid_expiry_; } + base::Time valid_start() const { return parsed_.valid_start_; } + base::Time valid_expiry() const { return parsed_.valid_expiry_; } + + void set_valid_start_for_testing(base::Time time) { + const_cast(parsed_).valid_start_ = time; + } + void set_valid_expiry_for_testing(base::Time time) { + const_cast(parsed_).valid_expiry_ = time; + } // Gets the subjectAltName extension field from the certificate, if any. // For future extension; currently this only returns those name types that diff --git a/naiveproxy/src/net/cert/x509_util.cc b/naiveproxy/src/net/cert/x509_util.cc index 97869d31fe..4ef57a103c 100644 --- a/naiveproxy/src/net/cert/x509_util.cc +++ b/naiveproxy/src/net/cert/x509_util.cc @@ -11,6 +11,7 @@ #include #include "base/containers/span.h" +#include "base/containers/to_vector.h" #include "base/logging.h" #include "base/memory/raw_ptr.h" #include "base/notreached.h" @@ -20,8 +21,8 @@ #include "base/time/time.h" #include "build/build_config.h" #include "crypto/hash.h" +#include "crypto/keypair.h" #include "crypto/openssl_util.h" -#include "crypto/rsa_private_key.h" #include "net/base/hash_value.h" #include "net/cert/asn1_util.h" #include "net/cert/time_conversions.h" @@ -281,31 +282,16 @@ bool GetTLSServerEndPointChannelBinding(const X509Certificate& certificate, return true; } -// RSA keys created by CreateKeyAndSelfSignedCert will be of this length. -static const uint16_t kRSAKeyLength = 1024; +std::vector CreateUnusableCert(std::string_view subject) { + const uint32_t kSerial = 1; + const base::Time not_valid_before = base::Time::Now() - base::Minutes(5); + const base::Time not_valid_after = base::Time::Now() + base::Hours(1); + auto key = crypto::keypair::PrivateKey::GenerateEcP256(); + std::string der_cert; + CHECK(CreateSelfSignedCert(key.key(), DIGEST_SHA256, subject, kSerial, + not_valid_before, not_valid_after, {}, &der_cert)); -// Certificates made by CreateKeyAndSelfSignedCert will be signed using this -// digest algorithm. -static const DigestAlgorithm kSignatureDigestAlgorithm = DIGEST_SHA256; - -bool CreateKeyAndSelfSignedCert(std::string_view subject, - uint32_t serial_number, - base::Time not_valid_before, - base::Time not_valid_after, - std::unique_ptr* key, - std::string* der_cert) { - std::unique_ptr new_key( - crypto::RSAPrivateKey::Create(kRSAKeyLength)); - if (!new_key) - return false; - - bool success = CreateSelfSignedCert(new_key->key(), kSignatureDigestAlgorithm, - subject, serial_number, not_valid_before, - not_valid_after, {}, der_cert); - if (success) - *key = std::move(new_key); - - return success; + return base::ToVector(base::as_byte_span(der_cert)); } Extension::Extension(base::span in_oid, @@ -510,12 +496,13 @@ bssl::ParseCertificateOptions DefaultParseCertificateOptions() { return options; } -bool CalculateSha256SpkiHash(const CRYPTO_BUFFER* buffer, HashValue* hash) { +bool CalculateSha256SpkiHash(const CRYPTO_BUFFER* buffer, + SHA256HashValue* hash) { std::string_view spki; if (!asn1::ExtractSPKIFromDERCert(CryptoBufferAsStringPiece(buffer), &spki)) { return false; } - *hash = HashValue(crypto::hash::Sha256(base::as_byte_span(spki))); + *hash = crypto::hash::Sha256(base::as_byte_span(spki)); return true; } diff --git a/naiveproxy/src/net/cert/x509_util.h b/naiveproxy/src/net/cert/x509_util.h index 25be9fe32c..2b3688158a 100644 --- a/naiveproxy/src/net/cert/x509_util.h +++ b/naiveproxy/src/net/cert/x509_util.h @@ -24,10 +24,6 @@ #include "third_party/boringssl/src/include/openssl/pool.h" #include "third_party/boringssl/src/pki/parsed_certificate.h" -namespace crypto { -class RSAPrivateKey; -} - namespace net { namespace x509_util { @@ -67,28 +63,17 @@ NET_EXPORT_PRIVATE bool GetTLSServerEndPointChannelBinding( const X509Certificate& certificate, std::string* token); -// Creates a public-private keypair and a self-signed certificate. -// Subject, serial number and validity period are given as parameters. -// The certificate is signed by the private key in |key|. The key length and -// signature algorithm may be updated periodically to match best practices. +// Creates a certificate which cannot be used: a random private key is +// generated, then a self-signed certificate using that private key is created +// and the private key is discarded. The resulting cert can never be used to +// actually authenticate anything because the private key is unknown, so this +// function is only useful for test and demonstration purposes. // -// |subject| specifies the subject and issuer names as in AddName() -// -// SECURITY WARNING -// -// Using self-signed certificates has the following security risks: -// 1. Encryption without authentication and thus vulnerable to -// man-in-the-middle attacks. -// 2. Self-signed certificates cannot be revoked. -// -// Use this certificate only after the above risks are acknowledged. -NET_EXPORT bool CreateKeyAndSelfSignedCert( - std::string_view subject, - uint32_t serial_number, - base::Time not_valid_before, - base::Time not_valid_after, - std::unique_ptr* key, - std::string* der_cert); +// |subject| specifies the subject and issuer names as in AddName() - a string +// consisting of a very small subset of the X.509 DN syntax. All fields of the +// cert that are not specified here are hardcoded. The certificate's lifetime is +// always from 5 minutes ago to 1 hour from now. +NET_EXPORT std::vector CreateUnusableCert(std::string_view subject); struct NET_EXPORT Extension { Extension(base::span oid, @@ -186,7 +171,7 @@ NET_EXPORT bssl::ParseCertificateOptions DefaultParseCertificateOptions(); // valid certificate, returns false and |hash| is in an undefined state. [[nodiscard]] NET_EXPORT bool CalculateSha256SpkiHash( const CRYPTO_BUFFER* buffer, - HashValue* hash); + SHA256HashValue* hash); // Calls |verifier->VerifyInit|, using the public key from |certificate|, // checking if the digitalSignature key usage bit is present, and returns true diff --git a/naiveproxy/src/net/cookies/canonical_cookie.cc b/naiveproxy/src/net/cookies/canonical_cookie.cc index ce288147d3..d51bb27abf 100644 --- a/naiveproxy/src/net/cookies/canonical_cookie.cc +++ b/naiveproxy/src/net/cookies/canonical_cookie.cc @@ -58,6 +58,7 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_functions.h" +#include "base/metrics/histogram_macros.h" #include "base/rand_util.h" #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" @@ -178,8 +179,8 @@ CanonicalCookie::~CanonicalCookie() = default; // static Time CanonicalCookie::ParseExpiration(const ParsedCookie& pc, - const Time& current, - const Time& server_time) { + Time current, + Time server_time) { // First, try the Max-Age attribute. if (pc.MaxAge().has_value()) { int64_t max_age = 0; @@ -266,8 +267,8 @@ Time CanonicalCookie::ParseExpiration(const ParsedCookie& pc, // static base::Time CanonicalCookie::ValidateAndAdjustExpiryDate( - const base::Time& expiry_date, - const base::Time& creation_date, + base::Time expiry_date, + base::Time creation_date, net::CookieSourceScheme scheme) { if (expiry_date.is_null()) return expiry_date; @@ -300,7 +301,7 @@ base::Time CanonicalCookie::ValidateAndAdjustExpiryDate( std::unique_ptr CanonicalCookie::Create( const GURL& url, std::string_view cookie_line, - const base::Time& creation_time, + base::Time creation_time, std::optional server_time, std::optional cookie_partition_key, CookieSourceType source_type, @@ -415,8 +416,7 @@ std::unique_ptr CanonicalCookie::Create( if (!status->IsInclude()) return nullptr; - CookieSameSiteString samesite_string = CookieSameSiteString::kUnspecified; - CookieSameSite samesite = parsed_cookie.SameSite(&samesite_string); + auto [samesite, samesite_string] = parsed_cookie.SameSite(); // The next two sections set the source_scheme_ and source_port_. Normally // these are taken directly from the url's scheme and port but if the url @@ -643,11 +643,9 @@ std::unique_ptr CanonicalCookie::CreateSanitizedCookie( std::string cookie_path = cookie_util::CanonPathWithString(url, path); // Canonicalize path again to make sure it escapes characters as needed. - url::Component path_component(0, cookie_path.length()); url::RawCanonOutputT canon_path; url::Component canon_path_component; - url::CanonicalizePath(cookie_path.data(), path_component, &canon_path, - &canon_path_component); + url::CanonicalizePath(cookie_path, &canon_path, &canon_path_component); std::string_view encoded_cookie_path = canon_path.view().substr( canon_path_component.begin, canon_path_component.len); @@ -667,8 +665,8 @@ std::unique_ptr CanonicalCookie::CreateSanitizedCookie( } CookiePrefix prefix = cookie_util::GetCookiePrefix(name); - if (!cookie_util::IsCookiePrefixValid(prefix, url, secure, domain_attribute, - cookie_path)) { + if (!cookie_util::IsCookiePrefixValid(prefix, url, secure, http_only, + domain_attribute, cookie_path)) { status->AddExclusionReason( net::CookieInclusionStatus::ExclusionReason::EXCLUDE_INVALID_PREFIX); } @@ -749,8 +747,8 @@ std::unique_ptr CanonicalCookie::FromStorage( // not have a valid name+value size length bool valid_cookie_name_value_pair = ParsedCookie::IsValidCookieNameValuePair(cc->Name(), cc->Value()); - base::UmaHistogramBoolean("Cookie.FromStorageWithValidLength", - valid_cookie_name_value_pair); + UMA_HISTOGRAM_BOOLEAN("Cookie.FromStorageWithValidLength", + valid_cookie_name_value_pair); } else { return nullptr; } @@ -763,10 +761,10 @@ std::unique_ptr CanonicalCookie::CreateUnsafeCookieForTesting( const std::string& value, const std::string& domain, const std::string& path, - const base::Time& creation, - const base::Time& expiration, - const base::Time& last_access, - const base::Time& last_update, + base::Time creation, + base::Time expiration, + base::Time last_access, + base::Time last_update, bool secure, bool httponly, CookieSameSite same_site, @@ -785,7 +783,7 @@ std::unique_ptr CanonicalCookie::CreateUnsafeCookieForTesting( std::unique_ptr CanonicalCookie::CreateForTesting( const GURL& url, const std::string& cookie_line, - const base::Time& creation_time, + base::Time creation_time, std::optional server_time, std::optional cookie_partition_key, CookieSourceType source_type, diff --git a/naiveproxy/src/net/cookies/canonical_cookie.h b/naiveproxy/src/net/cookies/canonical_cookie.h index afb0b14e9a..4a4be3d274 100644 --- a/naiveproxy/src/net/cookies/canonical_cookie.h +++ b/naiveproxy/src/net/cookies/canonical_cookie.h @@ -157,7 +157,7 @@ class NET_EXPORT CanonicalCookie : public CookieBase { static std::unique_ptr Create( const GURL& url, std::string_view cookie_line, - const base::Time& creation_time, + base::Time creation_time, std::optional server_time, std::optional cookie_partition_key, CookieSourceType source_type, @@ -223,10 +223,10 @@ class NET_EXPORT CanonicalCookie : public CookieBase { const std::string& value, const std::string& domain, const std::string& path, - const base::Time& creation, - const base::Time& expiration, - const base::Time& last_access, - const base::Time& last_update, + base::Time creation, + base::Time expiration, + base::Time last_access, + base::Time last_update, bool secure, bool httponly, CookieSameSite same_site, @@ -240,7 +240,7 @@ class NET_EXPORT CanonicalCookie : public CookieBase { static std::unique_ptr CreateForTesting( const GURL& url, const std::string& cookie_line, - const base::Time& creation_time, + base::Time creation_time, std::optional server_time = std::nullopt, std::optional cookie_partition_key = std::nullopt, CookieSourceType source_type = CookieSourceType::kUnknown, @@ -260,14 +260,14 @@ class NET_EXPORT CanonicalCookie : public CookieBase { // See CookieBase for other accessors. std::string Value() const; - const base::Time& ExpiryDate() const { return expiry_date_; } - const base::Time& LastAccessDate() const { return last_access_date_; } - const base::Time& LastUpdateDate() const { return last_update_date_; } + base::Time ExpiryDate() const { return expiry_date_; } + base::Time LastAccessDate() const { return last_access_date_; } + base::Time LastUpdateDate() const { return last_update_date_; } bool IsPersistent() const { return !expiry_date_.is_null(); } CookiePriority Priority() const { return priority_; } CookieSourceType SourceType() const { return source_type_; } - bool IsExpired(const base::Time& current) const { + bool IsExpired(base::Time current) const { return !expiry_date_.is_null() && current >= expiry_date_; } @@ -344,21 +344,19 @@ class NET_EXPORT CanonicalCookie : public CookieBase { // change subscribers such as the CookieStore API or service workers. bool IsWebEquivalentTo(const CanonicalCookie& other) const; - void SetLastAccessDate(const base::Time& date) { - last_access_date_ = date; - } + void SetLastAccessDate(base::Time date) { last_access_date_ = date; } std::string DebugString() const; // Returns a "null" time if expiration was unspecified or invalid. static base::Time ParseExpiration(const ParsedCookie& pc, - const base::Time& current, - const base::Time& server_time); + base::Time current, + base::Time server_time); // Per rfc6265bis the maximum expiry date is no further than 400 days in the // future. - static base::Time ValidateAndAdjustExpiryDate(const base::Time& expiry_date, - const base::Time& creation_date, + static base::Time ValidateAndAdjustExpiryDate(base::Time expiry_date, + base::Time creation_date, net::CookieSourceScheme scheme); // Return whether this object is a valid CanonicalCookie(). If the object is diff --git a/naiveproxy/src/net/cookies/cookie_base.h b/naiveproxy/src/net/cookies/cookie_base.h index 061dc4cc98..78f2c8a534 100644 --- a/naiveproxy/src/net/cookies/cookie_base.h +++ b/naiveproxy/src/net/cookies/cookie_base.h @@ -87,7 +87,7 @@ class NET_EXPORT CookieBase { // DomainWithoutDot(). const std::string& Domain() const { return domain_; } const std::string& Path() const { return path_; } - const base::Time& CreationDate() const { return creation_date_; } + base::Time CreationDate() const { return creation_date_; } bool SecureAttribute() const { return secure_; } bool IsHttpOnly() const { return httponly_; } CookieSameSite SameSite() const { return same_site_; } @@ -168,7 +168,7 @@ class NET_EXPORT CookieBase { // url::PORT_INVALID if value isn't in [0,65535] or url::PORT_UNSPECIFIED. void SetSourcePort(int port); - void SetCreationDate(const base::Time& date) { creation_date_ = date; } + void SetCreationDate(base::Time date) { creation_date_ = date; } protected: CookieBase(); diff --git a/naiveproxy/src/net/cookies/cookie_constants.cc b/naiveproxy/src/net/cookies/cookie_constants.cc index 2e206ebe70..9ebb6f46ec 100644 --- a/naiveproxy/src/net/cookies/cookie_constants.cc +++ b/naiveproxy/src/net/cookies/cookie_constants.cc @@ -4,6 +4,10 @@ #include "net/cookies/cookie_constants.h" +#include +#include +#include + #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/notreached.h" @@ -69,33 +73,21 @@ std::string CookieSameSiteToString(CookieSameSite same_site) { } } -CookieSameSite StringToCookieSameSite(const std::string& same_site, - CookieSameSiteString* samesite_string) { - // Put a value on the stack so that we can assign to |*samesite_string| - // instead of having to null-check it all the time. - CookieSameSiteString ignored = CookieSameSiteString::kUnspecified; - if (!samesite_string) - samesite_string = &ignored; - - *samesite_string = CookieSameSiteString::kUnrecognized; - CookieSameSite samesite = CookieSameSite::UNSPECIFIED; - +std::pair StringToCookieSameSite( + std::string_view same_site) { if (base::EqualsCaseInsensitiveASCII(same_site, kSameSiteNone)) { - samesite = CookieSameSite::NO_RESTRICTION; - *samesite_string = CookieSameSiteString::kNone; + return {CookieSameSite::NO_RESTRICTION, CookieSameSiteString::kNone}; } else if (base::EqualsCaseInsensitiveASCII(same_site, kSameSiteLax)) { - samesite = CookieSameSite::LAX_MODE; - *samesite_string = CookieSameSiteString::kLax; + return {CookieSameSite::LAX_MODE, CookieSameSiteString::kLax}; } else if (base::EqualsCaseInsensitiveASCII(same_site, kSameSiteStrict)) { - samesite = CookieSameSite::STRICT_MODE; - *samesite_string = CookieSameSiteString::kStrict; + return {CookieSameSite::STRICT_MODE, CookieSameSiteString::kStrict}; } else if (base::EqualsCaseInsensitiveASCII(same_site, kSameSiteExtended)) { // Extended isn't supported anymore -- we just parse it for UMA stats. - *samesite_string = CookieSameSiteString::kExtended; + return {CookieSameSite::UNSPECIFIED, CookieSameSiteString::kExtended}; } else if (same_site == "") { - *samesite_string = CookieSameSiteString::kEmptyString; + return {CookieSameSite::UNSPECIFIED, CookieSameSiteString::kEmptyString}; } - return samesite; + return {CookieSameSite::UNSPECIFIED, CookieSameSiteString::kUnrecognized}; } void RecordCookieSameSiteAttributeValueHistogram(CookieSameSiteString value) { diff --git a/naiveproxy/src/net/cookies/cookie_constants.h b/naiveproxy/src/net/cookies/cookie_constants.h index 110685614d..c365f9702c 100644 --- a/naiveproxy/src/net/cookies/cookie_constants.h +++ b/naiveproxy/src/net/cookies/cookie_constants.h @@ -6,6 +6,8 @@ #define NET_COOKIES_COOKIE_CONSTANTS_H_ #include +#include +#include #include "base/time/time.h" #include "net/base/net_export.h" @@ -329,12 +331,10 @@ NET_EXPORT std::string CookieSameSiteToString(CookieSameSite same_site); // Converts the Set-Cookie header SameSite token |same_site| to a // CookieSameSite. Defaults to CookieSameSite::UNSPECIFIED for empty or -// unrecognized strings. Returns an appropriate value of CookieSameSiteString in -// |samesite_string| to indicate what type of string was parsed as the SameSite -// attribute value, if a pointer is provided. -NET_EXPORT CookieSameSite -StringToCookieSameSite(const std::string& same_site, - CookieSameSiteString* samesite_string = nullptr); +// unrecognized strings. Returns an appropriate value of CookieSameSiteString to +// indicate what type of string was parsed as the SameSite attribute value. +NET_EXPORT std::pair +StringToCookieSameSite(std::string_view same_site); NET_EXPORT void RecordCookieSameSiteAttributeValueHistogram( CookieSameSiteString value); @@ -397,6 +397,8 @@ enum CookiePrefix { COOKIE_PREFIX_NONE = 0, COOKIE_PREFIX_SECURE, COOKIE_PREFIX_HOST, + COOKIE_PREFIX_HTTP, + COOKIE_PREFIX_HOSTHTTP, COOKIE_PREFIX_LAST }; diff --git a/naiveproxy/src/net/cookies/cookie_deletion_info.cc b/naiveproxy/src/net/cookies/cookie_deletion_info.cc index d3f7994775..1b0aaf3a87 100644 --- a/naiveproxy/src/net/cookies/cookie_deletion_info.cc +++ b/naiveproxy/src/net/cookies/cookie_deletion_info.cc @@ -50,7 +50,7 @@ CookieDeletionInfo::TimeRange::TimeRange(base::Time start, base::Time end) CookieDeletionInfo::TimeRange& CookieDeletionInfo::TimeRange::operator=( const TimeRange& rhs) = default; -bool CookieDeletionInfo::TimeRange::Contains(const base::Time& time) const { +bool CookieDeletionInfo::TimeRange::Contains(base::Time time) const { DCHECK(!time.is_null()); if (!start_.is_null() && start_ == end_) diff --git a/naiveproxy/src/net/cookies/cookie_deletion_info.h b/naiveproxy/src/net/cookies/cookie_deletion_info.h index 1d824985f6..ddc5ea64b7 100644 --- a/naiveproxy/src/net/cookies/cookie_deletion_info.h +++ b/naiveproxy/src/net/cookies/cookie_deletion_info.h @@ -52,7 +52,7 @@ struct NET_EXPORT CookieDeletionInfo { // Note 1: |time| cannot be null. // Note 2: If |start_| == |end_| then end_ is inclusive. // - bool Contains(const base::Time& time) const; + bool Contains(base::Time time) const; // Set the range start time. Set to null (i.e. Time()) to indicated an // unbounded lower range. diff --git a/naiveproxy/src/net/cookies/cookie_monster.cc b/naiveproxy/src/net/cookies/cookie_monster.cc index 698be82881..227b2bed2b 100644 --- a/naiveproxy/src/net/cookies/cookie_monster.cc +++ b/naiveproxy/src/net/cookies/cookie_monster.cc @@ -299,7 +299,7 @@ void SplitCookieVectorIntoSecureAndNonSecure( } bool LowerBoundAccessDateComparator(const CookieMonster::CookieMap::iterator it, - const Time& access_date) { + Time access_date) { return it->second->LastAccessDate() < access_date; } @@ -310,7 +310,7 @@ bool LowerBoundAccessDateComparator(const CookieMonster::CookieMap::iterator it, CookieMonster::CookieItVector::iterator LowerBoundAccessDate( const CookieMonster::CookieItVector::iterator its_begin, const CookieMonster::CookieItVector::iterator its_end, - const Time& access_date) { + Time access_date) { return std::lower_bound(its_begin, its_end, access_date, LowerBoundAccessDateComparator); } @@ -1958,7 +1958,7 @@ void CookieMonster::SetUnsafeCanonicalCookieForTest( } void CookieMonster::InternalUpdateCookieAccessTime(CanonicalCookie& cc, - const Time& current) { + Time current) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); // Based off the Mozilla code. When a cookie has been accessed recently, @@ -2098,8 +2098,7 @@ void CookieMonster::InternalDeletePartitionedCookie( // Domain expiry behavior is unchanged by key/expiry scheme (the // meaning of the key is different, but that's not visible to this routine). -size_t CookieMonster::GarbageCollect(const Time& current, - const std::string& key) { +size_t CookieMonster::GarbageCollect(Time current, const std::string& key) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); size_t num_deleted = 0; @@ -2281,7 +2280,7 @@ size_t CookieMonster::GarbageCollect(const Time& current, } size_t CookieMonster::GarbageCollectPartitionedCookies( - const base::Time& current, + base::Time current, const CookiePartitionKey& cookie_partition_key, const std::string& key) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); @@ -2532,7 +2531,7 @@ size_t CookieMonster::PurgeLeastRecentMatchesForOBC( return removed; } -size_t CookieMonster::GarbageCollectExpired(const Time& current, +size_t CookieMonster::GarbageCollectExpired(Time current, const CookieMapItPair& itpair, CookieItVector* cookie_its) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); @@ -2554,7 +2553,7 @@ size_t CookieMonster::GarbageCollectExpired(const Time& current, } size_t CookieMonster::GarbageCollectExpiredPartitionedCookies( - const Time& current, + Time current, const PartitionedCookieMap::iterator& cookie_partition_it, const CookieMapItPair& itpair, CookieItVector* cookie_its) { @@ -2577,8 +2576,7 @@ size_t CookieMonster::GarbageCollectExpiredPartitionedCookies( return num_deleted; } -void CookieMonster::GarbageCollectAllExpiredPartitionedCookies( - const Time& current) { +void CookieMonster::GarbageCollectAllExpiredPartitionedCookies(Time current) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); for (auto it = partitioned_cookies_.begin(); it != partitioned_cookies_.end();) { @@ -2596,7 +2594,7 @@ void CookieMonster::GarbageCollectAllExpiredPartitionedCookies( } size_t CookieMonster::GarbageCollectDeleteRange( - const Time& current, + Time current, DeletionCause cause, CookieItVector::iterator it_begin, CookieItVector::iterator it_end) { @@ -2609,8 +2607,8 @@ size_t CookieMonster::GarbageCollectDeleteRange( } size_t CookieMonster::GarbageCollectLeastRecentlyAccessed( - const base::Time& current, - const base::Time& safe_date, + base::Time current, + base::Time safe_date, size_t purge_goal, CookieItVector cookie_its, base::Time& earliest_time) { @@ -2816,7 +2814,7 @@ void CookieMonster::UpdateMostRecentCookie( // last_statistic_record_time_ is initialized to Now() rather than null // in the constructor so that we won't take statistics right after // startup, to avoid bias from browsers that are started but not used. -void CookieMonster::RecordPeriodicStats(const base::Time& current_time) { +void CookieMonster::RecordPeriodicStats(base::Time current_time) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); const base::TimeDelta kRecordStatisticsIntervalTime( diff --git a/naiveproxy/src/net/cookies/cookie_monster.h b/naiveproxy/src/net/cookies/cookie_monster.h index df271609ba..8abe173e60 100644 --- a/naiveproxy/src/net/cookies/cookie_monster.h +++ b/naiveproxy/src/net/cookies/cookie_monster.h @@ -623,7 +623,7 @@ class NET_EXPORT CookieMonster : public CookieStore { void SetAllCookies(CookieList list, SetCookiesCallback callback); void InternalUpdateCookieAccessTime(CanonicalCookie& cc, - const base::Time& current_time); + base::Time current_time); // |deletion_cause| argument is used for collecting statistics and choosing // the correct CookieChangeCause for OnCookieChange notifications. Guarantee: @@ -650,7 +650,7 @@ class NET_EXPORT CookieMonster : public CookieStore { // constants for details. Also removes expired cookies. // // Returns the number of cookies deleted (useful for debugging). - size_t GarbageCollect(const base::Time& current, const std::string& key); + size_t GarbageCollect(base::Time current, const std::string& key); // Run garbage collection for PartitionedCookieMap keys |cookie_partition_key| // and |key|. @@ -659,7 +659,7 @@ class NET_EXPORT CookieMonster : public CookieStore { // cookies in order to prevent leaking entropy about user behavior across // cookie partitions. size_t GarbageCollectPartitionedCookies( - const base::Time& current, + base::Time current, const CookiePartitionKey& cookie_partition_key, const std::string& key); @@ -690,7 +690,7 @@ class NET_EXPORT CookieMonster : public CookieStore { // non-expired cookies from |itpair| are appended to |cookie_its|. // // Returns the number of cookies deleted. - size_t GarbageCollectExpired(const base::Time& current, + size_t GarbageCollectExpired(base::Time current, const CookieMapItPair& itpair, CookieItVector* cookie_its); @@ -701,18 +701,18 @@ class NET_EXPORT CookieMonster : public CookieStore { // // Returns the number of cookies deleted. size_t GarbageCollectExpiredPartitionedCookies( - const base::Time& current, + base::Time current, const PartitionedCookieMap::iterator& cookie_partition_it, const CookieMapItPair& itpair, CookieItVector* cookie_its); // Helper function to garbage collect all expired cookies in // PartitionedCookieMap. - void GarbageCollectAllExpiredPartitionedCookies(const base::Time& current); + void GarbageCollectAllExpiredPartitionedCookies(base::Time current); // Helper for GarbageCollect(). Deletes all cookies in the range specified by // [|it_begin|, |it_end|). Returns the number of cookies deleted. - size_t GarbageCollectDeleteRange(const base::Time& current, + size_t GarbageCollectDeleteRange(base::Time current, DeletionCause cause, CookieItVector::iterator cookie_its_begin, CookieItVector::iterator cookie_its_end); @@ -723,8 +723,8 @@ class NET_EXPORT CookieMonster : public CookieStore { // // Sets |earliest_time| to be the earliest last access time of a cookie that // was not deleted, or base::Time() if no such cookie exists. - size_t GarbageCollectLeastRecentlyAccessed(const base::Time& current, - const base::Time& safe_date, + size_t GarbageCollectLeastRecentlyAccessed(base::Time current, + base::Time safe_date, size_t purge_goal, CookieItVector cookie_its, base::Time& earliest_time); @@ -768,7 +768,7 @@ class NET_EXPORT CookieMonster : public CookieStore { // This function should be called repeatedly, and will record // statistics if a sufficient time period has passed. - void RecordPeriodicStats(const base::Time& current_time); + void RecordPeriodicStats(base::Time current_time); // Records the aforementioned stats if we have already finished loading all // cookies. Returns whether stats were recorded. diff --git a/naiveproxy/src/net/cookies/cookie_monster_store_test.h b/naiveproxy/src/net/cookies/cookie_monster_store_test.h index f8d80ccf47..8a608013e0 100644 --- a/naiveproxy/src/net/cookies/cookie_monster_store_test.h +++ b/naiveproxy/src/net/cookies/cookie_monster_store_test.h @@ -133,12 +133,12 @@ class MockPersistentCookieStore : public CookieMonster::PersistentCookieStore { std::unique_ptr BuildCanonicalCookie( const GURL& url, const std::string& cookie_line, - const base::Time& creation_time); + base::Time creation_time); // Helper to build a list of CanonicalCookie*s. void AddCookieToList(const GURL& url, const std::string& cookie_line, - const base::Time& creation_time, + base::Time creation_time, std::vector>* out_list); // Just act like a backing database. Keep cookie information from diff --git a/naiveproxy/src/net/cookies/cookie_store_unittest.h b/naiveproxy/src/net/cookies/cookie_store_unittest.h index f661468d6d..d68677670d 100644 --- a/naiveproxy/src/net/cookies/cookie_store_unittest.h +++ b/naiveproxy/src/net/cookies/cookie_store_unittest.h @@ -261,7 +261,7 @@ class CookieStoreTest : public testing::Test { bool SetCookieWithSystemTime(CookieStore* cs, const GURL& url, const std::string& cookie_line, - const base::Time& system_time) { + base::Time system_time) { CookieOptions options; if (!CookieStoreTestTraits::supports_http_only) options.set_include_httponly(); @@ -274,7 +274,7 @@ class CookieStoreTest : public testing::Test { bool SetCookieWithServerTime(CookieStore* cs, const GURL& url, const std::string& cookie_line, - const base::Time& server_time) { + base::Time server_time) { CookieOptions options; if (!CookieStoreTestTraits::supports_http_only) options.set_include_httponly(); diff --git a/naiveproxy/src/net/cookies/cookie_util.cc b/naiveproxy/src/net/cookies/cookie_util.cc index f4ecb6f889..a9e4e448f8 100644 --- a/naiveproxy/src/net/cookies/cookie_util.cc +++ b/naiveproxy/src/net/cookies/cookie_util.cc @@ -68,14 +68,14 @@ base::Time MinNonNullTime() { // // * Time(1) if it's below the range FromUTCExploded() supports. // * Time::Max() if it's above the range FromUTCExploded() supports. -bool SaturatedTimeFromUTCExploded(const base::Time::Exploded& exploded, - base::Time* out) { +// * std::nullopt if the input does not have valid values. +std::optional SaturatedTimeFromUTCExploded( + const base::Time::Exploded& exploded) { // Try to calculate the base::Time in the normal fashion. - if (base::Time::FromUTCExploded(exploded, out)) { + base::Time out; + if (base::Time::FromUTCExploded(exploded, &out)) { // Don't return Time(0) on success. - if (out->is_null()) - *out = MinNonNullTime(); - return true; + return out.is_null() ? MinNonNullTime() : out; } // base::Time::FromUTCExploded() has platform-specific limits: @@ -88,19 +88,23 @@ bool SaturatedTimeFromUTCExploded(const base::Time::Exploded& exploded, // // Note that the following implementation is NOT perfect. It will accept // some invalid calendar dates in the out-of-range case. - if (!exploded.HasValidValues()) - return false; + if (!exploded.HasValidValues()) { + return std::nullopt; + } if (exploded.year > base::Time::kExplodedMaxYear) { - *out = base::Time::Max(); - return true; + return base::Time::Max(); } if (exploded.year < base::Time::kExplodedMinYear) { - *out = MinNonNullTime(); - return true; + return MinNonNullTime(); } - return false; + return std::nullopt; +} + +bool HasValidSecurePrefixAttributes(const GURL& url, bool secure) { + return secure && + ProvisionalAccessScheme(url) != CookieAccessScheme::kNonCryptographic; } // Tests that a cookie has the attributes for a valid __Host- prefix without @@ -109,14 +113,20 @@ bool HasValidHostPrefixAttributes(const GURL& url, bool secure, std::string_view domain, std::string_view path) { - if (!secure || - ProvisionalAccessScheme(url) == CookieAccessScheme::kNonCryptographic || - path != "/") { + if (!HasValidSecurePrefixAttributes(url, secure) || path != "/") { return false; } return domain.empty() || (url.HostIsIPAddress() && url.host() == domain); } +// Tests that a cookie has the attributes for a valid __Http- prefix without +// testing that the prefix is in the cookie name. +bool HasValidHttpPrefixAttributes(const GURL& url, + bool secure, + bool http_only) { + return HasValidSecurePrefixAttributes(url, secure) && http_only; +} + struct ComputeSameSiteContextResult { ContextType context_type = ContextType::CROSS_SITE; ContextMetadata metadata; @@ -605,15 +615,11 @@ base::Time ParseCookieExpirationTime(std::string_view time_string) { // Note that clipping the date if it is outside of a platform-specific range // is permitted by: https://tools.ietf.org/html/rfc6265#section-5.2.1 - base::Time result; - if (SaturatedTimeFromUTCExploded(exploded, &result)) - return result; - - // One of our values was out of expected range. For well-formed input, - // the following check would be reasonable: - // NOTREACHED() << "Cookie exploded expiration failed: " << time_string; - - return base::Time(); + // + // For well-formed input, the following check would be reasonable: + // CHECK(SaturatedTimeFromUTCExploded(exploded)) + // << "Cookie exploded expiration failed: " << time_string; + return SaturatedTimeFromUTCExploded(exploded).value_or(base::Time()); } std::string CanonPathWithString(const GURL& url, std::string_view path_string) { @@ -754,13 +760,25 @@ bool IsOnPath(const std::string& cookie_path, const std::string& url_path) { } CookiePrefix GetCookiePrefix(const std::string& name) { - const char kSecurePrefix[] = "__Secure-"; - const char kHostPrefix[] = "__Host-"; + constexpr std::string_view kSecurePrefix("__Secure-"); + constexpr std::string_view kHostPrefix("__Host-"); + constexpr std::string_view kHttpPrefix("__Http-"); + constexpr std::string_view kHostHttpPrefix("__Host-Http-"); if (base::StartsWith(name, kSecurePrefix, base::CompareCase::INSENSITIVE_ASCII)) { return COOKIE_PREFIX_SECURE; } + if (base::StartsWith(name, kHttpPrefix, + base::CompareCase::INSENSITIVE_ASCII) && + base::FeatureList::IsEnabled(features::kPrefixCookieHttp)) { + return COOKIE_PREFIX_HTTP; + } + if (base::StartsWith(name, kHostHttpPrefix, + base::CompareCase::INSENSITIVE_ASCII) && + base::FeatureList::IsEnabled(features::kPrefixCookieHostHttp)) { + return COOKIE_PREFIX_HOSTHTTP; + } if (base::StartsWith(name, kHostPrefix, base::CompareCase::INSENSITIVE_ASCII)) { return COOKIE_PREFIX_HOST; @@ -771,23 +789,30 @@ CookiePrefix GetCookiePrefix(const std::string& name) { bool IsCookiePrefixValid(CookiePrefix prefix, const GURL& url, const ParsedCookie& parsed_cookie) { - return IsCookiePrefixValid(prefix, url, parsed_cookie.IsSecure(), - parsed_cookie.Domain().value_or(""), - parsed_cookie.Path().value_or("")); + return IsCookiePrefixValid( + prefix, url, parsed_cookie.IsSecure(), parsed_cookie.IsHttpOnly(), + parsed_cookie.Domain().value_or(""), parsed_cookie.Path().value_or("")); } bool IsCookiePrefixValid(CookiePrefix prefix, const GURL& url, bool secure, + bool http_only, std::string_view domain, std::string_view path) { if (prefix == COOKIE_PREFIX_SECURE) { - return secure && ProvisionalAccessScheme(url) != - CookieAccessScheme::kNonCryptographic; + return HasValidSecurePrefixAttributes(url, secure); } if (prefix == COOKIE_PREFIX_HOST) { return HasValidHostPrefixAttributes(url, secure, domain, path); } + if (prefix == COOKIE_PREFIX_HTTP) { + return HasValidHttpPrefixAttributes(url, secure, http_only); + } + if (prefix == COOKIE_PREFIX_HOSTHTTP) { + return HasValidHttpPrefixAttributes(url, secure, http_only) && + HasValidHostPrefixAttributes(url, secure, domain, path); + } return true; } diff --git a/naiveproxy/src/net/cookies/cookie_util.h b/naiveproxy/src/net/cookies/cookie_util.h index 4cd9f91acc..cbb7365fb8 100644 --- a/naiveproxy/src/net/cookies/cookie_util.h +++ b/naiveproxy/src/net/cookies/cookie_util.h @@ -276,6 +276,7 @@ bool IsCookiePrefixValid(CookiePrefix prefix, NET_EXPORT_PRIVATE bool IsCookiePrefixValid(CookiePrefix prefix, const GURL& url, bool secure, + bool http_only, std::string_view domain, std::string_view path); diff --git a/naiveproxy/src/net/cookies/parsed_cookie.cc b/naiveproxy/src/net/cookies/parsed_cookie.cc index c17148bf11..498b383cf2 100644 --- a/naiveproxy/src/net/cookies/parsed_cookie.cc +++ b/naiveproxy/src/net/cookies/parsed_cookie.cc @@ -44,7 +44,8 @@ #include "net/cookies/parsed_cookie.h" -#include "base/logging.h" +#include + #include "base/metrics/histogram_macros.h" #include "base/numerics/checked_math.h" #include "base/strings/string_util.h" @@ -157,16 +158,11 @@ bool ParsedCookie::IsValid() const { return !pairs_.empty(); } -CookieSameSite ParsedCookie::SameSite( - CookieSameSiteString* samesite_string) const { - CookieSameSite samesite = CookieSameSite::UNSPECIFIED; +std::pair ParsedCookie::SameSite() const { if (same_site_index_ != 0) { - samesite = StringToCookieSameSite(pairs_[same_site_index_].second, - samesite_string); - } else if (samesite_string) { - *samesite_string = CookieSameSiteString::kUnspecified; + return StringToCookieSameSite(pairs_[same_site_index_].second); } - return samesite; + return {CookieSameSite::UNSPECIFIED, CookieSameSiteString::kUnspecified}; } CookiePriority ParsedCookie::Priority() const { @@ -502,6 +498,18 @@ bool ParsedCookie::IsValidCookieNameValuePair( return true; } +bool ParsedCookie::ForEachAttribute( + base::FunctionRef functor) const { + // The first element in `pairs_` is the name and value, so skip that one. + for (const auto& [attribute, value] : base::span(pairs_).subspan(1u)) { + if (!functor(attribute, value)) { + return false; + } + } + + return true; +} + // Parse all token/value pairs and populate pairs_. void ParsedCookie::ParseTokenValuePairs(std::string_view cookie_line, CookieInclusionStatus& status_out) { @@ -531,7 +539,7 @@ void ParsedCookie::ParseTokenValuePairs(std::string_view cookie_line, } for (int pair_num = 0; it != end; ++pair_num) { - TokenValuePair pair; + std::pair pair; std::string_view::iterator token_start, token_end; if (!ParseToken(&it, end, &token_start, &token_end)) { diff --git a/naiveproxy/src/net/cookies/parsed_cookie.h b/naiveproxy/src/net/cookies/parsed_cookie.h index af7fbe7778..d2e88d8c6d 100644 --- a/naiveproxy/src/net/cookies/parsed_cookie.h +++ b/naiveproxy/src/net/cookies/parsed_cookie.h @@ -12,6 +12,7 @@ #include #include +#include "base/functional/function_ref.h" #include "net/base/net_export.h" #include "net/cookies/cookie_constants.h" @@ -21,9 +22,6 @@ class CookieInclusionStatus; class NET_EXPORT ParsedCookie { public: - typedef std::pair TokenValuePair; - typedef std::vector PairList; - // The maximum length allowed for a cookie string's name/value pair. static const size_t kMaxCookieNamePlusValueSize = 4096; @@ -83,9 +81,8 @@ class NET_EXPORT ParsedCookie { bool IsSecure() const { return secure_index_ != 0; } bool IsHttpOnly() const { return httponly_index_ != 0; } // Also spits out an enum value representing the string given as the SameSite - // attribute value, if |samesite_string| is non-null. - CookieSameSite SameSite( - CookieSameSiteString* samesite_string = nullptr) const; + // attribute value. + std::pair SameSite() const; CookiePriority Priority() const; bool IsPartitioned() const { return partitioned_index_ != 0; } bool HasInternalHtab() const { return internal_htab_; } @@ -171,6 +168,14 @@ class NET_EXPORT ParsedCookie { const std::string& value, CookieInclusionStatus* status_out = nullptr); + // Synchronously calls `functor` with each attribute and value in the + // parsed cookie. `functor` may return `true` to continue the + // iteration or `false` to terminate. This function will return `true` + // if iteration was completed, or `false` if it was terminated. + bool ForEachAttribute( + base::FunctionRef functor) + const; + private: void ParseTokenValuePairs(std::string_view cookie_line, CookieInclusionStatus& status_out); @@ -197,7 +202,7 @@ class NET_EXPORT ParsedCookie { // |index| refers to a position in |pairs_|. void ClearAttributePair(size_t index); - PairList pairs_; + std::vector> pairs_; // These will default to 0, but that should never be valid since the // 0th index is the user supplied cookie name/value, not an attribute. size_t path_index_ = 0; diff --git a/naiveproxy/src/net/device_bound_sessions/cookie_craving.cc b/naiveproxy/src/net/device_bound_sessions/cookie_craving.cc index 8fd30df09a..8e924eb756 100644 --- a/naiveproxy/src/net/device_bound_sessions/cookie_craving.cc +++ b/naiveproxy/src/net/device_bound_sessions/cookie_craving.cc @@ -6,6 +6,8 @@ #include +#include "base/containers/contains.h" +#include "base/containers/fixed_flat_set.h" #include "base/strings/strcat.h" #include "net/base/url_util.h" #include "net/cookies/canonical_cookie.h" @@ -83,8 +85,7 @@ std::optional CookieCraving::Create( const GURL& url, const std::string& name, const std::string& attributes, - base::Time creation_time, - std::optional cookie_partition_key) { + base::Time creation_time) { if (!url.is_valid() || creation_time.is_null()) { return std::nullopt; } @@ -107,6 +108,16 @@ std::optional CookieCraving::Create( return std::nullopt; } + static constexpr auto kPermittedAttributes = + base::MakeFixedFlatSet( + {"domain", "path", "secure", "httponly", "samesite"}); + if (!parsed_cookie.ForEachAttribute( + [](std::string_view attribute, std::string_view value) { + return base::Contains(kPermittedAttributes, attribute); + })) { + return std::nullopt; + } + // `domain` is the domain key for storing the CookieCraving, determined // from the domain attribute value (if any) and the URL. A domain cookie is // marked by a preceding dot, as per CookieBase::Domain(), whereas a host @@ -133,17 +144,6 @@ std::optional CookieCraving::Create( return std::nullopt; } - // TODO(chlily): Determine whether nonced partition keys should be supported - // for CookieCravings. - bool partition_has_nonce = CookiePartitionKey::HasNonce(cookie_partition_key); - if (!cookie_util::IsCookiePartitionedValid(url, parsed_cookie, - partition_has_nonce)) { - return std::nullopt; - } - if (!parsed_cookie.IsPartitioned() && !partition_has_nonce) { - cookie_partition_key = std::nullopt; - } - // Note: This is a deviation from CanonicalCookie::Create(), which allows // cookies with a Secure attribute to be created as if they came from a // cryptographic URL, even if the URL is not cryptographic, on the basis that @@ -160,8 +160,7 @@ std::optional CookieCraving::Create( creation_time, parsed_cookie.IsSecure(), parsed_cookie.IsHttpOnly(), - parsed_cookie.SameSite(), - std::move(cookie_partition_key), + parsed_cookie.SameSite().first, source_scheme, source_port}; @@ -206,7 +205,19 @@ bool CookieCraving::IsValid() const { return false; } break; - default: + case COOKIE_PREFIX_HTTP: + if (!SecureAttribute() || !IsHttpOnly()) { + return false; + } + break; + case COOKIE_PREFIX_HOSTHTTP: + if (!SecureAttribute() || Path() != "/" || !IsHostCookie() || + !IsHttpOnly()) { + return false; + } + break; + case COOKIE_PREFIX_NONE: + case COOKIE_PREFIX_LAST: break; } @@ -265,14 +276,11 @@ CookieCraving CookieCraving::CreateUnsafeForTesting( bool secure, bool httponly, CookieSameSite same_site, - std::optional partition_key, CookieSourceScheme source_scheme, int source_port) { - return CookieCraving{std::move(name), std::move(domain), - std::move(path), creation, - secure, httponly, - same_site, std::move(partition_key), - source_scheme, source_port}; + return CookieCraving{ + std::move(name), std::move(domain), std::move(path), creation, secure, + httponly, same_site, source_scheme, source_port}; } CookieCraving::CookieCraving() = default; @@ -284,7 +292,6 @@ CookieCraving::CookieCraving(std::string name, bool secure, bool httponly, CookieSameSite same_site, - std::optional partition_key, CookieSourceScheme source_scheme, int source_port) : CookieBase(std::move(name), @@ -294,7 +301,7 @@ CookieCraving::CookieCraving(std::string name, secure, httponly, same_site, - std::move(partition_key), + /*partition_key=*/std::nullopt, source_scheme, source_port) {} @@ -338,21 +345,6 @@ proto::CookieCraving CookieCraving::ToProto() const { CreationDate().ToDeltaSinceWindowsEpoch().InMicroseconds()); proto.set_same_site(ProtoEnumFromCookieSameSite(SameSite())); proto.set_source_scheme(ProtoEnumFromCookieSourceScheme(SourceScheme())); - - if (IsPartitioned()) { - // TODO(crbug.com/356581003) The serialization below does not handle - // nonced cookies. Need to figure out whether this is required. - base::expected - serialized_partition_key = - net::CookiePartitionKey::Serialize(PartitionKey()); - CHECK(serialized_partition_key.has_value()); - proto.mutable_serialized_partition_key()->set_top_level_site( - serialized_partition_key->TopLevelSite()); - proto.mutable_serialized_partition_key()->set_has_cross_site_ancestor( - serialized_partition_key->has_cross_site_ancestor()); - } - return proto; } @@ -366,25 +358,6 @@ std::optional CookieCraving::CreateFromProto( return std::nullopt; } - // Retrieve the serialized cookie partition key if present. - std::optional partition_key; - if (proto.has_serialized_partition_key()) { - const proto::SerializedCookiePartitionKey& serialized_key = - proto.serialized_partition_key(); - if (!serialized_key.has_top_level_site() || - !serialized_key.has_has_cross_site_ancestor()) { - return std::nullopt; - } - base::expected, std::string> - restored_key = CookiePartitionKey::FromStorage( - serialized_key.top_level_site(), - serialized_key.has_cross_site_ancestor()); - if (!restored_key.has_value() || *restored_key == std::nullopt) { - return std::nullopt; - } - partition_key = std::move(*restored_key); - } - CookieCraving cookie_craving{ proto.name(), proto.domain(), @@ -394,7 +367,6 @@ std::optional CookieCraving::CreateFromProto( proto.secure(), proto.httponly(), CookieSameSiteFromProtoEnum(proto.same_site()), - std::move(partition_key), CookieSourceSchemeFromProtoEnum(proto.source_scheme()), proto.source_port()}; @@ -421,11 +393,27 @@ bool CookieCraving::ShouldIncludeForRequest( // conditions too. base::Time now = base::Time::Now(); CookieInclusionStatus status; + std::string domain = Domain(); + // This fix is needed because non-IP address __Host- prefix cookies are + // considered invalid if they pass through a domain, but Domain() is defined + // even for __Host- prefix cookies. This fix is very limited in scope for now + // (only __Host- prefix cookies). + // TODO(crbug.com/435221694): re-implement the way we call into + // `AnnotateAndMoveUserBlockedCookies` so that it is not possible for a + // validation to fail in this method. Some ideas: + // 1) Can we create a canonical cookie in the `CookieCraving` constructor + // with the original inputs? + // 2) Can we refactor `AnnotateAndMoveUserBlockedCookies` to input a + // `CookieBase` instead? + if (!request->url().HostIsIPAddress() && + cookie_util::GetCookiePrefix(Name()) == COOKIE_PREFIX_HOST) { + domain = ""; + } std::unique_ptr canonical_cookie = CanonicalCookie::CreateSanitizedCookie( - request->url(), Name(), /*value=*/"", Domain(), Path(), - CreationDate(), now + base::Days(1), now, IsSecure(), IsHttpOnly(), - SameSite(), COOKIE_PRIORITY_DEFAULT, PartitionKey(), &status); + request->url(), Name(), /*value=*/"", domain, Path(), CreationDate(), + now + base::Days(1), now, IsSecure(), IsHttpOnly(), SameSite(), + COOKIE_PRIORITY_DEFAULT, PartitionKey(), &status); CookieAccessResultList included_cravings; included_cravings.emplace_back(std::move(*canonical_cookie)); CookieAccessResultList excluded_cravings; diff --git a/naiveproxy/src/net/device_bound_sessions/cookie_craving.h b/naiveproxy/src/net/device_bound_sessions/cookie_craving.h index 2b30d18a97..2b82a08ed2 100644 --- a/naiveproxy/src/net/device_bound_sessions/cookie_craving.h +++ b/naiveproxy/src/net/device_bound_sessions/cookie_craving.h @@ -12,7 +12,6 @@ #include "net/base/net_export.h" #include "net/cookies/cookie_base.h" #include "net/cookies/cookie_constants.h" -#include "net/cookies/cookie_partition_key.h" namespace net { class URLRequest; @@ -68,12 +67,8 @@ class NET_EXPORT CookieCraving : public CookieBase { // it will satisfy IsValid(). If there is leading or trailing whitespace in // `name`, it will get trimmed. // - // `cookie_partition_key` only needs to be present if the attributes contain - // the Partitioned attribute. std::nullopt indicates an unpartitioned - // CookieCraving will be created. If there is a partition key but the - // attributes do not specify Partitioned, the resulting CookieCraving will be - // unpartitioned. If the partition_key is nullopt, the CookieCraving will - // always be unpartitioned even if the attributes specify Partitioned. + // Partitioned cookies are not supported. Attempts to create a + // partitioned CookieCraving will fail. // // SameSite and HttpOnly related parameters are not checked here, // so creation of CookieCravings with e.g. SameSite=Strict from a cross-site @@ -97,12 +92,10 @@ class NET_EXPORT CookieCraving : public CookieBase { // secure source_scheme, if that cookie was Secure, on the basis that that // URL might be trustworthy when checked later. CookieCraving does not // allow this. - static std::optional Create( - const GURL& url, - const std::string& name, - const std::string& attributes, - base::Time creation_time, - std::optional cookie_partition_key); + static std::optional Create(const GURL& url, + const std::string& name, + const std::string& attributes, + base::Time creation_time); CookieCraving(const CookieCraving& other); CookieCraving(CookieCraving&& other); @@ -135,7 +128,6 @@ class NET_EXPORT CookieCraving : public CookieBase { bool secure, bool httponly, CookieSameSite same_site, - std::optional partition_key, CookieSourceScheme source_scheme, int source_port); @@ -168,7 +160,6 @@ class NET_EXPORT CookieCraving : public CookieBase { bool secure, bool httponly, CookieSameSite same_site, - std::optional partition_key, CookieSourceScheme source_scheme, int source_port); diff --git a/naiveproxy/src/net/device_bound_sessions/deletion_reason.h b/naiveproxy/src/net/device_bound_sessions/deletion_reason.h new file mode 100644 index 0000000000..5528ae4dae --- /dev/null +++ b/naiveproxy/src/net/device_bound_sessions/deletion_reason.h @@ -0,0 +1,32 @@ +// Copyright 2025 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_DELETION_REASON_H_ +#define NET_DEVICE_BOUND_SESSIONS_DELETION_REASON_H_ + +namespace net::device_bound_sessions { + +// Reasons for session termination. +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +// LINT.IfChange(DeletionReason) +enum DeletionReason { + kExpired = 0, // Session was not used for too long. + kFailedToRestoreKey = 1, // Could not restore key from disk. + kFailedToUnwrapKey = 2, // Could not unwrap a key loaded from disk. + kStoragePartitionCleared = 3, // Site data is being cleared due to + // removal in the StoragePartitionImpl. + kClearBrowsingData = 4, // Site data is being cleared by the + // user. For example, through + // chrome://settings/clearBrowsingData. + kServerRequested = 5, // Server explicitly requested termination. + kInvalidSessionParams = 6, // Refresh provided invalid params. + kRefreshFatalError = 7, // Fatal error during refresh. + kMaxValue = kRefreshFatalError, +}; +// LINT.ThenChange(//tools/metrics/histograms/metadata/net/enums.xml:DeviceBoundSessionDeletionReason) + +} // namespace net::device_bound_sessions + +#endif // NET_DEVICE_BOUND_SESSIONS_DELETION_REASON_H_ diff --git a/naiveproxy/src/net/device_bound_sessions/host_patterns.cc b/naiveproxy/src/net/device_bound_sessions/host_patterns.cc new file mode 100644 index 0000000000..18a7999c79 --- /dev/null +++ b/naiveproxy/src/net/device_bound_sessions/host_patterns.cc @@ -0,0 +1,38 @@ +// Copyright 2025 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/host_patterns.h" + +#include "url/url_util.h" + +namespace net::device_bound_sessions { + +bool IsValidHostPattern(std::string_view host_pattern) { + if (host_pattern.empty()) { + return false; + } + + if (host_pattern == "*") { + return true; + } + + size_t host_part_offset = host_pattern.starts_with("*.") ? 2u : 0u; + // Don't allow '*' except in the initial position + return host_pattern.substr(host_part_offset).find('*') == std::string::npos; +} + +bool MatchesHostPattern(std::string_view host_pattern, std::string_view host) { + if (host_pattern == "*") { + return true; + } + + if (host_pattern.starts_with("*.") && + host.ends_with(host_pattern.substr(1)) && !url::HostIsIPAddress(host)) { + return true; + } + + return host == host_pattern; +} + +} // namespace net::device_bound_sessions diff --git a/naiveproxy/src/net/device_bound_sessions/host_patterns.h b/naiveproxy/src/net/device_bound_sessions/host_patterns.h new file mode 100644 index 0000000000..e3aeaaabd9 --- /dev/null +++ b/naiveproxy/src/net/device_bound_sessions/host_patterns.h @@ -0,0 +1,26 @@ +// Copyright 2025 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_HOST_PATTERNS_H_ +#define NET_DEVICE_BOUND_SESSIONS_HOST_PATTERNS_H_ + +#include + +#include "net/base/net_export.h" + +namespace net::device_bound_sessions { + +// Returns if `host_pattern` is valid (i.e. can match any hosts). The +// `host_pattern` must either be a full domain (host piece), exactly '*', or a +// pattern containing a wildcard ('*' character) in the most-specific (leftmost) +// label position followed by a dot and the rest of the domain. +bool NET_EXPORT IsValidHostPattern(std::string_view host_pattern); + +// Returns whether `host_patern` matches `host`. +bool NET_EXPORT MatchesHostPattern(std::string_view host_pattern, + std::string_view host); + +} // namespace net::device_bound_sessions + +#endif // NET_DEVICE_BOUND_SESSIONS_HOST_PATTERNS_H_ diff --git a/naiveproxy/src/net/device_bound_sessions/jwk_utils.cc b/naiveproxy/src/net/device_bound_sessions/jwk_utils.cc index ff0539ffb8..3a9e5669fd 100644 --- a/naiveproxy/src/net/device_bound_sessions/jwk_utils.cc +++ b/naiveproxy/src/net/device_bound_sessions/jwk_utils.cc @@ -5,8 +5,8 @@ #include "net/device_bound_sessions/jwk_utils.h" #include "base/base64url.h" +#include "crypto/evp.h" #include "third_party/boringssl/src/include/openssl/bn.h" -#include "third_party/boringssl/src/include/openssl/bytestring.h" #include "third_party/boringssl/src/include/openssl/ec.h" #include "third_party/boringssl/src/include/openssl/evp.h" #include "third_party/boringssl/src/include/openssl/rsa.h" @@ -36,19 +36,9 @@ std::string Base64UrlEncode(base::span input) { return output; } -bssl::UniquePtr ParsePublicKey(base::span pkey_spki) { - CBS cbs; - CBS_init(&cbs, pkey_spki.data(), pkey_spki.size()); - bssl::UniquePtr pkey(EVP_parse_public_key(&cbs)); - if (CBS_len(&cbs) != 0) { - return nullptr; - } - return pkey; -} - base::Value::Dict ConvertES256PkeySpkiToJwk( base::span pkey_spki) { - bssl::UniquePtr pkey = ParsePublicKey(pkey_spki); + bssl::UniquePtr pkey = crypto::evp::PublicKeyFromBytes(pkey_spki); if (!pkey || EVP_PKEY_id(pkey.get()) != EVP_PKEY_EC) { return base::Value::Dict(); } @@ -91,7 +81,7 @@ base::Value::Dict ConvertES256PkeySpkiToJwk( base::Value::Dict ConvertRS256PkeySpkiToJwk( base::span pkey_spki) { - bssl::UniquePtr pkey = ParsePublicKey(pkey_spki); + bssl::UniquePtr pkey = crypto::evp::PublicKeyFromBytes(pkey_spki); if (!pkey || EVP_PKEY_id(pkey.get()) != EVP_PKEY_RSA) { return base::Value::Dict(); } diff --git a/naiveproxy/src/net/device_bound_sessions/mock_session_service.h b/naiveproxy/src/net/device_bound_sessions/mock_session_service.h index f43dd824fe..06ed88c17a 100644 --- a/naiveproxy/src/net/device_bound_sessions/mock_session_service.h +++ b/naiveproxy/src/net/device_bound_sessions/mock_session_service.h @@ -56,13 +56,14 @@ class SessionServiceMock : public SessionService { (override)); MOCK_METHOD(void, DeleteSessionAndNotify, - (const SchemefulSite& site, - const Session::Id& id, + (DeletionReason reason, + const SessionKey& session_key, SessionService::OnAccessCallback per_request_callback), (override)); MOCK_METHOD(void, DeleteAllSessions, - (std::optional created_after_time, + (DeletionReason reason, + std::optional created_after_time, std::optional created_before_time, base::RepeatingCallback diff --git a/naiveproxy/src/net/device_bound_sessions/mock_session_store.h b/naiveproxy/src/net/device_bound_sessions/mock_session_store.h index dc2888d16e..b09ee88e3e 100644 --- a/naiveproxy/src/net/device_bound_sessions/mock_session_store.h +++ b/naiveproxy/src/net/device_bound_sessions/mock_session_store.h @@ -5,9 +5,6 @@ #ifndef NET_DEVICE_BOUND_SESSIONS_MOCK_SESSION_STORE_H_ #define NET_DEVICE_BOUND_SESSIONS_MOCK_SESSION_STORE_H_ -#include -#include - #include "base/functional/callback.h" #include "net/base/schemeful_site.h" #include "net/device_bound_sessions/session.h" @@ -30,8 +27,7 @@ class SessionStoreMock : public SessionStore { MOCK_METHOD(SessionStore::SessionsMap, GetAllSessions, (), (const, override)); MOCK_METHOD(void, RestoreSessionBindingKey, - (const SchemefulSite& site, - const Session::Id& session_id, + (const SessionKey& session_key, RestoreSessionBindingKeyCallback callback), (override)); }; diff --git a/naiveproxy/src/net/device_bound_sessions/proto/storage.proto b/naiveproxy/src/net/device_bound_sessions/proto/storage.proto index 19add53847..49951819d5 100644 --- a/naiveproxy/src/net/device_bound_sessions/proto/storage.proto +++ b/naiveproxy/src/net/device_bound_sessions/proto/storage.proto @@ -30,7 +30,7 @@ message UrlRule { // Whether the request should be included/excluded if there is a match. optional RuleType rule_type = 1; // Domain or pattern the URL must match. - optional string host_matcher_rule = 2; + optional string host_pattern = 2; // Prefix consisting of path components that the URL must match. optional string path_prefix = 3; } @@ -66,12 +66,6 @@ enum CookieSourceScheme { SECURE = 2; } -// Serialized data for a partitioned cookie. -message SerializedCookiePartitionKey { - optional string top_level_site = 1; - optional bool has_cross_site_ancestor = 2; -} - // Represents the need for a certain cookie to be present. // See //net/device_bound_sessions/cookie_craving.h for details. message CookieCraving { @@ -84,7 +78,7 @@ message CookieCraving { optional int64 creation_time = 7; optional CookieSameSite same_site = 8; optional CookieSourceScheme source_scheme = 9; - optional SerializedCookiePartitionKey serialized_partition_key = 10; + reserved 10; } // A Session represents persistent state scoped to a single DBSC session. @@ -107,6 +101,8 @@ message Session { // Creation date for session (encoded as microseconds since the Windows // epoch). optional int64 creation_time = 8; + // Initiator sites allowed to trigger refresh from third-party contexts + repeated string allowed_refresh_initiators = 9; } // All the sessions associated with a site (eTLD+1) and it's subdomains. diff --git a/naiveproxy/src/net/device_bound_sessions/registration_fetcher.cc b/naiveproxy/src/net/device_bound_sessions/registration_fetcher.cc index a3db53d29b..d90ac8d086 100644 --- a/naiveproxy/src/net/device_bound_sessions/registration_fetcher.cc +++ b/naiveproxy/src/net/device_bound_sessions/registration_fetcher.cc @@ -9,9 +9,11 @@ #include #include "base/functional/callback_helpers.h" +#include "base/metrics/histogram_functions.h" #include "components/unexportable_keys/background_task_priority.h" #include "components/unexportable_keys/unexportable_key_service.h" #include "net/base/io_buffer.h" +#include "net/base/net_errors.h" #include "net/device_bound_sessions/registration_request_param.h" #include "net/device_bound_sessions/session_binding_utils.h" #include "net/device_bound_sessions/session_challenge_param.h" @@ -67,6 +69,15 @@ constexpr int kBufferSize = 4096; constexpr unexportable_keys::BackgroundTaskPriority kTaskPriority = unexportable_keys::BackgroundTaskPriority::kBestEffort; +void RecordHttpResponseOrErrorCode(const char* metric_name, + int net_error, + int http_response_code) { + // No need to special-case `net::ERR_HTTP_RESPONSE_CODE_FAILURE` to return + // the HTTP response code, because `UrlRequest` does not use that net error. + base::UmaHistogramSparse( + metric_name, net_error == net::OK ? http_response_code : net_error); +} + void OnDataSigned( crypto::SignatureVerifier::SignatureAlgorithm algorithm, unexportable_keys::UnexportableKeyService& unexportable_key_service, @@ -132,21 +143,13 @@ void SignChallengeWithKey( key_id, std::move(callback))); } -class RegistrationFetcherImpl : public URLRequest::Delegate { +RegistrationFetcher::FetcherType* g_mock_fetcher = nullptr; + +class RegistrationFetcherImpl : public RegistrationFetcher, + URLRequest::Delegate { public: // URLRequest::Delegate - void OnReceivedRedirect(URLRequest* request, - const RedirectInfo& redirect_info, - bool* defer_redirect) override { - if (!IsSecure(redirect_info.new_url)) { - request->Cancel(); - OnResponseCompleted( - /*error_on_no_data=*/SessionError::ErrorType::kPersistentHttpError); - // *this is deleted here - } - } - // TODO(kristianm): Look into if OnAuthRequired might need to be customize // for DBSC @@ -158,6 +161,14 @@ class RegistrationFetcherImpl : public URLRequest::Delegate { // This is always called unless the request is deleted before it is called. void OnResponseStarted(URLRequest* request, int net_error) override { + HttpResponseHeaders* headers = request->response_headers(); + const int response_code = headers ? headers->response_code() : 0; + const char* histogram_name = + IsForRefreshRequest() + ? "Net.DeviceBoundSessions.Refresh.Network.Result" + : "Net.DeviceBoundSessions.Registration.Network.Result"; + RecordHttpResponseOrErrorCode(histogram_name, net_error, response_code); + if (net_error != OK) { OnResponseCompleted( /*error_on_no_data=*/SessionError::ErrorType::kNetError); @@ -165,9 +176,6 @@ class RegistrationFetcherImpl : public URLRequest::Delegate { return; } - HttpResponseHeaders* headers = request->response_headers(); - const int response_code = headers ? headers->response_code() : 0; - if (response_code == 401) { auto challenge_params = device_bound_sessions::SessionChallengeParam::CreateIfValid( @@ -231,27 +239,38 @@ class RegistrationFetcherImpl : public URLRequest::Delegate { const GURL& fetcher_endpoint, std::optional session_identifier, unexportable_keys::UnexportableKeyService& key_service, - const unexportable_keys::UnexportableKeyId& key_id, const URLRequestContext* context, const IsolationInfo& isolation_info, std::optional net_log_source, - const std::optional& original_request_initiator, - RegistrationFetcher::RegistrationCompleteCallback callback) + const std::optional& original_request_initiator) : fetcher_endpoint_(fetcher_endpoint), session_identifier_(std::move(session_identifier)), key_service_(key_service), - key_id_(key_id), context_(context), isolation_info_(isolation_info), net_log_source_(std::move(net_log_source)), original_request_initiator_(original_request_initiator), - callback_(std::move(callback)), buf_(base::MakeRefCounted(kBufferSize)) {} - ~RegistrationFetcherImpl() override { CHECK(!callback_); } + ~RegistrationFetcherImpl() override {} + + void OnKeyGenerated( + unexportable_keys::ServiceErrorOr + key_id) { + if (!key_id.has_value()) { + RunCallback( + base::unexpected(SessionError{SessionError::ErrorType::kKeyError})); + // `this` may be deleted. + return; + } + + key_id_ = std::move(*key_id); + } void StartFetch(std::optional challenge, std::optional authorization) { + CHECK(key_id_.has_value()); + current_challenge_ = std::move(challenge); current_authorization_ = std::move(authorization); @@ -261,9 +280,9 @@ class RegistrationFetcherImpl : public URLRequest::Delegate { AttemptChallengeSigning(); return; } else { - RunCallbackAndDeleteSelf(base::unexpected(SessionError{ - SessionError::ErrorType::kTooManyChallenges, - net::SchemefulSite(fetcher_endpoint_), session_identifier_})); + RunCallback(base::unexpected( + SessionError{SessionError::ErrorType::kTooManyChallenges})); + // `this` may be deleted. return; } } @@ -276,16 +295,70 @@ class RegistrationFetcherImpl : public URLRequest::Delegate { request_->Start(); } + base::WeakPtr GetWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); + } + + void StartCreateTokenAndFetch( + RegistrationRequestParam& registration_params, + base::span + supported_algos, + RegistrationCompleteCallback callback) override { + // Using mock fetcher for testing. + if (g_mock_fetcher) { + std::move(callback).Run(nullptr, g_mock_fetcher->Run()); + return; + } + + CHECK(callback_.is_null()); + callback_ = std::move(callback); + + key_service_->GenerateSigningKeySlowlyAsync( + supported_algos, kTaskPriority, + base::BindOnce(&RegistrationFetcherImpl::OnKeyGenerated, GetWeakPtr()) + .Then(base::BindOnce(&RegistrationFetcherImpl::StartFetch, + GetWeakPtr(), + registration_params.TakeChallenge(), + registration_params.TakeAuthorization()))); + } + + void StartFetchWithExistingKey( + RegistrationRequestParam& request_params, + unexportable_keys::ServiceErrorOr + key_id, + RegistrationCompleteCallback callback) override { + // Using mock fetcher for testing. + if (g_mock_fetcher) { + std::move(callback).Run(nullptr, g_mock_fetcher->Run()); + return; + } + + if (!key_id.has_value()) { + std::move(callback).Run( + nullptr, + base::unexpected(SessionError{SessionError::ErrorType::kKeyError})); + return; + } + + CHECK(callback_.is_null()); + callback_ = std::move(callback); + + key_id_ = *key_id; + + StartFetch(request_params.TakeChallenge(), + request_params.TakeAuthorization()); + } + private: static constexpr size_t kMaxSigningFailures = 2; static constexpr size_t kMaxChallenges = 5; void AttemptChallengeSigning() { SignChallengeWithKey( - *key_service_, key_id_, fetcher_endpoint_, *current_challenge_, + *key_service_, *key_id_, fetcher_endpoint_, *current_challenge_, current_authorization_, session_identifier_, base::BindOnce(&RegistrationFetcherImpl::OnRegistrationTokenCreated, - base::Unretained(this))); + GetWeakPtr())); } void OnRegistrationTokenCreated( @@ -296,10 +369,9 @@ class RegistrationFetcherImpl : public URLRequest::Delegate { AttemptChallengeSigning(); return; } else { - RunCallbackAndDeleteSelf(base::unexpected(SessionError{ - SessionError::ErrorType::kSigningError, - net::SchemefulSite(url::Origin::Create(fetcher_endpoint_)), - session_identifier_})); + RunCallback(base::unexpected( + SessionError{SessionError::ErrorType::kSigningError})); + // `this` may be deleted. return; } } @@ -335,10 +407,9 @@ class RegistrationFetcherImpl : public URLRequest::Delegate { void OnChallengeNeeded( std::optional> challenge_params) { if (!challenge_params || challenge_params->empty()) { - RunCallbackAndDeleteSelf(base::unexpected(SessionError{ - SessionError::ErrorType::kInvalidChallenge, - net::SchemefulSite(url::Origin::Create(fetcher_endpoint_)), - session_identifier_})); + RunCallback(base::unexpected( + SessionError{SessionError::ErrorType::kInvalidChallenge})); + // `this` may be deleted. return; } @@ -350,24 +421,20 @@ class RegistrationFetcherImpl : public URLRequest::Delegate { void OnResponseCompleted(SessionError::ErrorType error_on_no_data) { if (data_received_.empty()) { - RunCallbackAndDeleteSelf(base::unexpected(SessionError{ - error_on_no_data, - net::SchemefulSite(url::Origin::Create(fetcher_endpoint_)), - session_identifier_})); + RunCallback(base::unexpected(SessionError{error_on_no_data})); + // `this` may be deleted. return; } - RunCallbackAndDeleteSelf( - ParseSessionInstructionJson(request_->url(), key_id_, data_received_)); + RunCallback(ParseSessionInstructionJson( + request_->url(), *key_id_, session_identifier_, data_received_)); + // `this` may be deleted. } - // Running callback when fetching is complete or on error. - // Deletes `this` afterwards. - void RunCallbackAndDeleteSelf( + void RunCallback( base::expected params_or_error) { AddNetLogResult(params_or_error); - std::move(callback_).Run(std::move(params_or_error)); - delete this; + std::move(callback_).Run(this, std::move(params_or_error)); } void AddNetLogResult( @@ -408,7 +475,7 @@ class RegistrationFetcherImpl : public URLRequest::Delegate { // Populated iff this is a refresh request (not a registration request). std::optional session_identifier_; const raw_ref key_service_; - unexportable_keys::UnexportableKeyId key_id_; + std::optional key_id_; raw_ptr context_; IsolationInfo isolation_info_; std::optional net_log_source_; @@ -426,76 +493,24 @@ class RegistrationFetcherImpl : public URLRequest::Delegate { std::optional current_authorization_; size_t number_of_signing_failures_ = 0; size_t number_of_challenges_ = 0; -}; -RegistrationFetcher::FetcherType* g_mock_fetcher = nullptr; + base::WeakPtrFactory weak_ptr_factory_{this}; +}; } // namespace // static -void RegistrationFetcher::StartCreateTokenAndFetch( - RegistrationFetcherParam registration_params, +std::unique_ptr RegistrationFetcher::CreateFetcher( + RegistrationRequestParam& request_params, unexportable_keys::UnexportableKeyService& key_service, - // TODO(kristianm): Check the lifetime of context and make sure this use - // is safe. const URLRequestContext* context, const IsolationInfo& isolation_info, std::optional net_log_source, - const std::optional& original_request_initiator, - RegistrationCompleteCallback callback) { - // Using mock fetcher for testing - if (g_mock_fetcher) { - std::move(callback).Run(g_mock_fetcher->Run()); - return; - } - - const auto supported_algos = registration_params.supported_algos(); - auto request_params = RegistrationRequestParam::CreateForRegistration( - std::move(registration_params)); - // `key_service` is created along with `SessionService` and will be valid - // until the browser ends, hence `std::ref` is safe here. - key_service.GenerateSigningKeySlowlyAsync( - supported_algos, kTaskPriority, - base::BindOnce(&RegistrationFetcher::StartFetchWithExistingKey, - std::move(request_params), std::ref(key_service), context, - isolation_info, net_log_source, original_request_initiator, - std::move(callback))); -} - -// static -void RegistrationFetcher::StartFetchWithExistingKey( - RegistrationRequestParam request_params, - unexportable_keys::UnexportableKeyService& unexportable_key_service, - const URLRequestContext* context, - const IsolationInfo& isolation_info, - std::optional net_log_source, - const std::optional& original_request_initiator, - RegistrationFetcher::RegistrationCompleteCallback callback, - unexportable_keys::ServiceErrorOr - key_id) { - // Using mock fetcher for testing. - if (g_mock_fetcher) { - std::move(callback).Run(g_mock_fetcher->Run()); - return; - } - - if (!key_id.has_value()) { - std::move(callback).Run(base::unexpected( - SessionError{SessionError::ErrorType::kKeyError, - net::SchemefulSite(request_params.registration_endpoint()), - request_params.session_identifier()})); - return; - } - - // RegistrationFetcherImpl manages its own lifetime. - RegistrationFetcherImpl* fetcher = new RegistrationFetcherImpl( + const std::optional& original_request_initiator) { + return std::make_unique( request_params.TakeRegistrationEndpoint(), - request_params.TakeSessionIdentifier(), unexportable_key_service, - key_id.value(), context, isolation_info, net_log_source, - original_request_initiator, std::move(callback)); - - fetcher->StartFetch(request_params.TakeChallenge(), - request_params.TakeAuthorization()); + request_params.TakeSessionIdentifier(), key_service, context, + isolation_info, net_log_source, original_request_initiator); } void RegistrationFetcher::SetFetcherForTesting(FetcherType* func) { diff --git a/naiveproxy/src/net/device_bound_sessions/registration_fetcher.h b/naiveproxy/src/net/device_bound_sessions/registration_fetcher.h index 63ae2e8287..6e9d6a0b99 100644 --- a/naiveproxy/src/net/device_bound_sessions/registration_fetcher.h +++ b/naiveproxy/src/net/device_bound_sessions/registration_fetcher.h @@ -40,7 +40,8 @@ class RegistrationRequestParam; class NET_EXPORT RegistrationFetcher { public: using RegistrationCompleteCallback = - base::OnceCallback)>; + base::OnceCallback)>; using FetcherType = base::RepeatingCallback()>; @@ -51,35 +52,36 @@ class NET_EXPORT RegistrationFetcher { unexportable_keys::UnexportableKeyId key_id; }; + // Creates a fetcher that can be used to do registration or refresh. + static std::unique_ptr CreateFetcher( + RegistrationRequestParam& request_params, + unexportable_keys::UnexportableKeyService& key_service, + const URLRequestContext* context, + const IsolationInfo& isolation_info, + std::optional net_log_source, + const std::optional& original_request_initiator); + // Creates an unexportable key from the key service, creates a registration // JWT and signs it with the new key. Starts the network request to the DBSC // registration endpoint with the signed JWT in the header. `callback` // is called with the fetch results upon completion. // 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( - RegistrationFetcherParam registration_params, - unexportable_keys::UnexportableKeyService& key_service, - const URLRequestContext* context, - const IsolationInfo& isolation_info, - std::optional net_log_source, - const std::optional& original_request_initiator, - RegistrationCompleteCallback callback); + virtual void StartCreateTokenAndFetch( + RegistrationRequestParam& registration_params, + base::span + supported_algos, + RegistrationCompleteCallback callback) = 0; // Starts the network request to the DBSC refresh endpoint with existing key // id. `callback` is called with the fetch results upon completion. This can // fail during signing and during the network request, and if so the callback // will be called with a std::nullopt. - static void StartFetchWithExistingKey( - RegistrationRequestParam request_params, - unexportable_keys::UnexportableKeyService& key_service, - const URLRequestContext* context, - const IsolationInfo& isolation_info, - std::optional net_log_source, - const std::optional& original_request_initiator, - RegistrationCompleteCallback callback, + virtual void StartFetchWithExistingKey( + RegistrationRequestParam& request_params, unexportable_keys::ServiceErrorOr - key_id); + key_id, + RegistrationCompleteCallback callback) = 0; // Helper function for generating a new binding key and a registration token // to bind the key on the server. unexportable_key_service must outlive the @@ -95,6 +97,8 @@ class NET_EXPORT RegistrationFetcher { callback); static void SetFetcherForTesting(FetcherType* fetcher); + + virtual ~RegistrationFetcher() = default; }; } // namespace net::device_bound_sessions diff --git a/naiveproxy/src/net/device_bound_sessions/registration_request_param.h b/naiveproxy/src/net/device_bound_sessions/registration_request_param.h index 63852b1bc4..4c746a6043 100644 --- a/naiveproxy/src/net/device_bound_sessions/registration_request_param.h +++ b/naiveproxy/src/net/device_bound_sessions/registration_request_param.h @@ -32,10 +32,6 @@ class NET_EXPORT RegistrationRequestParam { RegistrationFetcherParam&& fetcher_param); static RegistrationRequestParam CreateForRefresh(const Session& session); - const GURL& registration_endpoint() const { return registration_endpoint_; } - const std::optional& session_identifier() const { - return session_identifier_; - } const std::optional& challenge() const { return challenge_; } const std::optional& authorization() const { return authorization_; diff --git a/naiveproxy/src/net/device_bound_sessions/session.cc b/naiveproxy/src/net/device_bound_sessions/session.cc index 62a6a93b6a..21c3f467a5 100644 --- a/naiveproxy/src/net/device_bound_sessions/session.cc +++ b/naiveproxy/src/net/device_bound_sessions/session.cc @@ -6,8 +6,11 @@ #include +#include "base/memory/ptr_util.h" #include "base/strings/escape.h" +#include "base/types/expected_macros.h" #include "components/unexportable_keys/unexportable_key_id.h" +#include "net/base/features.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_access_params.h" @@ -16,6 +19,7 @@ #include "net/cookies/cookie_store.h" #include "net/cookies/cookie_util.h" #include "net/device_bound_sessions/cookie_craving.h" +#include "net/device_bound_sessions/host_patterns.h" #include "net/device_bound_sessions/proto/storage.pb.h" #include "net/device_bound_sessions/session_binding_utils.h" #include "net/device_bound_sessions/session_error.h" @@ -57,10 +61,10 @@ constexpr net::BackoffEntry::Policy kBackoffPolicy = { }; } -Session::Session(Id id, url::Origin origin, GURL refresh) +Session::Session(Id id, SessionInclusionRules inclusion_rules, GURL refresh) : id_(id), refresh_url_(refresh), - inclusion_rules_(origin), + inclusion_rules_(std::move(inclusion_rules)), backoff_(&kBackoffPolicy) {} Session::Session(Id id, @@ -69,7 +73,8 @@ Session::Session(Id id, std::vector cookie_cravings, bool should_defer_when_expired, base::Time creation_date, - base::Time expiry_date) + base::Time expiry_date, + std::vector allowed_refresh_initiators) : id_(id), refresh_url_(refresh), inclusion_rules_(std::move(inclusion_rules)), @@ -77,7 +82,8 @@ Session::Session(Id id, should_defer_when_expired_(should_defer_when_expired), creation_date_(creation_date), expiry_date_(expiry_date), - backoff_(&kBackoffPolicy) {} + backoff_(&kBackoffPolicy), + allowed_refresh_initiators_(std::move(allowed_refresh_initiators)) {} Session::~Session() = default; @@ -86,16 +92,13 @@ base::expected, SessionError> Session::CreateIfValid( const SessionParams& params) { if (!params.fetcher_url.is_valid()) { return base::unexpected( - SessionError{SessionError::ErrorType::kInvalidFetcherUrl, - net::SchemefulSite(), /*session_id=*/std::nullopt}); + SessionError{SessionError::ErrorType::kInvalidFetcherUrl}); } else if (params.refresh_url.empty()) { return base::unexpected( - SessionError{SessionError::ErrorType::kInvalidRefreshUrl, - net::SchemefulSite(), /*session_id=*/std::nullopt}); + SessionError{SessionError::ErrorType::kInvalidRefreshUrl}); } else if (params.session_id.empty()) { return base::unexpected( - SessionError{SessionError::ErrorType::kInvalidSessionId, - net::SchemefulSite(), /*session_id=*/std::nullopt}); + SessionError{SessionError::ErrorType::kInvalidSessionId}); } // If there is an origin in the scope, verify it is valid. Default to the @@ -106,16 +109,14 @@ base::expected, SessionError> Session::CreateIfValid( url::Origin scope_origin = url::Origin::Create(scope_origin_as_url); if (scope_origin.opaque()) { return base::unexpected( - SessionError{SessionError::ErrorType::kInvalidScopeOrigin, - net::SchemefulSite(), /*session_id=*/std::nullopt}); + SessionError{SessionError::ErrorType::kInvalidScopeOrigin}); } // Check if the scope-origin is samesite with fetcher URL. if (net::SchemefulSite(scope_origin_as_url) != net::SchemefulSite(params.fetcher_url)) { return base::unexpected( - SessionError{SessionError::ErrorType::kScopeOriginSameSiteMismatch, - net::SchemefulSite(), /*session_id=*/std::nullopt}); + SessionError{SessionError::ErrorType::kScopeOriginSameSiteMismatch}); } // The refresh endpoint can be a full URL (samesite with request origin) @@ -132,47 +133,36 @@ base::expected, SessionError> Session::CreateIfValid( if (!candidate_refresh_endpoint.is_valid() || !IsSecure(candidate_refresh_endpoint)) { return base::unexpected( - SessionError{SessionError::ErrorType::kInvalidRefreshUrl, - net::SchemefulSite(), /*session_id=*/std::nullopt}); + SessionError{SessionError::ErrorType::kInvalidRefreshUrl}); } // Check if the refresh URL is same-site with the fetcher URL. if (net::SchemefulSite(candidate_refresh_endpoint) != net::SchemefulSite(params.fetcher_url)) { return base::unexpected( - SessionError{SessionError::ErrorType::kRefreshUrlSameSiteMismatch, - net::SchemefulSite(), /*session_id=*/std::nullopt}); + SessionError{SessionError::ErrorType::kRefreshUrlSameSiteMismatch}); } - std::unique_ptr session(new Session( - Id(params.session_id), scope_origin, candidate_refresh_endpoint)); - for (const auto& spec : params.scope.specifications) { - if (!spec.domain.empty() && !spec.path.empty()) { - const auto inclusion_result = - spec.type == SessionParams::Scope::Specification::Type::kExclude - ? SessionInclusionRules::InclusionResult::kExclude - : SessionInclusionRules::InclusionResult::kInclude; - session->inclusion_rules_.AddUrlRuleIfValid(inclusion_result, spec.domain, - spec.path); - } - } - - // Sessions should never include the refresh endpoint, since that would - // prevent them from ever refreshing when a cookie expires. - session->inclusion_rules_.AddUrlRuleIfValid( - SessionInclusionRules::InclusionResult::kExclude, - candidate_refresh_endpoint.host(), candidate_refresh_endpoint.path()); - - session->inclusion_rules_.SetIncludeSite(params.scope.include_site); + ASSIGN_OR_RETURN(SessionInclusionRules session_inclusion_rules, + SessionInclusionRules::Create(scope_origin, params.scope, + candidate_refresh_endpoint)); + std::unique_ptr session( + new Session(Id(params.session_id), std::move(session_inclusion_rules), + candidate_refresh_endpoint)); for (const auto& cred : params.credentials) { - if (!cred.name.empty()) { - std::optional craving = - CookieCraving::Create(params.fetcher_url, cred.name, cred.attributes, - base::Time::Now(), std::nullopt); - if (craving) { - session->cookie_cravings_.push_back(*craving); - } + if (cred.name.empty()) { + return base::unexpected( + SessionError{SessionError::ErrorType::kInvalidCredentials}); + } + + std::optional craving = CookieCraving::Create( + params.fetcher_url, cred.name, cred.attributes, base::Time::Now()); + if (craving) { + session->cookie_cravings_.push_back(*craving); + } else { + return base::unexpected( + SessionError{SessionError::ErrorType::kInvalidCredentials}); } } @@ -180,6 +170,15 @@ base::expected, SessionError> Session::CreateIfValid( session->set_expiry_date(base::Time::Now() + kSessionTtl); session->set_unexportable_key_id(std::move(params.key_id)); + for (const std::string& initiator : params.allowed_refresh_initiators) { + if (!IsValidHostPattern(initiator)) { + return base::unexpected( + SessionError{SessionError::ErrorType::kInvalidRefreshInitiators}); + } + } + session->set_allowed_refresh_initiators( + std::move(params.allowed_refresh_initiators)); + return base::ok(std::move(session)); } @@ -200,7 +199,7 @@ std::unique_ptr Session::CreateFromProto(const proto::Session& proto) { return nullptr; } - std::unique_ptr inclusion_rules = + std::optional inclusion_rules = SessionInclusionRules::CreateFromProto(proto.session_inclusion_rules()); if (!inclusion_rules) { return nullptr; @@ -228,12 +227,19 @@ std::unique_ptr Session::CreateFromProto(const proto::Session& proto) { return nullptr; } - std::unique_ptr result(new Session( + std::vector allowed_refresh_initiators; + allowed_refresh_initiators.reserve(proto.allowed_refresh_initiators_size()); + for (const std::string& initiator : proto.allowed_refresh_initiators()) { + if (!IsValidHostPattern(initiator)) { + return nullptr; + } + allowed_refresh_initiators.emplace_back(initiator); + } + + return base::WrapUnique(new Session( Id(proto.id()), std::move(refresh), std::move(*inclusion_rules), std::move(cravings), proto.should_defer_when_expired(), creation_date, - expiry_date)); - - return result; + expiry_date, std::move(allowed_refresh_initiators))); } proto::Session Session::ToProto() const { @@ -248,10 +254,14 @@ proto::Session Session::ToProto() const { *session_proto.mutable_session_inclusion_rules() = inclusion_rules_.ToProto(); - for (auto& craving : cookie_cravings_) { + for (const auto& craving : cookie_cravings_) { session_proto.mutable_cookie_cravings()->Add(craving.ToProto()); } + for (const std::string& initiator : allowed_refresh_initiators_) { + *session_proto.add_allowed_refresh_initiators() = initiator; + } + return session_proto; } @@ -292,6 +302,20 @@ bool Session::ShouldDeferRequest( return dict; }); + if (base::FeatureList::IsEnabled( + features::kDeviceBoundSessionsOriginTrialFeedback) && + !AllowedToInitiateRefresh(request->initiator())) { + request->net_log().AddEvent( + net::NetLogEventType::CHECK_DBSC_REFRESH_REQUIRED, + [&](NetLogCaptureMode capture_mode) { + base::Value::Dict dict; + dict.Set("refresh_required_reason", + "refresh_not_allowed_for_initiator"); + return dict; + }); + return false; + } + // TODO(crbug.com/353766029): Refactor this. // The below is all copied from AddCookieHeaderAndStart. We should refactor // it. @@ -402,7 +426,8 @@ bool Session::IsEqualForTesting(const Session& other) const { creation_date_ == other.creation_date_ && expiry_date_ == other.expiry_date_ && key_id_or_error_ == other.key_id_or_error_ && - cached_challenge_ == other.cached_challenge_; + cached_challenge_ == other.cached_challenge_ && + allowed_refresh_initiators_ == other.allowed_refresh_initiators_; } void Session::RecordAccess() { @@ -414,6 +439,25 @@ bool Session::IncludesUrl(const GURL& url) const { SessionInclusionRules::kInclude; } +bool Session::AllowedToInitiateRefresh( + const std::optional& initiator) const { + // The initiator is missing only for browser-initiated requests. + if (!initiator.has_value()) { + return true; + } + + if (inclusion_rules_.AllowsRefreshForInitiator(initiator.value())) { + return true; + } + + for (const std::string& initiator_pattern : allowed_refresh_initiators_) { + if (MatchesHostPattern(initiator_pattern, initiator->host())) { + return true; + } + } + return false; +} + bool Session::ShouldBackoff() const { return backoff_.ShouldRejectRequest(); } @@ -440,6 +484,12 @@ void Session::InformOfRefreshResult(SessionError::ErrorType error_type) { case kScopeOriginSameSiteMismatch: case kRefreshUrlSameSiteMismatch: case kInvalidScopeOrigin: + case kMismatchedSessionId: + case kInvalidRefreshInitiators: + case kInvalidScopeRule: + case kMissingScope: + case kNoCredentials: + case kInvalidScopeIncludeSite: // We do not want to back off on many network connection errors // (e.g. internet disconnected), so we do not hit our maximum diff --git a/naiveproxy/src/net/device_bound_sessions/session.h b/naiveproxy/src/net/device_bound_sessions/session.h index 2188979a18..47a31e00bd 100644 --- a/naiveproxy/src/net/device_bound_sessions/session.h +++ b/naiveproxy/src/net/device_bound_sessions/session.h @@ -73,9 +73,9 @@ class NET_EXPORT Session { return cached_challenge_; } - const base::Time& creation_date() const { return creation_date_; } + base::Time creation_date() const { return creation_date_; } - const base::Time& expiry_date() const { return expiry_date_; } + base::Time expiry_date() const { return expiry_date_; } bool should_defer_when_expired() const { return should_defer_when_expired_; } @@ -99,6 +99,11 @@ class NET_EXPORT Session { // Whether the URL is in-scope for the session. bool IncludesUrl(const GURL& url) const; + // Whether a request initiated by `initiator` is allowed to trigger a + // refresh for this session. + bool AllowedToInitiateRefresh( + const std::optional& initiator) const; + bool ShouldBackoff() const; // Inform the session about a refresh so it can decide whether to @@ -107,15 +112,25 @@ class NET_EXPORT Session { const url::Origin& origin() const { return inclusion_rules_.origin(); } + const std::vector& allowed_refresh_initiators() { + return allowed_refresh_initiators_; + } + + void set_allowed_refresh_initiators( + std::vector allowed_refresh_initiators) { + allowed_refresh_initiators_ = std::move(allowed_refresh_initiators); + } + private: - Session(Id id, url::Origin origin, GURL refresh); + Session(Id id, SessionInclusionRules inclusion_rules, GURL refresh); Session(Id id, GURL refresh, SessionInclusionRules inclusion_rules, std::vector cookie_cravings, bool should_defer_when_expired, base::Time creation_date, - base::Time expiry_date); + base::Time expiry_date, + std::vector allowed_refresh_initiators); // The unique server-issued identifier of the session. const Id id_; @@ -156,6 +171,8 @@ class NET_EXPORT Session { // preventing Chrome from causing a DoS due to expiring session // cookies. net::BackoffEntry backoff_; + // Host patterns for initiators allowed to trigger a refresh. + std::vector allowed_refresh_initiators_; }; } // namespace net::device_bound_sessions diff --git a/naiveproxy/src/net/device_bound_sessions/session_error.cc b/naiveproxy/src/net/device_bound_sessions/session_error.cc index 761385ae13..82b09b9197 100644 --- a/naiveproxy/src/net/device_bound_sessions/session_error.cc +++ b/naiveproxy/src/net/device_bound_sessions/session_error.cc @@ -6,10 +6,7 @@ namespace net::device_bound_sessions { -SessionError::SessionError(SessionError::ErrorType type, - net::SchemefulSite site, - std::optional session_id) - : type(type), site(std::move(site)), session_id(std::move(session_id)) {} +SessionError::SessionError(SessionError::ErrorType type) : type(type) {} SessionError::~SessionError() = default; @@ -36,6 +33,12 @@ bool SessionError::IsFatal() const { case kScopeOriginSameSiteMismatch: case kRefreshUrlSameSiteMismatch: case kInvalidScopeOrigin: + case kMismatchedSessionId: + case kInvalidRefreshInitiators: + case kInvalidScopeRule: + case kMissingScope: + case kNoCredentials: + case kInvalidScopeIncludeSite: return true; case kNetError: @@ -66,6 +69,12 @@ bool SessionError::IsServerError() const { case kRefreshUrlSameSiteMismatch: case kInvalidScopeOrigin: case kTransientHttpError: + case kMismatchedSessionId: + case kInvalidRefreshInitiators: + case kInvalidScopeRule: + case kMissingScope: + case kNoCredentials: + case kInvalidScopeIncludeSite: return true; } } diff --git a/naiveproxy/src/net/device_bound_sessions/session_error.h b/naiveproxy/src/net/device_bound_sessions/session_error.h index 55d7e93b79..7cc6b129d3 100644 --- a/naiveproxy/src/net/device_bound_sessions/session_error.h +++ b/naiveproxy/src/net/device_bound_sessions/session_error.h @@ -33,13 +33,17 @@ struct NET_EXPORT SessionError { kScopeOriginSameSiteMismatch = 15, kRefreshUrlSameSiteMismatch = 16, kInvalidScopeOrigin = 17, - kMaxValue = kInvalidScopeOrigin + kMismatchedSessionId = 18, + kInvalidRefreshInitiators = 19, + kInvalidScopeRule = 20, + kMissingScope = 21, + kNoCredentials = 22, + kInvalidScopeIncludeSite = 23, + kMaxValue = kInvalidScopeIncludeSite }; // LINT.ThenChange(//tools/metrics/histograms/metadata/net/enums.xml:DeviceBoundSessionError) - SessionError(ErrorType type, - net::SchemefulSite site, - std::optional session_id); + explicit SessionError(ErrorType type); ~SessionError(); SessionError(const SessionError&) = delete; @@ -54,8 +58,6 @@ struct NET_EXPORT SessionError { bool IsServerError() const; ErrorType type; - net::SchemefulSite site; - std::optional session_id; }; } // namespace net::device_bound_sessions 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 37d2cd54cd..62bd66662b 100644 --- a/naiveproxy/src/net/device_bound_sessions/session_inclusion_rules.cc +++ b/naiveproxy/src/net/device_bound_sessions/session_inclusion_rules.cc @@ -9,12 +9,10 @@ #include "base/check.h" #include "base/containers/adapters.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/strings/string_util.h" -#include "net/base/ip_address.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" -#include "net/base/scheme_host_port_matcher_result.h" -#include "net/base/scheme_host_port_matcher_rule.h" -#include "net/base/url_util.h" +#include "net/device_bound_sessions/host_patterns.h" #include "net/device_bound_sessions/proto/storage.pb.h" #include "net/device_bound_sessions/session.h" @@ -30,15 +28,6 @@ bool IsIncludeSiteAllowed(const url::Origin& origin) { return !domain_and_registry.empty() && origin.host() == domain_and_registry; } -// Types of characters valid in IPv6 addresses. -// Derived from logic in url::DoIPv6AddressToNumber() and url::DoParseIPv6(). -bool IsValidIPv6Char(char c) { - return c == ':' || base::IsHexDigit(c) || c == '.' || - // 'x' or 'X' is used in IPv4 to denote hex values, and can be used in - // parts of IPv6 addresses. - c == 'x' || c == 'X'; -} - proto::RuleType GetRuleTypeProto( SessionInclusionRules::InclusionResult result) { return result == SessionInclusionRules::InclusionResult::kInclude @@ -46,12 +35,12 @@ proto::RuleType GetRuleTypeProto( : proto::RuleType::EXCLUDE; } -std::optional GetInclusionResult( +std::optional GetInclusionResult( proto::RuleType proto) { if (proto == proto::RuleType::INCLUDE) { - return SessionInclusionRules::InclusionResult::kInclude; + return SessionParams::Scope::Specification::Type::kInclude; } else if (proto == proto::RuleType::EXCLUDE) { - return SessionInclusionRules::InclusionResult::kExclude; + return SessionParams::Scope::Specification::Type::kExclude; } // proto = RULE_TYPE_UNSPECIFIED @@ -77,41 +66,68 @@ struct SessionInclusionRules::UrlRule { // Domain or pattern that the URL must match. This must either be a // full domain (host piece) or a pattern containing a wildcard in the - // most-specific (leftmost) label position followed by a dot and a non-eTLD. + // most-specific (leftmost) label position followed by a dot. // The matched strings follow SchemeHostPortMatcherRule's logic, but with // some extra requirements for validity: - // - A leading wildcard * must be followed by a dot, so "*ple.com" is not - // acceptable. - // - "*.com" is not accepted because com is an eTLD. Same with "*.co.uk" and - // similar. + // - If the pattern has a leading wildcard *, it must be "*" itself or + // the * must be followed by a dot, so "*ple.com" is not acceptable. // - Multiple wildcards are not allowed. // - Internal wildcards are not allowed, so "sub.*.example.com" does not // work because the wildcard is not the leftmost component. - // - IP addresses also work if specified as the exact host, as described in - // SchemeHostPortMatcherRule. - std::unique_ptr host_matcher_rule; + // - IP addresses also work. IPv4 addresses can contain wildcards. + std::string host_pattern; // Prefix consisting of path components that the URL must match. Must begin // with '/'. Wildcards are not allowed. Simply use "/" to match all paths. std::string path_prefix; - friend bool operator==(const UrlRule& lhs, const UrlRule& rhs) { - return lhs.rule_type == rhs.rule_type && - lhs.path_prefix == rhs.path_prefix && - lhs.host_matcher_rule->ToString() == - rhs.host_matcher_rule->ToString(); - } + friend bool operator==(const UrlRule& lhs, const UrlRule& rhs) = default; // Returns whether the given `url` matches this rule. Note that this // function does not check the scheme and port portions of the URL/origin. bool MatchesHostAndPath(const GURL& url) const; }; +// static +base::expected +SessionInclusionRules::Create(const url::Origin& origin, + const SessionParams::Scope& scope_params, + const GURL& refresh_endpoint) { + SessionInclusionRules rules(origin); + + if (scope_params.include_site && !rules.may_include_site_) { + return base::unexpected( + SessionError{SessionError::ErrorType::kInvalidScopeIncludeSite}); + } + + rules.SetIncludeSite(scope_params.include_site); + + for (const auto& spec : scope_params.specifications) { + const auto inclusion_result = + spec.type == SessionParams::Scope::Specification::Type::kExclude + ? SessionInclusionRules::InclusionResult::kExclude + : SessionInclusionRules::InclusionResult::kInclude; + if (!rules.AddUrlRuleIfValid(inclusion_result, spec.domain, spec.path)) { + return base::unexpected( + SessionError{SessionError::ErrorType::kInvalidScopeRule}); + } + } + + if (refresh_endpoint.is_valid()) { + // Sessions should never include the refresh endpoint, since that would + // prevent them from ever refreshing when a cookie expires. We intentionally + // don't return an error if the rule is not valid or add a CHECK, because a + // refresh URL is allowed to be outside an origin-scoped session. + rules.AddUrlRuleIfValid(SessionInclusionRules::InclusionResult::kExclude, + refresh_endpoint.host(), refresh_endpoint.path()); + } + + return rules; +} + SessionInclusionRules::SessionInclusionRules(const url::Origin& origin) : origin_(origin), may_include_site_(IsIncludeSiteAllowed(origin)) {} -SessionInclusionRules::SessionInclusionRules() = default; - SessionInclusionRules::~SessionInclusionRules() = default; SessionInclusionRules::SessionInclusionRules(SessionInclusionRules&& other) = @@ -124,10 +140,6 @@ bool SessionInclusionRules::operator==( const SessionInclusionRules& other) const = default; void SessionInclusionRules::SetIncludeSite(bool include_site) { - if (!may_include_site_) { - return; - } - if (!include_site) { include_site_.reset(); return; @@ -142,98 +154,41 @@ bool SessionInclusionRules::AddUrlRuleIfValid(InclusionResult rule_type, if (path_prefix.empty() || path_prefix.front() != '/') { return false; } - if (host_pattern.empty()) { + + if (!IsValidHostPattern(host_pattern)) { return false; } - // If only the origin is allowed, the host_pattern must be precisely its host. - bool host_pattern_is_host = host_pattern == origin_.host(); - if (!may_include_site_ && !host_pattern_is_host) { + // Return early if the rule can't match anything. For origin-scoped + // sessions, the origin must match the host pattern. + if (!include_site_ && !MatchesHostPattern(host_pattern, origin_.host())) { return false; } - // Don't allow '*' anywhere besides the first character of the pattern. - size_t star_pos = host_pattern.rfind('*'); - if (star_pos != std::string::npos && star_pos != 0) { - return false; - } - // Only allow wildcard if immediately followed by a dot. - bool has_initial_wildcard_label = host_pattern.starts_with("*."); - if (star_pos != std::string::npos && !has_initial_wildcard_label) { - return false; - } - - std::string_view hostlike_part{host_pattern}; - if (has_initial_wildcard_label) { - hostlike_part = hostlike_part.substr(2); - } - - bool presumed_ipv6 = host_pattern.front() == '['; - if (presumed_ipv6 && host_pattern.back() != ']') { - return false; - } - - // Allow only specific characters into SchemeHostPortMatcherRule parsing. - if (presumed_ipv6) { - // Leave out the brackets, but everything else must be a valid char. - std::string_view ipv6_address{host_pattern.begin() + 1, - host_pattern.end() - 1}; - if (std::find_if_not(ipv6_address.begin(), ipv6_address.end(), - &IsValidIPv6Char) != ipv6_address.end()) { - return false; + // For site-scoped sessions, either the site itself matches the + // pattern (e.g. a pattern of "*") or the hostlike part of the pattern + // is same-site. + if (include_site_ && !MatchesHostPattern(host_pattern, origin_.host())) { + std::string_view hostlike_part = host_pattern; + if (hostlike_part.starts_with("*.")) { + hostlike_part = hostlike_part.substr(2); } - } else { - // Note that this excludes a ':' character specifying a port number, even - // though SchemeHostPortMatcherRule supports it. Same for '/' (for the - // scheme or an IP block). - // TODO(chlily): Consider supporting port numbers. - if (!IsCanonicalizedHostCompliant(hostlike_part)) { + + std::string hostlike_part_domain = + registry_controlled_domains::GetDomainAndRegistry( + hostlike_part, + registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); + + std::string domain_and_registry = + registry_controlled_domains::GetDomainAndRegistry( + origin_, registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); + + if (hostlike_part_domain != domain_and_registry) { return false; } } - // Delegate the rest of the parsing to SchemeHostPortMatcherRule. - std::unique_ptr host_matcher_rule = - SchemeHostPortMatcherRule::FromUntrimmedRawString(host_pattern); - if (!host_matcher_rule) { - return false; - } - - // Now that we know the host_pattern is at least the right shape, validate the - // remaining restrictions. - - // Skip the eTLD lookups if the host pattern is an exact match. - if (host_pattern_is_host) { - url_rules_.emplace_back(rule_type, std::move(host_matcher_rule), - path_prefix); - return true; - } - - std::string hostlike_part_domain = - registry_controlled_domains::GetDomainAndRegistry( - hostlike_part, - registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); - // If there is a wildcard, we require the pattern to be a normal domain and - // not an eTLD. - if (has_initial_wildcard_label && hostlike_part_domain.empty()) { - return false; - } - - // Validate that the host pattern is on the right origin/site. - // TODO(chlily): Perhaps we should use a cached value, but surely URL rule - // parsing only happens a small number of times. - std::string domain_and_registry = - registry_controlled_domains::GetDomainAndRegistry( - origin_, registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); - // The origin_ must have an eTLD+1, because if it didn't, then we'd know that - // !may_include_site_, and that would mean we'd have already returned early - // and would never get here. - CHECK(!domain_and_registry.empty()); - if (hostlike_part_domain != domain_and_registry) { - return false; - } - - url_rules_.emplace_back(rule_type, std::move(host_matcher_rule), path_prefix); + url_rules_.emplace_back(rule_type, host_pattern, path_prefix); return true; } @@ -263,9 +218,21 @@ SessionInclusionRules::EvaluateRequestUrl(const GURL& url) const { return SessionInclusionRules::kInclude; } +bool SessionInclusionRules::AllowsRefreshForInitiator( + const url::Origin& initiator) const { + if (include_site_ && include_site_->IsSameSiteWith(initiator)) { + return true; + } + + if (!include_site_ && origin_.IsSameOriginWith(initiator)) { + return true; + } + + return false; +} + bool SessionInclusionRules::UrlRule::MatchesHostAndPath(const GURL& url) const { - if (host_matcher_rule->Evaluate(url) == - SchemeHostPortMatcherResult::kNoMatch) { + if (!MatchesHostPattern(host_pattern, url.host())) { return false; } @@ -306,7 +273,7 @@ proto::SessionInclusionRules SessionInclusionRules::ToProto() const { for (auto& rule : url_rules_) { proto::UrlRule rule_proto; rule_proto.set_rule_type(GetRuleTypeProto(rule.rule_type)); - rule_proto.set_host_matcher_rule(rule.host_matcher_rule->ToString()); + rule_proto.set_host_pattern(rule.host_pattern); rule_proto.set_path_prefix(rule.path_prefix); proto.mutable_url_rules()->Add(std::move(rule_proto)); } @@ -315,41 +282,46 @@ proto::SessionInclusionRules SessionInclusionRules::ToProto() const { } // static: -std::unique_ptr SessionInclusionRules::CreateFromProto( +std::optional SessionInclusionRules::CreateFromProto( const proto::SessionInclusionRules& proto) { if (!proto.has_origin() || !proto.has_do_include_site()) { - return nullptr; + return std::nullopt; } url::Origin origin = url::Origin::Create(GURL(proto.origin())); if (origin.opaque()) { DLOG(ERROR) << "proto origin parse error: " << origin.GetDebugString(); - return nullptr; + return std::nullopt; } - auto result = std::make_unique(origin); - result->SetIncludeSite(proto.do_include_site()); + SessionParams::Scope params; + params.include_site = proto.do_include_site(); for (const auto& rule_proto : proto.url_rules()) { - std::optional rule_type = + std::optional rule_type = GetInclusionResult(rule_proto.rule_type()); - if (!rule_type.has_value() || - !result->AddUrlRuleIfValid(*rule_type, rule_proto.host_matcher_rule(), - rule_proto.path_prefix())) { - DLOG(ERROR) << "proto rule parse error: " << "type:" - << proto::RuleType_Name(rule_proto.rule_type()) << " " - << "matcher:" << rule_proto.host_matcher_rule() << " " - << "prefix:" << rule_proto.path_prefix(); - return nullptr; + if (!rule_type.has_value()) { + return std::nullopt; } + + params.specifications.emplace_back(*rule_type, rule_proto.host_pattern(), + rule_proto.path_prefix()); } - return result; + // We use an empty refresh URL because the implicit refresh rule is already + // among those in `url_rules()`. + auto inclusion_rules_or_error = + Create(origin, std::move(params), /*refresh_endpoint=*/GURL()); + if (!inclusion_rules_or_error.has_value()) { + return std::nullopt; + } + + return std::move(*inclusion_rules_or_error); } std::string SessionInclusionRules::DebugString() const { std::string result; for (const UrlRule& rule : url_rules_) { base::StrAppend(&result, {"Type=", RuleTypeToString(rule.rule_type), - "; Domain=", rule.host_matcher_rule->ToString(), + "; Domain=", rule.host_pattern, "; Path=", rule.path_prefix, "\n"}); } return result; 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 1da7ec69bf..4fef4d74bc 100644 --- a/naiveproxy/src/net/device_bound_sessions/session_inclusion_rules.h +++ b/naiveproxy/src/net/device_bound_sessions/session_inclusion_rules.h @@ -9,9 +9,12 @@ #include #include +#include "base/types/expected.h" #include "net/base/net_export.h" #include "net/base/scheme_host_port_matcher_rule.h" #include "net/base/schemeful_site.h" +#include "net/device_bound_sessions/session_error.h" +#include "net/device_bound_sessions/session_params.h" #include "url/origin.h" namespace net::device_bound_sessions { @@ -50,13 +53,10 @@ class NET_EXPORT SessionInclusionRules final { kInclude, }; - // Initializes a default rule for the given origin. Does not do any checks - // on the origin; caller should enforce semantic checks on the origin such as - // desired schemes. - explicit SessionInclusionRules(const url::Origin& origin); - - // Default, matches nothing. - SessionInclusionRules(); + static base::expected Create( + const url::Origin& origin, + const SessionParams::Scope& scope_params, + const GURL& refresh_endpoint); SessionInclusionRules(const SessionInclusionRules& other) = delete; SessionInclusionRules& operator=(const SessionInclusionRules& other) = delete; @@ -68,6 +68,34 @@ class NET_EXPORT SessionInclusionRules final { bool operator==(const SessionInclusionRules& other) const; + // Evaluates `url` to determine whether a request to `url` may be included + // (i.e. potentially deferred on account of this DBSC session, if other + // conditions are met). + InclusionResult EvaluateRequestUrl(const GURL& url) const; + + // Returns whether a request with initiator `initiator` is allowed to trigger + // a refresh by default. + bool AllowsRefreshForInitiator(const url::Origin& initiator) const; + + bool may_include_site_for_testing() const { return may_include_site_; } + const url::Origin& origin() const { return origin_; } + + size_t num_url_rules_for_testing() const; + + proto::SessionInclusionRules ToProto() const; + static std::optional CreateFromProto( + const proto::SessionInclusionRules& proto); + + std::string DebugString() const; + + private: + struct UrlRule; + + // Initializes a default rule for the given origin. Does not do any checks + // on the origin; caller should enforce semantic checks on the origin such as + // desired schemes. + explicit SessionInclusionRules(const url::Origin& origin); + // Sets the basic include rule underlying the more specific URL rules. This // should be derived from the "include_site" param in the config. If not set // explicitly, the default is false (meaning an origin-scoped session). If @@ -78,37 +106,26 @@ class NET_EXPORT SessionInclusionRules final { void SetIncludeSite(bool include_site); // Adds a specific URL rule that includes/excludes certain URLs based on their - // host part matching `host_pattern` and the path matching `path_prefix`. Any - // matching rule takes precedence over the basic scope. Does some validity - // checks on the inputs first. The `host_pattern` must either be a full domain - // (host piece) or a pattern containing a wildcard ('*' character) in the - // most-specific (leftmost) label position followed by a dot and a non-eTLD. - // The `path_prefix` must begin with '/' and cannot contain wildcards, and - // will match paths that start with the same path components. Returns whether - // the specified rule was added. + // host part matching `host_pattern` and the path matching `path_prefix`. The + // basic scope takes precedence over any matching rule. Does some validity + // checks on the inputs first. + // + // The `host_pattern` must either be a full domain (host piece) or a pattern + // containing a wildcard ('*' character) in the most-specific (leftmost) label + // position followed by a dot and the rest of the domain. The `host_pattern` + // must also match at least one host within the scope (the origin itself for + // origin-scoped sessions, or some subdomain of the site for site-scoped + // sessions). This helps catch the most egregious configuration errors. + // + // The `path_prefix` must begin with '/' and cannot contain + // wildcards, and will match paths that start with the same path + // components. + // + // Returns whether the specified rule was added. bool AddUrlRuleIfValid(InclusionResult rule_type, const std::string& host_pattern, const std::string& path_prefix); - // Evaluates `url` to determine whether a request to `url` may be included - // (i.e. potentially deferred on account of this DBSC session, if other - // conditions are met). - InclusionResult EvaluateRequestUrl(const GURL& url) const; - - bool may_include_site_for_testing() const { return may_include_site_; } - const url::Origin& origin() const { return origin_; } - - size_t num_url_rules_for_testing() const; - - proto::SessionInclusionRules ToProto() const; - static std::unique_ptr CreateFromProto( - const proto::SessionInclusionRules& proto); - - std::string DebugString() const; - - private: - struct UrlRule; - // The origin that created/set the session that this applies to. By default, // sessions are origin-scoped unless specified otherwise. url::Origin origin_; diff --git a/naiveproxy/src/net/device_bound_sessions/session_json_utils.cc b/naiveproxy/src/net/device_bound_sessions/session_json_utils.cc index a0018d4c27..556dc37525 100644 --- a/naiveproxy/src/net/device_bound_sessions/session_json_utils.cc +++ b/naiveproxy/src/net/device_bound_sessions/session_json_utils.cc @@ -5,12 +5,14 @@ #include "net/device_bound_sessions/session_json_utils.h" #include "base/json/json_reader.h" +#include "base/types/expected_macros.h" namespace net::device_bound_sessions { namespace { -SessionParams::Scope ParseScope(const base::Value::Dict& scope_dict) { +base::expected ParseScope( + const base::Value::Dict& scope_dict) { SessionParams::Scope scope; std::optional include_site = scope_dict.FindBool("include_site"); @@ -26,48 +28,58 @@ SessionParams::Scope ParseScope(const base::Value::Dict& scope_dict) { for (const auto& specification : *specifications_list) { const base::Value::Dict* specification_dict = specification.GetIfDict(); if (!specification_dict) { - continue; + return base::unexpected( + SessionError{SessionError::ErrorType::kInvalidScopeRule}); } 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}); - } + if (!type || !domain || domain->empty() || !path || path->empty()) { + return base::unexpected( + SessionError{SessionError::ErrorType::kInvalidScopeRule}); } + SessionParams::Scope::Specification::Type rule_type = + SessionParams::Scope::Specification::Type::kInclude; + if (*type == "include") { + rule_type = SessionParams::Scope::Specification::Type::kInclude; + } else if (*type == "exclude") { + rule_type = SessionParams::Scope::Specification::Type::kExclude; + } else { + return base::unexpected( + SessionError{SessionError::ErrorType::kInvalidScopeRule}); + } + + scope.specifications.push_back( + SessionParams::Scope::Specification{rule_type, *domain, *path}); } return scope; } -std::vector ParseCredentials( - const base::Value::List& credentials_list) { +base::expected, SessionError> +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; + return base::unexpected( + SessionError{SessionError::ErrorType::kInvalidCredentials}); } const std::string* type = credential_dict->FindString("type"); if (!type || *type != "cookie") { - continue; + return base::unexpected( + SessionError{SessionError::ErrorType::kInvalidCredentials}); } 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}); + if (!name || !attributes) { + return base::unexpected( + SessionError{SessionError::ErrorType::kInvalidCredentials}); } + + cookie_credentials.push_back(SessionParams::Credential{*name, *attributes}); } return cookie_credentials; @@ -78,59 +90,71 @@ std::vector ParseCredentials( base::expected ParseSessionInstructionJson( GURL fetcher_url, unexportable_keys::UnexportableKeyId key_id, + std::optional expected_session_id, 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. - - net::SchemefulSite fetcher_site(fetcher_url); std::optional maybe_root = base::JSONReader::ReadDict( response_json, base::JSON_PARSE_RFC, /*max_depth=*/5u); if (!maybe_root) { return base::unexpected( - SessionError{SessionError::ErrorType::kInvalidConfigJson, fetcher_site, - /*session_id=*/std::nullopt}); + SessionError{SessionError::ErrorType::kInvalidConfigJson}); } - 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 base::unexpected( - SessionError{SessionError::ErrorType::kInvalidSessionId, fetcher_site, - /*session_id=*/std::nullopt}); + SessionError{SessionError::ErrorType::kInvalidSessionId}); + } + + if (expected_session_id.has_value() && *expected_session_id != *session_id) { + return base::unexpected( + SessionError{SessionError::ErrorType::kMismatchedSessionId}); } std::optional continue_value = maybe_root->FindBool("continue"); if (continue_value.has_value() && *continue_value == false) { return base::unexpected( - SessionError{SessionError::ErrorType::kServerRequestedTermination, - fetcher_site, *session_id}); + SessionError{SessionError::ErrorType::kServerRequestedTermination}); } + base::Value::Dict* scope_dict = maybe_root->FindDict("scope"); + if (!scope_dict) { + return base::unexpected( + SessionError{SessionError::ErrorType::kMissingScope}); + } + ASSIGN_OR_RETURN(SessionParams::Scope scope, ParseScope(*scope_dict)); + 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); + ASSIGN_OR_RETURN(credentials, ParseCredentials(*credentials_list)); } if (credentials.empty()) { return base::unexpected( - SessionError{SessionError::ErrorType::kInvalidCredentials, fetcher_site, - /*session_id=*/std::nullopt}); + SessionError{SessionError::ErrorType::kNoCredentials}); } - return SessionParams( - *session_id, fetcher_url, refresh_url ? *refresh_url : "", - scope_dict ? ParseScope(*scope_dict) : SessionParams::Scope{}, - std::move(credentials), key_id); + std::vector allowed_refresh_initiators; + if (base::Value::List* initiator_list = + maybe_root->FindList("allowed_refresh_initiators"); + initiator_list) { + for (base::Value& initiator : *initiator_list) { + if (!initiator.is_string()) { + return base::unexpected( + SessionError{SessionError::ErrorType::kInvalidRefreshInitiators}); + } + + allowed_refresh_initiators.emplace_back(std::move(initiator.GetString())); + } + } + + return SessionParams(*session_id, fetcher_url, + refresh_url ? *refresh_url : "", std::move(scope), + std::move(credentials), key_id, + std::move(allowed_refresh_initiators)); } } // 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 index 4ef9752728..d550895866 100644 --- a/naiveproxy/src/net/device_bound_sessions/session_json_utils.h +++ b/naiveproxy/src/net/device_bound_sessions/session_json_utils.h @@ -26,6 +26,7 @@ namespace net::device_bound_sessions { base::expected ParseSessionInstructionJson( GURL fetcher_url, unexportable_keys::UnexportableKeyId key_id, + std::optional expected_session_id, std::string_view response_json); } // namespace net::device_bound_sessions diff --git a/naiveproxy/src/net/device_bound_sessions/session_params.cc b/naiveproxy/src/net/device_bound_sessions/session_params.cc index 277dffab60..8dcc4ad319 100644 --- a/naiveproxy/src/net/device_bound_sessions/session_params.cc +++ b/naiveproxy/src/net/device_bound_sessions/session_params.cc @@ -6,18 +6,21 @@ namespace net::device_bound_sessions { -SessionParams::SessionParams(std::string id, - GURL fetcher_url, - std::string refresh_url, - Scope scope, - std::vector creds, - unexportable_keys::UnexportableKeyId key_id) +SessionParams::SessionParams( + std::string id, + GURL fetcher_url, + std::string refresh_url, + Scope scope, + std::vector creds, + unexportable_keys::UnexportableKeyId key_id, + std::vector allowed_refresh_initiators) : session_id(std::move(id)), fetcher_url(std::move(fetcher_url)), refresh_url(std::move(refresh_url)), scope(std::move(scope)), credentials(std::move(creds)), - key_id(std::move(key_id)) {} + key_id(std::move(key_id)), + allowed_refresh_initiators(std::move(allowed_refresh_initiators)) {} SessionParams::SessionParams(SessionParams&& other) noexcept = default; diff --git a/naiveproxy/src/net/device_bound_sessions/session_params.h b/naiveproxy/src/net/device_bound_sessions/session_params.h index 6b5d97188b..9f9d076cd5 100644 --- a/naiveproxy/src/net/device_bound_sessions/session_params.h +++ b/naiveproxy/src/net/device_bound_sessions/session_params.h @@ -53,7 +53,8 @@ struct NET_EXPORT SessionParams final { std::string refresh_url, Scope scope, std::vector creds, - unexportable_keys::UnexportableKeyId key_id); + unexportable_keys::UnexportableKeyId key_id, + std::vector allowed_refresh_initiators); SessionParams(SessionParams&& other) noexcept; SessionParams& operator=(SessionParams&& other) noexcept; @@ -67,6 +68,7 @@ struct NET_EXPORT SessionParams final { Scope scope; std::vector credentials; unexportable_keys::UnexportableKeyId key_id; + std::vector allowed_refresh_initiators; }; } // 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 index bfaca63f81..9b5fd7a8fa 100644 --- a/naiveproxy/src/net/device_bound_sessions/session_service.h +++ b/naiveproxy/src/net/device_bound_sessions/session_service.h @@ -10,6 +10,7 @@ #include "base/functional/callback_forward.h" #include "base/functional/callback_helpers.h" #include "net/base/net_export.h" +#include "net/device_bound_sessions/deletion_reason.h" #include "net/device_bound_sessions/registration_fetcher_param.h" #include "net/device_bound_sessions/session.h" #include "net/device_bound_sessions/session_access.h" @@ -39,7 +40,7 @@ class NET_EXPORT SessionService { kInitializedService, // Service is now initialized, refresh may still be // needed. kUnreachable, // Refresh endpoint was unreachable. - kServerError, // Refresh endpoint eserved a transient error. + kServerError, // Refresh endpoint served a transient error. kQuotaExceeded, // Refresh quota exceeded. kFatalError, // Refresh failed and session was terminated. No // further refresh needed. @@ -138,16 +139,17 @@ class NET_EXPORT SessionService { virtual void GetAllSessionsAsync( base::OnceCallback&)> callback) = 0; - // Delete the session on `site` with `id`, notifying + // Delete the session matching `session_key`, notifying // `per_request_callback` about any deletions. virtual void DeleteSessionAndNotify( - const SchemefulSite& site, - const Session::Id& id, + DeletionReason reason, + const SessionKey& session_key, SessionService::OnAccessCallback per_request_callback) = 0; // Delete all sessions that match the filtering arguments. See // `device_bound_sessions.mojom` for details on the filtering logic. virtual void DeleteAllSessions( + DeletionReason reason, std::optional created_after_time, std::optional created_before_time, base::RepeatingCallback fetcher = + RegistrationFetcher::CreateFetcher( + request_params, key_service_.get(), context_.get(), isolation_info, + net_log_source_for_registration, original_request_initiator); + RegistrationFetcher* fetcher_raw = fetcher.get(); + registration_fetchers_.insert(std::move(fetcher)); + fetcher_raw->StartCreateTokenAndFetch( + request_params, supported_algos, base::BindOnce(&SessionServiceImpl::OnRegistrationComplete, weak_factory_.GetWeakPtr(), std::move(on_access_callback))); @@ -174,9 +183,10 @@ void SessionServiceImpl::OnLoadSessionsComplete( void SessionServiceImpl::OnRegistrationComplete( OnAccessCallback on_access_callback, + RegistrationFetcher* fetcher, base::expected params_or_error) { SessionError::ErrorType result = OnRegistrationCompleteInternal( - std::move(on_access_callback), std::move(params_or_error)); + std::move(on_access_callback), fetcher, std::move(params_or_error)); base::UmaHistogramEnumeration("Net.DeviceBoundSessions.RegistrationResult", result); } @@ -196,7 +206,8 @@ SessionServiceImpl::GetSessionsForSite(const SchemefulSite& site) { if (now >= curit->second->expiry_date()) { // Since this deletion is not due to a request, we do not need to // provide a per-request callback here. - DeleteSessionAndNotifyInternal(curit, base::NullCallback()); + DeleteSessionAndNotifyInternal(DeletionReason::kExpired, curit, + base::NullCallback()); } else { curit->second->RecordAccess(); } @@ -220,8 +231,8 @@ std::optional SessionServiceImpl::ShouldDefer( request->device_bound_session_deferrals(); for (const auto& [_, session] : GetSessionsForSite(site)) { if (session->ShouldDeferRequest(request, first_party_set_metadata)) { - auto previous_deferrals_it = - previous_deferrals.find({site, session->id()}); + SessionKey session_key{site, session->id()}; + auto previous_deferrals_it = previous_deferrals.find(session_key); if (previous_deferrals_it != previous_deferrals.end()) { debug_header_builder.AddSkippedSession(previous_deferrals_it->first, previous_deferrals_it->second); @@ -229,7 +240,8 @@ std::optional SessionServiceImpl::ShouldDefer( } NotifySessionAccess(request->device_bound_session_access_callback(), - SessionAccess::AccessType::kUpdate, site, *session); + SessionAccess::AccessType::kUpdate, session_key, + *session); return DeferralParams(session->id()); } } @@ -259,35 +271,37 @@ void SessionServiceImpl::DeferRequestForRefresh( return; } - Session::Id session_id = *deferral.session_id; + SessionKey session_key{SchemefulSite(request->url()), *deferral.session_id}; // For the first deferring request, create a new vector and add the request. - auto [it, inserted] = deferred_requests_.try_emplace(session_id); + auto [it, inserted] = deferred_requests_.try_emplace(session_key.id); // Add the request to the deferred list. it->second.emplace_back(request, std::move(callback)); - SchemefulSite site(request->url()); - auto* session = GetSession(site, session_id); + auto* session = GetSession(session_key); + CHECK(session, base::NotFatalUntil::M147); + // TODO(crbug.com/417770933): Remove this block. if (!session) { - // If we can't find the session, clear the session_id key in the map + // If we can't find the session, clear the `session_key` in the map // and continue all related requests. We can call this a fatal error // because the session has already been deleted. - UnblockDeferredRequests(session_id, RefreshResult::kFatalError); + UnblockDeferredRequests(session_key, RefreshResult::kFatalError); return; } // Notify the request that it has been deferred for refreshed cookies. NotifySessionAccess(request->device_bound_session_access_callback(), - SessionAccess::AccessType::kUpdate, site, *session); + SessionAccess::AccessType::kUpdate, session_key, + *session); if (!inserted) { return; } - if (RefreshQuotaExceeded(site)) { - UnblockDeferredRequests(session_id, RefreshResult::kQuotaExceeded); + if (RefreshQuotaExceeded(session_key.site)) { + UnblockDeferredRequests(session_key, RefreshResult::kQuotaExceeded); return; } if (session->ShouldBackoff()) { - UnblockDeferredRequests(session_id, RefreshResult::kUnreachable); + UnblockDeferredRequests(session_key, RefreshResult::kUnreachable); return; } @@ -296,32 +310,32 @@ void SessionServiceImpl::DeferRequestForRefresh( if (key_id.error() == unexportable_keys::ServiceError::kKeyNotReady) { // Unwrap key and then try to refresh session_store_->RestoreSessionBindingKey( - site, session_id, + session_key, base::BindOnce(&SessionServiceImpl::OnSessionKeyRestored, - weak_factory_.GetWeakPtr(), request, site, session_id, + weak_factory_.GetWeakPtr(), request, session_key, request->device_bound_session_access_callback())); } else { - UnblockDeferredRequests(session_id, RefreshResult::kFatalError); - DeleteSessionAndNotify(site, session_id, + UnblockDeferredRequests(session_key, RefreshResult::kFatalError); + DeleteSessionAndNotify(DeletionReason::kFailedToRestoreKey, session_key, request->device_bound_session_access_callback()); } return; } - RefreshSessionInternal(request, site, session, *key_id); + RefreshSessionInternal(request, session_key, session, *key_id); } void SessionServiceImpl::OnRefreshRequestCompletion( OnAccessCallback on_access_callback, - SchemefulSite site, - Session::Id session_id, + SessionKey session_key, + RegistrationFetcher* fetcher, base::expected params_or_error) { SessionError::ErrorType result = OnRefreshRequestCompletionInternal( - std::move(on_access_callback), site, session_id, + std::move(on_access_callback), session_key, fetcher, std::move(params_or_error)); - Session* session = GetSession(site, session_id); + Session* session = GetSession(session_key); if (session) { session->InformOfRefreshResult(result); } @@ -332,9 +346,9 @@ void SessionServiceImpl::OnRefreshRequestCompletion( // Continue or restart all deferred requests for the session and remove the // session_id key in the map. -void SessionServiceImpl::UnblockDeferredRequests(const Session::Id& session_id, +void SessionServiceImpl::UnblockDeferredRequests(const SessionKey& session_key, RefreshResult result) { - auto it = deferred_requests_.find(session_id); + auto it = deferred_requests_.find(session_key.id); if (it == deferred_requests_.end()) { return; } @@ -361,7 +375,8 @@ void SessionServiceImpl::SetChallengeForBoundSession( for (const auto& [_, session] : GetSessionsForSite(site)) { if (session->id().value() == param.session_id()) { NotifySessionAccess(on_access_callback, - SessionAccess::AccessType::kUpdate, site, *session); + SessionAccess::AccessType::kUpdate, + SessionKey{site, session->id()}, *session); session->set_cached_challenge(param.challenge()); return; } @@ -385,20 +400,19 @@ void SessionServiceImpl::GetAllSessionsAsync( } void SessionServiceImpl::DeleteSessionAndNotify( - const SchemefulSite& site, - const Session::Id& id, + DeletionReason reason, + const SessionKey& session_key, SessionService::OnAccessCallback per_request_callback) { - auto it = unpartitioned_sessions_.find(SessionKey{site, id}); + auto it = unpartitioned_sessions_.find(session_key); if (it == unpartitioned_sessions_.end()) { return; } - DeleteSessionAndNotifyInternal(it, per_request_callback); + DeleteSessionAndNotifyInternal(reason, it, per_request_callback); } -Session* SessionServiceImpl::GetSession(const SchemefulSite& site, - const Session::Id& session_id) const { - auto it = unpartitioned_sessions_.find(SessionKey{site, session_id}); +Session* SessionServiceImpl::GetSession(const SessionKey& session_key) const { + auto it = unpartitioned_sessions_.find(session_key); if (it != unpartitioned_sessions_.end()) { return it->second.get(); } @@ -416,6 +430,7 @@ void SessionServiceImpl::AddSession(const SchemefulSite& site, } void SessionServiceImpl::DeleteAllSessions( + DeletionReason reason, std::optional created_after_time, std::optional created_before_time, base::RepeatingCallback @@ -429,7 +444,7 @@ void SessionServiceImpl::DeleteAllSessions( if (SessionMatchesFilter(curit->first.site, *curit->second, created_after_time, created_before_time, origin_and_site_matcher)) { - DeleteSessionAndNotifyInternal(curit, base::NullCallback()); + DeleteSessionAndNotifyInternal(reason, curit, base::NullCallback()); } } @@ -448,14 +463,18 @@ base::ScopedClosureRunner SessionServiceImpl::AddObserver( } void SessionServiceImpl::DeleteSessionAndNotifyInternal( + DeletionReason reason, SessionServiceImpl::SessionsMap::iterator it, SessionService::OnAccessCallback per_request_callback) { + base::UmaHistogramEnumeration("Net.DeviceBoundSessions.DeletionReason", + reason); + if (session_store_) { session_store_->DeleteSession(it->first); } NotifySessionAccess(per_request_callback, - SessionAccess::AccessType::kTermination, it->first.site, + SessionAccess::AccessType::kTermination, it->first, *it->second); unpartitioned_sessions_.erase(it); @@ -464,9 +483,9 @@ void SessionServiceImpl::DeleteSessionAndNotifyInternal( void SessionServiceImpl::NotifySessionAccess( SessionService::OnAccessCallback per_request_callback, SessionAccess::AccessType access_type, - const SchemefulSite& site, + const SessionKey& session_key, const Session& session) { - SessionAccess access{access_type, {site, session.id()}}; + SessionAccess access{access_type, session_key}; if (access_type == SessionAccess::AccessType::kTermination) { access.cookies.reserve(session.cookies().size()); @@ -479,7 +498,7 @@ void SessionServiceImpl::NotifySessionAccess( per_request_callback.Run(access); } - auto observers_it = observers_by_site_.find(site); + auto observers_it = observers_by_site_.find(session_key.site); if (observers_it == observers_by_site_.end()) { return; } @@ -514,20 +533,14 @@ void SessionServiceImpl::RemoveObserver(net::SchemefulSite site, SessionError::ErrorType SessionServiceImpl::OnRegistrationCompleteInternal( OnAccessCallback on_access_callback, + RegistrationFetcher* fetcher, base::expected params_or_error) { + RemoveFetcher(fetcher); + if (!params_or_error.has_value()) { - // There was a failure attempting to register. This registration - // request could be used to clean up an existing session if the - // server returned `"continue": false` in the JSON. In that case, we - // need to delete the session. In all other cases, we failed to - // create a new session, so there's nothing to clean up. - const SessionError& error = params_or_error.error(); - if (error.type == SessionError::ErrorType::kServerRequestedTermination && - error.session_id.has_value()) { - Session::Id session_id(*error.session_id); - DeleteSessionAndNotify(error.site, session_id, on_access_callback); - } - return error.type; + // We failed to create a new session, so there's nothing to clean + // up. + return params_or_error.error().type; } const SessionParams& params = *params_or_error; @@ -541,67 +554,59 @@ SessionError::ErrorType SessionServiceImpl::OnRegistrationCompleteInternal( } CHECK(*session_or_error); NotifySessionAccess(on_access_callback, SessionAccess::AccessType::kCreation, - site, **session_or_error); + SessionKey{site, (*session_or_error)->id()}, + **session_or_error); AddSession(site, std::move(*session_or_error)); return SessionError::ErrorType::kSuccess; } SessionError::ErrorType SessionServiceImpl::OnRefreshRequestCompletionInternal( OnAccessCallback on_access_callback, - const SchemefulSite& site, - const Session::Id& session_id, + const SessionKey& session_key, + RegistrationFetcher* fetcher, base::expected params_or_error) { + RemoveFetcher(fetcher); + // If refresh succeeded: - // 1. update the session by adding a new session and deleting the old one + // 1. update the session by adding a new session, replacing the old one // 2. restart the deferred requests. // - // Note that we notified `on_access_callback` about `session_id` already, so - // we only need to notify the callback about other sessions. - // - // TODO(crbug.com/353766139): check if add/delete update will cause some race, - // for example, if the the old session_id is still in use while deleting it. - // Is it service's responsibility to keep the session_id same with the one in - // received JSON which parsed as result_result->params? + // Note that we notified `on_access_callback` about `session_key.id` already, + // so we only need to notify the callback about other sessions. if (params_or_error.has_value()) { auto session_or_error = Session::CreateIfValid(*params_or_error); if (!session_or_error.has_value()) { // New parameters are invalid, terminate the session. - DeleteSessionAndNotify(site, session_id, on_access_callback); - UnblockDeferredRequests(session_id, RefreshResult::kFatalError); + DeleteSessionAndNotify(DeletionReason::kInvalidSessionParams, session_key, + on_access_callback); + UnblockDeferredRequests(session_key, RefreshResult::kFatalError); return session_or_error.error().type; } std::unique_ptr new_session = std::move(*session_or_error); CHECK(new_session); + CHECK_EQ(new_session->id(), session_key.id); - // Delete old session. - DeleteSessionAndNotify(site, session_id, - new_session->id() == session_id - ? base::NullCallback() - : on_access_callback); - // Add the new session. SchemefulSite new_site( url::Origin::Create(GURL(params_or_error->fetcher_url))); - if (new_session->id() != session_id) { - NotifySessionAccess(on_access_callback, - SessionAccess::AccessType::kCreation, new_site, - *new_session); + if (new_session->id() != session_key.id) { + NotifySessionAccess( + on_access_callback, SessionAccess::AccessType::kCreation, + SessionKey{new_site, new_session->id()}, *new_session); } AddSession(new_site, std::move(new_session)); // The session has been refreshed, restart the request. - UnblockDeferredRequests(session_id, RefreshResult::kRefreshed); + UnblockDeferredRequests(session_key, RefreshResult::kRefreshed); } else if (const SessionError& error = params_or_error.error(); error.IsFatal()) { - Session::Id session_to_terminate = - error.session_id ? Session::Id(*error.session_id) : session_id; - DeleteSessionAndNotify(error.site, session_to_terminate, + DeleteSessionAndNotify(DeletionReason::kRefreshFatalError, session_key, on_access_callback); - UnblockDeferredRequests(session_id, RefreshResult::kFatalError); + UnblockDeferredRequests(session_key, RefreshResult::kFatalError); } else { // Transient error, unblock the request without cookies. - UnblockDeferredRequests(session_id, error.IsServerError() - ? RefreshResult::kServerError - : RefreshResult::kUnreachable); + UnblockDeferredRequests(session_key, error.IsServerError() + ? RefreshResult::kServerError + : RefreshResult::kUnreachable); } return params_or_error.has_value() ? SessionError::ErrorType::kSuccess @@ -610,30 +615,30 @@ SessionError::ErrorType SessionServiceImpl::OnRefreshRequestCompletionInternal( void SessionServiceImpl::OnSessionKeyRestored( URLRequest* request, - const SchemefulSite& site, - const Session::Id& session_id, + const SessionKey& session_key, OnAccessCallback on_access_callback, Session::KeyIdOrError key_id_or_error) { if (!key_id_or_error.has_value()) { - UnblockDeferredRequests(session_id, RefreshResult::kFatalError); - DeleteSessionAndNotify(site, session_id, on_access_callback); + UnblockDeferredRequests(session_key, RefreshResult::kFatalError); + DeleteSessionAndNotify(DeletionReason::kFailedToUnwrapKey, session_key, + on_access_callback); return; } - auto* session = GetSession(site, session_id); + auto* session = GetSession(session_key); if (!session) { - UnblockDeferredRequests(session_id, RefreshResult::kFatalError); + UnblockDeferredRequests(session_key, RefreshResult::kFatalError); return; } session->set_unexportable_key_id(key_id_or_error); - RefreshSessionInternal(request, site, session, *key_id_or_error); + RefreshSessionInternal(request, session_key, session, *key_id_or_error); } void SessionServiceImpl::RefreshSessionInternal( URLRequest* request, - const SchemefulSite& site, + const SessionKey& session_key, Session* session, unexportable_keys::UnexportableKeyId key_id) { net::NetLogSource net_log_source_for_refresh = net::NetLogSource( @@ -641,16 +646,24 @@ void SessionServiceImpl::RefreshSessionInternal( request->net_log().AddEventReferencingSource( net::NetLogEventType::DBSC_REFRESH_REQUEST, net_log_source_for_refresh); - refresh_times_[site].push_back(base::TimeTicks::Now()); + refresh_times_[session_key.site].push_back(base::TimeTicks::Now()); + + auto registration_param = + RegistrationRequestParam::CreateForRefresh(*session); auto callback = base::BindOnce( &SessionServiceImpl::OnRefreshRequestCompletion, weak_factory_.GetWeakPtr(), - request->device_bound_session_access_callback(), site, session->id()); - RegistrationFetcher::StartFetchWithExistingKey( - RegistrationRequestParam::CreateForRefresh(*session), key_service_.get(), - context_.get(), request->isolation_info(), net_log_source_for_refresh, - request->initiator(), std::move(callback), key_id); + request->device_bound_session_access_callback(), session_key); + std::unique_ptr fetcher = + RegistrationFetcher::CreateFetcher( + registration_param, key_service_.get(), context_.get(), + request->isolation_info(), net_log_source_for_refresh, + request->initiator()); + RegistrationFetcher* fetcher_raw = fetcher.get(); + registration_fetchers_.insert(std::move(fetcher)); + fetcher_raw->StartFetchWithExistingKey(registration_param, key_id, + std::move(callback)); } bool SessionServiceImpl::RefreshQuotaExceeded(const SchemefulSite& site) { @@ -678,4 +691,15 @@ bool SessionServiceImpl::RefreshQuotaExceeded(const SchemefulSite& site) { return refresh_count >= kRefreshQuota; } +void SessionServiceImpl::RemoveFetcher(RegistrationFetcher* fetcher) { + if (!fetcher) { + return; + } + auto it = registration_fetchers_.find(fetcher); + if (it == registration_fetchers_.end()) { + return; + } + registration_fetchers_.erase(it); +} + } // namespace net::device_bound_sessions diff --git a/naiveproxy/src/net/device_bound_sessions/session_service_impl.h b/naiveproxy/src/net/device_bound_sessions/session_service_impl.h index cf7ba44273..b1965ec8b0 100644 --- a/naiveproxy/src/net/device_bound_sessions/session_service_impl.h +++ b/naiveproxy/src/net/device_bound_sessions/session_service_impl.h @@ -87,10 +87,11 @@ class NET_EXPORT SessionServiceImpl : public SessionService { base::OnceCallback&)> callback) override; void DeleteSessionAndNotify( - const SchemefulSite& site, - const Session::Id& id, + DeletionReason reason, + const SessionKey& session_key, SessionService::OnAccessCallback per_request_callback) override; void DeleteAllSessions( + DeletionReason reason, std::optional created_after_time, std::optional created_before_time, base::RepeatingCallback callback) override; - Session* GetSession(const SchemefulSite& site, - const Session::Id& session_id) const; + Session* GetSession(const SessionKey& session_key) const; private: friend class SessionServiceImplWithStoreTest; @@ -133,15 +133,16 @@ class NET_EXPORT SessionServiceImpl : public SessionService { void OnRegistrationComplete( OnAccessCallback on_access_callback, + RegistrationFetcher* fetcher, base::expected params_or_error); void OnRefreshRequestCompletion( OnAccessCallback on_access_callback, - SchemefulSite site, - Session::Id session_id, + SessionKey session_key, + RegistrationFetcher* fetcher, base::expected params_or_error); void AddSession(const SchemefulSite& site, std::unique_ptr session); - void UnblockDeferredRequests(const Session::Id& session_id, + void UnblockDeferredRequests(const SessionKey& session_key, RefreshResult result); // Get all the unexpired sessions for a given site. This also removes @@ -153,6 +154,7 @@ class NET_EXPORT SessionServiceImpl : public SessionService { // from `session_store_` and notifies any observers (including // `per_request_callback`) about the termination. void DeleteSessionAndNotifyInternal( + DeletionReason reason, SessionsMap::iterator it, SessionService::OnAccessCallback per_request_callback); @@ -162,7 +164,7 @@ class NET_EXPORT SessionServiceImpl : public SessionService { void NotifySessionAccess( SessionService::OnAccessCallback per_request_callback, SessionAccess::AccessType access_type, - const SchemefulSite& site, + const SessionKey& session_key, const Session& session); // Remove an observer by site and pointer. @@ -171,27 +173,27 @@ class NET_EXPORT SessionServiceImpl : public SessionService { // Helper function encapsulating the processing of registration SessionError::ErrorType OnRegistrationCompleteInternal( OnAccessCallback on_access_callback, + RegistrationFetcher* fetcher, base::expected params_or_error); // Helper function encapsulating the processing of refresh SessionError::ErrorType OnRefreshRequestCompletionInternal( OnAccessCallback on_access_callback, - const SchemefulSite& site, - const Session::Id& session_id, + const SessionKey& session_key, + RegistrationFetcher* fetcher, base::expected params_or_error); // Callback after unwrapping a session key. `on_access_callback` is // used to notify the browser that this request led to usage of a // session. void OnSessionKeyRestored(URLRequest* request, - const SchemefulSite& site, - const Session::Id& session_id, + const SessionKey& session_key, OnAccessCallback on_access_callback, Session::KeyIdOrError key_id_or_error); // Helper function for starting a refresh void RefreshSessionInternal(URLRequest* request, - const SchemefulSite& site, + const SessionKey& session_key, Session* session, unexportable_keys::UnexportableKeyId key_id); @@ -202,6 +204,10 @@ class NET_EXPORT SessionServiceImpl : public SessionService { // applied, but did not due to error conditions. void AddDebugHeader(URLRequest* request); + // Removes `fetcher` from the set of active fetchers. If `fetcher` is + // null, does nothing. + void RemoveFetcher(RegistrationFetcher* fetcher); + // Whether we are waiting on the initial load of saved sessions to complete. bool pending_initialization_ = false; // Functions to call once initialization completes. @@ -230,6 +236,10 @@ class NET_EXPORT SessionServiceImpl : public SessionService { // session parameter changes, we enforce refresh quota for a site. std::map> refresh_times_; + // Holds all currently live registration fetchers. + std::set, base::UniquePtrComparator> + registration_fetchers_; + base::WeakPtrFactory weak_factory_{this}; }; diff --git a/naiveproxy/src/net/device_bound_sessions/session_store.h b/naiveproxy/src/net/device_bound_sessions/session_store.h index 56efd95c48..b3a454b55f 100644 --- a/naiveproxy/src/net/device_bound_sessions/session_store.h +++ b/naiveproxy/src/net/device_bound_sessions/session_store.h @@ -52,8 +52,7 @@ class NET_EXPORT SessionStore { using RestoreSessionBindingKeyCallback = base::OnceCallback)>; virtual void RestoreSessionBindingKey( - const SchemefulSite& site, - const Session::Id& session_id, + const SessionKey& session_key, RestoreSessionBindingKeyCallback callback) = 0; protected: diff --git a/naiveproxy/src/net/device_bound_sessions/session_store_impl.cc b/naiveproxy/src/net/device_bound_sessions/session_store_impl.cc index dfe5786194..777842bcaf 100644 --- a/naiveproxy/src/net/device_bound_sessions/session_store_impl.cc +++ b/naiveproxy/src/net/device_bound_sessions/session_store_impl.cc @@ -271,8 +271,7 @@ SessionStore::SessionsMap SessionStoreImpl::GetAllSessions() const { } void SessionStoreImpl::RestoreSessionBindingKey( - const SchemefulSite& site, - const Session::Id& session_id, + const SessionKey& session_key, RestoreSessionBindingKeyCallback callback) { auto key_id_or_error = base::unexpected(ServiceError::kKeyNotFound); if (db_status_ != DBStatus::kSuccess) { @@ -282,8 +281,8 @@ void SessionStoreImpl::RestoreSessionBindingKey( // Retrieve the session's persisted binding key and unwrap it. proto::SiteSessions site_proto; - if (session_data_->TryGetData(site.Serialize(), &site_proto)) { - auto it = site_proto.sessions().find(*session_id); + if (session_data_->TryGetData(session_key.site.Serialize(), &site_proto)) { + auto it = site_proto.sessions().find(*session_key.id); if (it != site_proto.sessions().end()) { // Unwrap the binding key asynchronously. std::vector wrapped_key(it->second.wrapped_key().begin(), diff --git a/naiveproxy/src/net/device_bound_sessions/session_store_impl.h b/naiveproxy/src/net/device_bound_sessions/session_store_impl.h index 92bf9a8c9f..80db666782 100644 --- a/naiveproxy/src/net/device_bound_sessions/session_store_impl.h +++ b/naiveproxy/src/net/device_bound_sessions/session_store_impl.h @@ -62,8 +62,7 @@ class NET_EXPORT SessionStoreImpl : public SessionStore { void DeleteSession(const SessionKey& key) override; SessionsMap GetAllSessions() const override; void RestoreSessionBindingKey( - const SchemefulSite& site, - const Session::Id& session_id, + const SessionKey& session_key, RestoreSessionBindingKeyCallback callback) override; DBStatus db_status() const { return db_status_; } @@ -78,6 +77,8 @@ class NET_EXPORT SessionStoreImpl : public SessionStore { PruneLoadedEntryWithInvalidSession); FRIEND_TEST_ALL_PREFIXES(SessionStoreImplTest, PruneLoadedEntryWithSessionMissingWrappedKey); + FRIEND_TEST_ALL_PREFIXES(SessionStoreImplTest, + PruneLoadedEntryWithInvalidRefreshInitiator); void OnDatabaseLoaded(LoadSessionsCallback callback, base::ElapsedTimer timer, diff --git a/naiveproxy/src/net/device_bound_sessions/test_support.cc b/naiveproxy/src/net/device_bound_sessions/test_support.cc index 7aa76e764f..99e18a2a57 100644 --- a/naiveproxy/src/net/device_bound_sessions/test_support.cc +++ b/naiveproxy/src/net/device_bound_sessions/test_support.cc @@ -17,13 +17,13 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/values.h" +#include "crypto/evp.h" #include "crypto/signature_verifier.h" #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/boringssl/src/include/openssl/base.h" #include "third_party/boringssl/src/include/openssl/bn.h" -#include "third_party/boringssl/src/include/openssl/bytestring.h" #include "third_party/boringssl/src/include/openssl/curve25519.h" #include "third_party/boringssl/src/include/openssl/ec_key.h" #include "third_party/boringssl/src/include/openssl/ecdsa.h" @@ -97,7 +97,6 @@ std::unique_ptr RequestHandler( .Set("refresh_url", base_url.Resolve("/dbsc_refresh_session").spec()) .Set("scope", base::Value::Dict() - .Set("include_site", true) .Set("scope_specification", base::Value::List().Append( base::Value::Dict() @@ -177,22 +176,7 @@ std::optional> Es256JwkToSpki( return std::nullopt; } - bssl::ScopedCBB cbb; - if (!CBB_init(cbb.get(), 0) || - !EVP_marshal_public_key(cbb.get(), pkey.get())) { - return std::nullopt; - } - - uint8_t* data; - size_t len; - if (!CBB_finish(cbb.get(), &data, &len)) { - return std::nullopt; - } - - bssl::UniquePtr delete_der(data); - // SAFETY: `CBB_finish` uses a C-style API. - auto spki_span = UNSAFE_BUFFERS(base::span(data, len)); - return base::ToVector(spki_span); + return crypto::evp::PublicKeyToBytes(pkey.get()); } std::optional> RawSigToDerSig( @@ -354,7 +338,8 @@ ScopedTestRegistrationFetcher ScopedTestRegistrationFetcher::CreateWithSuccess( return base::expected(SessionParams( session_id, GURL(refresh_url_string), refresh_url_string, std::move(scope), std::move(cookie_credentials), - unexportable_keys::UnexportableKeyId())); + unexportable_keys::UnexportableKeyId(), + /*allowed_refresh_initiators=*/{})); }, std::string(session_id), std::string(refresh_url_string), std::string(origin_string))); @@ -366,9 +351,8 @@ ScopedTestRegistrationFetcher ScopedTestRegistrationFetcher::CreateWithFailure( std::string_view refresh_url_string) { return ScopedTestRegistrationFetcher(base::BindRepeating( [](SessionError::ErrorType error_type, const GURL& refresh_url) { - return base::expected(base::unexpected( - SessionError{error_type, net::SchemefulSite(refresh_url), - /*session_id=*/std::nullopt})); + return base::expected( + base::unexpected(SessionError{error_type})); }, error_type, GURL(refresh_url_string))); } @@ -382,8 +366,7 @@ ScopedTestRegistrationFetcher::CreateWithTermination( [](const std::string& session_id, const std::string& refresh_url_string) { return base::expected( base::unexpected(SessionError{ - SessionError::ErrorType::kServerRequestedTermination, - net::SchemefulSite(GURL(refresh_url_string)), session_id})); + SessionError::ErrorType::kServerRequestedTermination})); }, std::string(session_id), std::string(refresh_url_string))); } diff --git a/naiveproxy/src/net/disk_cache/backend_cleanup_tracker.cc b/naiveproxy/src/net/disk_cache/backend_cleanup_tracker.cc index c25be4b827..c64af7465e 100644 --- a/naiveproxy/src/net/disk_cache/backend_cleanup_tracker.cc +++ b/naiveproxy/src/net/disk_cache/backend_cleanup_tracker.cc @@ -12,9 +12,9 @@ #include "base/files/file_path.h" #include "base/functional/callback.h" -#include "base/lazy_instance.h" #include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" +#include "base/no_destructor.h" #include "base/synchronization/lock.h" #include "base/task/sequenced_task_runner.h" @@ -36,7 +36,10 @@ struct AllBackendCleanupTrackers { base::Lock lock; }; -static base::LazyInstance::Leaky g_all_trackers; +AllBackendCleanupTrackers& GetAllTrackers() { + static base::NoDestructor all_trackers; + return *all_trackers; +} } // namespace. @@ -44,12 +47,11 @@ static base::LazyInstance::Leaky g_all_trackers; scoped_refptr BackendCleanupTracker::TryCreate( const base::FilePath& path, base::OnceClosure retry_closure) { - AllBackendCleanupTrackers* all_trackers = g_all_trackers.Pointer(); - base::AutoLock lock(all_trackers->lock); + AllBackendCleanupTrackers& all_trackers = GetAllTrackers(); + base::AutoLock lock(all_trackers.lock); - std::pair insert_result = - all_trackers->map.insert( - std::pair(path, nullptr)); + std::pair insert_result = all_trackers.map.insert( + std::pair(path, nullptr)); if (insert_result.second) { auto tracker = base::WrapRefCounted(new BackendCleanupTracker(path)); insert_result.first->second = tracker.get(); @@ -65,7 +67,7 @@ void BackendCleanupTracker::AddPostCleanupCallback(base::OnceClosure cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(seq_checker_); // Despite the sequencing requirement we need to grab the table lock since // this may otherwise race against TryMakeContext. - base::AutoLock lock(g_all_trackers.Get().lock); + base::AutoLock lock(GetAllTrackers().lock); AddPostCleanupCallbackImpl(std::move(cb)); } @@ -81,9 +83,9 @@ BackendCleanupTracker::~BackendCleanupTracker() { DCHECK_CALLED_ON_VALID_SEQUENCE(seq_checker_); { - AllBackendCleanupTrackers* all_trackers = g_all_trackers.Pointer(); - base::AutoLock lock(all_trackers->lock); - int rv = all_trackers->map.erase(path_); + AllBackendCleanupTrackers& all_trackers = GetAllTrackers(); + base::AutoLock lock(all_trackers.lock); + int rv = all_trackers.map.erase(path_); DCHECK_EQ(1, rv); } diff --git a/naiveproxy/src/net/disk_cache/backend_experiment.cc b/naiveproxy/src/net/disk_cache/backend_experiment.cc index a160a35918..9cdfb43d29 100644 --- a/naiveproxy/src/net/disk_cache/backend_experiment.cc +++ b/naiveproxy/src/net/disk_cache/backend_experiment.cc @@ -25,4 +25,11 @@ bool InBlockfileBackendExperimentGroup() { net::features::DiskCacheBackend::kBlockfile; } +#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND) +bool InSqlBackendExperimentGroup() { + return InBackendExperiment() && net::features::kDiskCacheBackendParam.Get() == + net::features::DiskCacheBackend::kSql; +} +#endif // ENABLE_DISK_CACHE_SQL_BACKEND + } // namespace disk_cache diff --git a/naiveproxy/src/net/disk_cache/backend_experiment.h b/naiveproxy/src/net/disk_cache/backend_experiment.h index e8a91f1e75..48230f1d3e 100644 --- a/naiveproxy/src/net/disk_cache/backend_experiment.h +++ b/naiveproxy/src/net/disk_cache/backend_experiment.h @@ -7,6 +7,7 @@ #include "build/build_config.h" #include "net/base/net_export.h" +#include "net/disk_cache/buildflags.h" namespace disk_cache { @@ -26,6 +27,11 @@ NET_EXPORT bool InSimpleBackendExperimentGroup(); // True if assigned to the "blockfile" disk cache backend group. NET_EXPORT bool InBlockfileBackendExperimentGroup(); +#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND) +// True if assigned to the "sql" disk cache backend group. +NET_EXPORT bool InSqlBackendExperimentGroup(); +#endif // ENABLE_DISK_CACHE_SQL_BACKEND + } // namespace disk_cache #endif // NET_DISK_CACHE_BACKEND_EXPERIMENT_H_ diff --git a/naiveproxy/src/net/disk_cache/blockfile/backend_impl.cc b/naiveproxy/src/net/disk_cache/blockfile/backend_impl.cc index 422b6b05fe..60d40eac2e 100644 --- a/naiveproxy/src/net/disk_cache/blockfile/backend_impl.cc +++ b/naiveproxy/src/net/disk_cache/blockfile/backend_impl.cc @@ -11,6 +11,8 @@ #include #include "base/containers/heap_array.h" +#include "base/debug/crash_logging.h" +#include "base/debug/dump_without_crashing.h" #include "base/files/file.h" #include "base/files/file_path.h" #include "base/files/file_util.h" @@ -36,8 +38,8 @@ #include "base/threading/thread_restrictions.h" #include "base/time/time.h" #include "base/timer/timer.h" +#include "base/trace_event/trace_event.h" #include "net/base/net_errors.h" -#include "net/base/tracing.h" #include "net/disk_cache/backend_cleanup_tracker.h" #include "net/disk_cache/blockfile/disk_format.h" #include "net/disk_cache/blockfile/entry_impl.h" @@ -62,6 +64,23 @@ const int kBaseTableLen = 64 * 1024; // Avoid trimming the cache for the first 5 minutes (10 timer ticks). const int kTrimDelay = 10; +BASE_FEATURE(kBlockfileCacheBackendDumpWithoutCrashing, + "BlockfileCacheBackendDumpWithoutCrashing", + base::FEATURE_DISABLED_BY_DEFAULT); + +BASE_FEATURE_PARAM(double, + kBlockfileCacheBackendDumpWithoutCrashingFrequency, + &kBlockfileCacheBackendDumpWithoutCrashing, + "dump_without_crashing_frequency", + 0.01); + +BASE_FEATURE_PARAM( + double, + kBlockfileCacheBackendDumpWithoutCrashingFrequencyOnInvalidLinks, + &kBlockfileCacheBackendDumpWithoutCrashing, + "dump_without_crashing_frequency_on_invalid_links", + 0.01); + int DesiredIndexTableLen(int32_t storage_size) { if (storage_size <= k64kEntriesStore) return kBaseTableLen; @@ -245,7 +264,19 @@ int BackendImpl::SyncInit() { new_eviction_ = (GetCacheType() == net::DISK_CACHE); } - if (!CheckIndex()) { + BackendImpl::CheckIndexResult check_index_result = CheckIndex(); + if (check_index_result != BackendImpl::CheckIndexResult::kOk) { + SCOPED_CRASH_KEY_NUMBER("DiskCache", "check_index_result", + static_cast(check_index_result)); + SCOPED_CRASH_KEY_NUMBER("DiskCache", "current_index_size", + index_->GetLength()); + SCOPED_CRASH_KEY_NUMBER("DiskCache", "table_len", data_->header.table_len); + SCOPED_CRASH_KEY_NUMBER("DiskCache", "index_size", + GetIndexSize(data_->header.table_len)); + SCOPED_CRASH_KEY_NUMBER("DiskCache", "num_entries", + data_->header.num_entries); + SCOPED_CRASH_KEY_NUMBER("DiskCache", "last_file_num", + data_->header.last_file); ReportError(ERR_INIT_FAILED); return net::ERR_FAILED; } @@ -907,7 +938,7 @@ int32_t BackendImpl::GetCurrentEntryId() const { } int64_t BackendImpl::MaxFileSize() const { - return GetCacheType() == net::PNACL_CACHE ? max_size_ : max_size_ / 8; + return max_size_ / 8; } void BackendImpl::ModifyStorageSize(int32_t old_size, int32_t new_size) { @@ -1012,6 +1043,40 @@ void BackendImpl::ReportError(int error) { // We transmit positive numbers, instead of direct error codes. DCHECK_LE(error, 0); if (GetCacheType() == net::DISK_CACHE) { + SCOPED_CRASH_KEY_NUMBER("DiskCache", "disk_cache_error", error * -1); + // TODO(crbug.com/433551601): Remove this once sufficient crash reports have + // been gathered, and definitely before stable. + if (error == ERR_INIT_FAILED) { + static bool has_considered_dumping = false; + // We want to DumpWithoutCrashing() only for X% of processes (configured + // by kBlockfileCacheBackendDumpWithoutCrashingFrequency), and only once + // per process, to avoid overwhelming the crash service. + if (!has_considered_dumping) { + has_considered_dumping = true; + if (base::FeatureList::IsEnabled( + kBlockfileCacheBackendDumpWithoutCrashing) && + base::ShouldRecordSubsampledMetric( + kBlockfileCacheBackendDumpWithoutCrashingFrequency.Get())) { + // Capture the last file error. This may or may not be related to the + // reason why init failed. + base::File::Error file_error = base::File::GetLastFileError(); + SCOPED_CRASH_KEY_NUMBER("DiskCache", "file_error", file_error); + base::debug::DumpWithoutCrashing(); + } + } + } else if (error == ERR_INVALID_LINKS) { + static bool has_considered_dumping = false; + if (!has_considered_dumping) { + has_considered_dumping = true; + if (base::FeatureList::IsEnabled( + kBlockfileCacheBackendDumpWithoutCrashing) && + base::ShouldRecordSubsampledMetric( + kBlockfileCacheBackendDumpWithoutCrashingFrequencyOnInvalidLinks + .Get())) { + base::debug::DumpWithoutCrashing(); + } + } + } base::UmaHistogramExactLinear("DiskCache.0.Error", error * -1, 50); } } @@ -1372,6 +1437,11 @@ bool BackendImpl::InitBackingStore(bool* file_created) { index_ = base::MakeRefCounted(); data_ = static_cast(index_->Init(index_name, 0)); +#if BUILDFLAG(IS_WIN) + // Experimentally enable flush for the index file on Windows + // (crbug.com/433551601). + index_->EnableFlush(); +#endif if (!data_) { LOG(ERROR) << "Unable to map Index file"; return false; @@ -1890,18 +1960,18 @@ void BackendImpl::UpgradeTo3_0() { data_->header.num_bytes = data_->header.old_v2_num_bytes; } -bool BackendImpl::CheckIndex() { +BackendImpl::CheckIndexResult BackendImpl::CheckIndex() { DCHECK(data_); size_t current_size = index_->GetLength(); if (current_size < sizeof(Index)) { LOG(ERROR) << "Corrupt Index file"; - return false; + return BackendImpl::CheckIndexResult::kCorruptIndexFileInIndexLength; } if (data_->header.magic != kIndexMagic) { LOG(ERROR) << "Invalid file magic"; - return false; + return BackendImpl::CheckIndexResult::kInvalidFileMagic; } // 2.0 + new_eviction needs conversion to 2.1. @@ -1917,18 +1987,22 @@ bool BackendImpl::CheckIndex() { if (kCurrentVersion != data_->header.version) { LOG(ERROR) << "Invalid file version"; - return false; + return BackendImpl::CheckIndexResult::kInvalidFileVersion; } if (!data_->header.table_len) { LOG(ERROR) << "Invalid table size"; - return false; + return BackendImpl::CheckIndexResult::kInvalidTableSize; } - if (current_size < GetIndexSize(data_->header.table_len) || - data_->header.table_len & (kBaseTableLen - 1)) { + if (current_size < GetIndexSize(data_->header.table_len)) { LOG(ERROR) << "Corrupt Index file"; - return false; + return BackendImpl::CheckIndexResult::kCorruptIndexFileInTableLength1; + } + + if (data_->header.table_len & (kBaseTableLen - 1)) { + LOG(ERROR) << "Corrupt Index file"; + return BackendImpl::CheckIndexResult::kCorruptIndexFileInTableLength2; } AdjustMaxCacheSize(data_->header.table_len); @@ -1938,13 +2012,13 @@ bool BackendImpl::CheckIndex() { (max_size_ < std::numeric_limits::max() - kDefaultCacheSize && data_->header.num_bytes > max_size_ + kDefaultCacheSize)) { LOG(ERROR) << "Invalid cache (current) size"; - return false; + return BackendImpl::CheckIndexResult::kInvalidCacheSize; } #endif if (data_->header.num_entries < 0) { LOG(ERROR) << "Invalid number of entries"; - return false; + return BackendImpl::CheckIndexResult::kInvalidNumberOfEntries; } if (!mask_) { @@ -1952,7 +2026,8 @@ bool BackendImpl::CheckIndex() { } // Load the table into memory. - return index_->Preload(); + return index_->Preload() ? BackendImpl::CheckIndexResult::kOk + : BackendImpl::CheckIndexResult::kFailedOnPreload; } int BackendImpl::CheckAllEntries() { diff --git a/naiveproxy/src/net/disk_cache/blockfile/backend_impl.h b/naiveproxy/src/net/disk_cache/blockfile/backend_impl.h index 04440b5b88..c277773e3d 100644 --- a/naiveproxy/src/net/disk_cache/blockfile/backend_impl.h +++ b/naiveproxy/src/net/disk_cache/blockfile/backend_impl.h @@ -380,8 +380,21 @@ class NET_EXPORT_PRIVATE BackendImpl : public Backend { // (from 2.1/2.0 depending on eviction algorithm) void UpgradeTo3_0(); - // Performs basic checks on the index file. Returns false on failure. - bool CheckIndex(); + enum class CheckIndexResult { + kOk, + kCorruptIndexFileInIndexLength, + kInvalidFileMagic, + kInvalidFileVersion, + kInvalidTableSize, + kCorruptIndexFileInTableLength1, + kInvalidCacheSize, + kInvalidNumberOfEntries, + kFailedOnPreload, + kCorruptIndexFileInTableLength2, + }; + + // Performs basic checks on the index file. + CheckIndexResult CheckIndex(); // Part of the self test. Returns the number or dirty entries, or an error. int CheckAllEntries(); diff --git a/naiveproxy/src/net/disk_cache/blockfile/disk_format.h b/naiveproxy/src/net/disk_cache/blockfile/disk_format.h index 325add45a4..996f222f13 100644 --- a/naiveproxy/src/net/disk_cache/blockfile/disk_format.h +++ b/naiveproxy/src/net/disk_cache/blockfile/disk_format.h @@ -102,8 +102,11 @@ struct NET_EXPORT_PRIVATE IndexHeader { // The structure of the whole index file. struct Index { IndexHeader header; - CacheAddr table[kIndexTablesize]; // Default size. Actual size controlled - // by header.table_len. + // Default size. Actual size controlled by header.table_len, and may be bigger + // or lower than this. Do not make this an std::array as the bound would be + // incorrect; see `BackendImpl::index_table_` for how boundary checking of + // this works. + CacheAddr table[kIndexTablesize]; }; // Main structure for an entry on the backing storage. If the key is longer than diff --git a/naiveproxy/src/net/disk_cache/blockfile/entry_impl.cc b/naiveproxy/src/net/disk_cache/blockfile/entry_impl.cc index e212f3df1c..f761a6b70c 100644 --- a/naiveproxy/src/net/disk_cache/blockfile/entry_impl.cc +++ b/naiveproxy/src/net/disk_cache/blockfile/entry_impl.cc @@ -815,7 +815,7 @@ Time EntryImpl::GetLastUsed() const { return Time::FromInternalValue(node->Data()->last_used); } -int32_t EntryImpl::GetDataSize(int index) const { +int64_t EntryImpl::GetDataSize(int index) const { if (index < 0 || index >= kNumStreams) return 0; @@ -824,12 +824,17 @@ int32_t EntryImpl::GetDataSize(int index) const { } int EntryImpl::ReadData(int index, - int offset, + int64_t offset, IOBuffer* buf, int buf_len, CompletionOnceCallback callback) { + if (offset > std::numeric_limits::max()) { + return net::ERR_INVALID_ARGUMENT; + } + if (callback.is_null()) - return ReadDataImpl(index, offset, buf, buf_len, std::move(callback)); + return ReadDataImpl(index, base::checked_cast(offset), buf, + buf_len, std::move(callback)); DCHECK(node_.Data()->dirty || read_only_); if (index < 0 || index >= kNumStreams) @@ -847,20 +852,25 @@ int EntryImpl::ReadData(int index, if (!background_queue_.get()) return net::ERR_UNEXPECTED; - background_queue_->ReadData(this, index, offset, buf, buf_len, - std::move(callback)); + background_queue_->ReadData(this, index, base::checked_cast(offset), + buf, buf_len, std::move(callback)); return net::ERR_IO_PENDING; } int EntryImpl::WriteData(int index, - int offset, + int64_t offset, IOBuffer* buf, int buf_len, CompletionOnceCallback callback, bool truncate) { + // TODO(crbug.com/391398191): Support `offset` larger than int32_t max. + if (offset > std::numeric_limits::max()) { + return net::ERR_INVALID_ARGUMENT; + } + if (callback.is_null()) { - return WriteDataImpl(index, offset, buf, buf_len, std::move(callback), - truncate); + return WriteDataImpl(index, base::checked_cast(offset), buf, + buf_len, std::move(callback), truncate); } DCHECK(node_.Data()->dirty || read_only_); @@ -870,11 +880,15 @@ int EntryImpl::WriteData(int index, if (offset < 0 || buf_len < 0) return net::ERR_INVALID_ARGUMENT; + if (!buf && buf_len != 0) { + return net::ERR_INVALID_ARGUMENT; + } + if (!background_queue_.get()) return net::ERR_UNEXPECTED; - background_queue_->WriteData(this, index, offset, buf, buf_len, truncate, - std::move(callback)); + background_queue_->WriteData(this, index, base::checked_cast(offset), + buf, buf_len, truncate, std::move(callback)); return net::ERR_IO_PENDING; } diff --git a/naiveproxy/src/net/disk_cache/blockfile/entry_impl.h b/naiveproxy/src/net/disk_cache/blockfile/entry_impl.h index 212b4fa9e5..ab4e458a5c 100644 --- a/naiveproxy/src/net/disk_cache/blockfile/entry_impl.h +++ b/naiveproxy/src/net/disk_cache/blockfile/entry_impl.h @@ -173,14 +173,14 @@ class NET_EXPORT_PRIVATE EntryImpl void Close() override; std::string GetKey() const override; base::Time GetLastUsed() const override; - int32_t GetDataSize(int index) const override; + int64_t GetDataSize(int index) const override; int ReadData(int index, - int offset, + int64_t offset, IOBuffer* buf, int buf_len, CompletionOnceCallback callback) override; int WriteData(int index, - int offset, + int64_t offset, IOBuffer* buf, int buf_len, CompletionOnceCallback callback, diff --git a/naiveproxy/src/net/disk_cache/blockfile/eviction.cc b/naiveproxy/src/net/disk_cache/blockfile/eviction.cc index 11257cbcf9..d1416b3997 100644 --- a/naiveproxy/src/net/disk_cache/blockfile/eviction.cc +++ b/naiveproxy/src/net/disk_cache/blockfile/eviction.cc @@ -36,12 +36,13 @@ #include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/location.h" +#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/notreached.h" #include "base/strings/string_util.h" #include "base/task/single_thread_task_runner.h" #include "base/time/time.h" -#include "net/base/tracing.h" +#include "base/trace_event/trace_event.h" #include "net/disk_cache/blockfile/backend_impl.h" #include "net/disk_cache/blockfile/disk_format.h" #include "net/disk_cache/blockfile/entry_impl.h" @@ -340,6 +341,27 @@ void Eviction::TrimCacheV2(bool empty) { // This entry is not being used by anybody. // Do NOT use node as an iterator after this point. rankings_->TrackRankingsBlock(node.get(), false); + if (!empty) { + // Eviction algorithm V2 is only used for the HTTP disk cache. These + // histograms are logged for every stored request, so they use the + // histogram macros. + // TODO(crbug.com/433551601): Remove these histograms once issue + // 433551601 is resolved. + UMA_HISTOGRAM_EXACT_LINEAR("DiskCache.0.EvictedRank", list, + kListsToSearch); + + const Time used_time = + Time::FromInternalValue(node->Data()->last_used); + const base::TimeDelta age = Time::Now() - used_time; + // For the purposes of this investigation we don't care about old + // entries getting evicted, so just ignore them so that they don't + // mess up the averages. + if (age < base::Days(1)) { + UMA_HISTOGRAM_CUSTOM_TIMES("DiskCache.0.EvictedAge", age, + base::Milliseconds(1), base::Days(1), + 50); + } + } if (EvictEntry(node.get(), empty, static_cast(list))) deleted_entries++; @@ -470,13 +492,14 @@ void Eviction::TrimDeleted(bool empty) { if (backend_->disabled_) return; + static constexpr int kMaxDeletedPerCall = 20; TimeTicks start = TimeTicks::Now(); Rankings::ScopedRankingsBlock node(rankings_); Rankings::ScopedRankingsBlock next( rankings_, rankings_->GetPrev(node.get(), Rankings::DELETED)); int deleted_entries = 0; while (next.get() && - (empty || (deleted_entries < 20 && + (empty || (deleted_entries < kMaxDeletedPerCall && (TimeTicks::Now() - start).InMilliseconds() < 20))) { node.reset(next.release()); next.reset(rankings_->GetPrev(node.get(), Rankings::DELETED)); @@ -486,6 +509,13 @@ void Eviction::TrimDeleted(bool empty) { break; } + if (!empty && new_eviction_) { + // TODO(crbug.com/433551601): Remove this histogram once issue 433551601 is + // resolved. + base::UmaHistogramExactLinear("DiskCache.0.TrimmedDeletedRankingEntries", + deleted_entries, kMaxDeletedPerCall + 1); + } + if (deleted_entries && !empty && ShouldTrimDeleted()) { base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( FROM_HERE, base::BindOnce(&Eviction::TrimDeleted, diff --git a/naiveproxy/src/net/disk_cache/blockfile/mapped_file.h b/naiveproxy/src/net/disk_cache/blockfile/mapped_file.h index 25ac5bbc61..958123784d 100644 --- a/naiveproxy/src/net/disk_cache/blockfile/mapped_file.h +++ b/naiveproxy/src/net/disk_cache/blockfile/mapped_file.h @@ -66,6 +66,9 @@ class NET_EXPORT_PRIVATE MappedFile : public File { // Flush the memory-mapped section to disk (synchronously). void Flush(); +#if BUILDFLAG(IS_WIN) + void EnableFlush(); +#endif // Heats up the file system cache and make sure the file is fully // readable (synchronously). @@ -75,7 +78,9 @@ class NET_EXPORT_PRIVATE MappedFile : public File { ~MappedFile() override; bool init_ = false; + #if BUILDFLAG(IS_WIN) + bool enable_flush_ = false; HANDLE section_; #endif diff --git a/naiveproxy/src/net/disk_cache/blockfile/mapped_file_win.cc b/naiveproxy/src/net/disk_cache/blockfile/mapped_file_win.cc index 7b3affc793..f165e0281e 100644 --- a/naiveproxy/src/net/disk_cache/blockfile/mapped_file_win.cc +++ b/naiveproxy/src/net/disk_cache/blockfile/mapped_file_win.cc @@ -10,7 +10,9 @@ #include "base/check.h" #include "base/containers/heap_array.h" +#include "base/feature_list.h" #include "base/files/file_path.h" +#include "net/base/features.h" #include "net/disk_cache/disk_cache.h" namespace disk_cache { @@ -59,6 +61,19 @@ MappedFile::~MappedFile() { } void MappedFile::Flush() { + if (!base::FeatureList::IsEnabled( + net::features::kHttpCacheMappedFileFlushWin) || + !enable_flush_) { + return; + } + if (buffer_) { + BOOL ret = FlushViewOfFile(buffer_, 0); + DCHECK(ret); + } +} + +void MappedFile::EnableFlush() { + enable_flush_ = true; } } // namespace disk_cache diff --git a/naiveproxy/src/net/disk_cache/blockfile/rankings.cc b/naiveproxy/src/net/disk_cache/blockfile/rankings.cc index 091fcb28ee..58a9d56f07 100644 --- a/naiveproxy/src/net/disk_cache/blockfile/rankings.cc +++ b/naiveproxy/src/net/disk_cache/blockfile/rankings.cc @@ -202,6 +202,18 @@ Rankings::ScopedRankingsBlock::ScopedRankingsBlock(Rankings* rankings, CacheRankingsBlock* node) : std::unique_ptr(node), rankings_(rankings) {} +Rankings::ScopedRankingsBlock::~ScopedRankingsBlock() { + rankings_->FreeRankingsBlock(get()); +} + +// scoped_ptr::reset will delete `p`. +void Rankings::ScopedRankingsBlock::reset(CacheRankingsBlock* p) { + if (p != get()) { + rankings_->FreeRankingsBlock(get()); + } + std::unique_ptr::reset(p); +} + Rankings::Iterator::Iterator() = default; void Rankings::Iterator::Reset() { diff --git a/naiveproxy/src/net/disk_cache/blockfile/rankings.h b/naiveproxy/src/net/disk_cache/blockfile/rankings.h index a8cabb4ca7..67168925a3 100644 --- a/naiveproxy/src/net/disk_cache/blockfile/rankings.h +++ b/naiveproxy/src/net/disk_cache/blockfile/rankings.h @@ -76,20 +76,13 @@ class Rankings { ScopedRankingsBlock(const ScopedRankingsBlock&) = delete; ScopedRankingsBlock& operator=(const ScopedRankingsBlock&) = delete; - ~ScopedRankingsBlock() { - rankings_->FreeRankingsBlock(get()); - } + ~ScopedRankingsBlock(); void set_rankings(Rankings* rankings) { rankings_ = rankings; } - // scoped_ptr::reset will delete the object. - void reset(CacheRankingsBlock* p = nullptr) { - if (p != get()) - rankings_->FreeRankingsBlock(get()); - std::unique_ptr::reset(p); - } + void reset(CacheRankingsBlock* p = nullptr); private: raw_ptr rankings_; diff --git a/naiveproxy/src/net/disk_cache/cache_util.cc b/naiveproxy/src/net/disk_cache/cache_util.cc index b004d25a68..4e47c44aaa 100644 --- a/naiveproxy/src/net/disk_cache/cache_util.cc +++ b/naiveproxy/src/net/disk_cache/cache_util.cc @@ -23,6 +23,7 @@ #include "base/task/thread_pool.h" #include "base/threading/thread_restrictions.h" #include "build/build_config.h" +#include "net/base/cache_type.h" namespace { @@ -134,16 +135,9 @@ namespace disk_cache { const int kDefaultCacheSize = 80 * 1024 * 1024; -BASE_FEATURE(kChangeDiskCacheSizeExperiment, - "ChangeDiskCacheSize", -// See go/change-disk-cache-size-results-2024 for an explanation of why the -// state of this feature varies by platform. -#if BUILDFLAG(IS_WIN) - base::FEATURE_DISABLED_BY_DEFAULT -#else - base::FEATURE_ENABLED_BY_DEFAULT -#endif -); +BASE_FEATURE(kChangeGeneratedCodeCacheSizeExperiment, + "ChangeGeneratedCodeCacheSize", + base::FEATURE_DISABLED_BY_DEFAULT); void DeleteCache(const base::FilePath& path, bool remove_folder) { if (remove_folder) { @@ -189,12 +183,20 @@ int PreferredCacheSize(int64_t available, net::CacheType type) { // use 100% of the default size. int percent_relative_size = 100; +// See go/change-disk-cache-size-results-2024 for an explanation of why the +// size varies by platform. +#if !BUILDFLAG(IS_WIN) + if (type == net::DISK_CACHE) { + percent_relative_size = 400; + } +#endif + if (base::FeatureList::IsEnabled( - disk_cache::kChangeDiskCacheSizeExperiment) && - type == net::DISK_CACHE) { + disk_cache::kChangeGeneratedCodeCacheSizeExperiment) && + type == net::GENERATED_BYTE_CODE_CACHE) { percent_relative_size = base::GetFieldTrialParamByFeatureAsInt( - disk_cache::kChangeDiskCacheSizeExperiment, "percent_relative_size", - 400 /* default value */); + disk_cache::kChangeGeneratedCodeCacheSizeExperiment, + "percent_relative_size", 400 /* default value */); } // Cap scaling, as a safety check, to avoid overflow. diff --git a/naiveproxy/src/net/disk_cache/cache_util.h b/naiveproxy/src/net/disk_cache/cache_util.h index db71eabcfa..4ae9974a4c 100644 --- a/naiveproxy/src/net/disk_cache/cache_util.h +++ b/naiveproxy/src/net/disk_cache/cache_util.h @@ -18,9 +18,10 @@ class FilePath; namespace disk_cache { -// Experiment to increase the cache size to see the impact on various -// performance metrics. -NET_EXPORT_PRIVATE BASE_DECLARE_FEATURE(kChangeDiskCacheSizeExperiment); +// Experiment to increase the generated code cache size to see the impact on +// various performance metrics. +NET_EXPORT_PRIVATE BASE_DECLARE_FEATURE( + kChangeGeneratedCodeCacheSizeExperiment); // Moves the cache files from the given path to another location. // Fails if the destination exists already, or if it doesn't have diff --git a/naiveproxy/src/net/disk_cache/cache_util_win.cc b/naiveproxy/src/net/disk_cache/cache_util_win.cc index 70d798e925..880079ac31 100644 --- a/naiveproxy/src/net/disk_cache/cache_util_win.cc +++ b/naiveproxy/src/net/disk_cache/cache_util_win.cc @@ -8,6 +8,7 @@ #include "base/files/file_path.h" #include "base/logging.h" +#include "base/metrics/histogram_functions.h" #include "base/strings/string_util.h" #include "base/win/scoped_handle.h" @@ -16,8 +17,14 @@ namespace disk_cache { bool MoveCache(const base::FilePath& from_path, const base::FilePath& to_path) { // I don't want to use the shell version of move because if something goes // wrong, that version will attempt to move file by file and fail at the end. - if (!MoveFileEx(from_path.value().c_str(), to_path.value().c_str(), 0)) { + bool result = + MoveFileEx(from_path.value().c_str(), to_path.value().c_str(), 0); + base::UmaHistogramBoolean("DiskCache.MoveCacheToRestartCache.Windows", + result); + if (!result) { PLOG(ERROR) << "Unable to move the cache"; + base::UmaHistogramSparse("DiskCache.MoveCacheToRestartCacheError.Windows", + ::GetLastError()); return false; } return true; diff --git a/naiveproxy/src/net/disk_cache/disk_cache.cc b/naiveproxy/src/net/disk_cache/disk_cache.cc index 06a0fd60b8..7d04b64893 100644 --- a/naiveproxy/src/net/disk_cache/disk_cache.cc +++ b/naiveproxy/src/net/disk_cache/disk_cache.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "net/disk_cache/disk_cache.h" + #include #include "base/barrier_closure.h" @@ -16,10 +18,12 @@ #include "base/task/single_thread_task_runner.h" #include "base/task/thread_pool/thread_pool_instance.h" #include "build/build_config.h" +#include "build/buildflag.h" #include "net/base/cache_type.h" #include "net/base/net_errors.h" #include "net/disk_cache/backend_cleanup_tracker.h" #include "net/disk_cache/blockfile/backend_impl.h" +#include "net/disk_cache/buildflags.h" #include "net/disk_cache/cache_util.h" #include "net/disk_cache/disk_cache.h" #include "net/disk_cache/memory/mem_backend_impl.h" @@ -27,6 +31,10 @@ #include "net/disk_cache/simple/simple_file_enumerator.h" #include "net/disk_cache/simple/simple_util.h" +#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND) +#include "net/disk_cache/sql/sql_backend_impl.h" +#endif // ENABLE_DISK_CACHE_SQL_BACKEND + namespace { using FileEnumerator = disk_cache::BackendFileOperations::FileEnumerator; @@ -152,6 +160,18 @@ void CacheCreator::Run() { return; } +#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND) + if (backend_type_ == net::CACHE_BACKEND_EXPERIMENTAL_SQL) { + auto sql_cache = + std::make_unique(path_, max_bytes_, type_); + auto* sql_cache_ptr = sql_cache.get(); + created_cache_ = std::move(sql_cache); + sql_cache_ptr->Init( + base::BindOnce(&CacheCreator::OnIOComplete, base::Unretained(this))); + return; + } +#endif // ENABLE_DISK_CACHE_SQL_BACKEND + // Avoid references to blockfile functions on Android to reduce binary size. #if BUILDFLAG(IS_ANDROID) FailAttempt(); diff --git a/naiveproxy/src/net/disk_cache/disk_cache.h b/naiveproxy/src/net/disk_cache/disk_cache.h index c3e250f0dc..fe34bd6199 100644 --- a/naiveproxy/src/net/disk_cache/disk_cache.h +++ b/naiveproxy/src/net/disk_cache/disk_cache.h @@ -347,36 +347,40 @@ class NET_EXPORT Entry { virtual base::Time GetLastUsed() const = 0; // Returns the size of the cache data with the given index. - virtual int32_t GetDataSize(int index) const = 0; + virtual int64_t GetDataSize(int index) const = 0; - // Copies cached data into the given buffer of length |buf_len|. Returns the + // Copies cached data into the given buffer of length `buf_len`. Returns the // number of bytes read or a network error code. If this function returns // ERR_IO_PENDING, the completion callback will be called on the current - // thread when the operation completes, and a reference to |buf| will be + // thread when the operation completes, and a reference to `buf` will be // retained until the callback is called. Note that as long as the function // does not complete immediately, the callback will always be invoked, even // after Close has been called; in other words, the caller may close this // entry without having to wait for all the callbacks, and still rely on the // cleanup performed from the callback code. + // Note that `offset` larger than int32 max is supported only by Simple Cache + // backend. It will return ERR_INVALID_ARGUMENT for other backends. virtual int ReadData(int index, - int offset, + int64_t offset, IOBuffer* buf, int buf_len, CompletionOnceCallback callback) = 0; - // Copies data from the given buffer of length |buf_len| into the cache. + // Copies data from the given buffer of length `buf_len` into the cache. // Returns the number of bytes written or a network error code. If this // function returns ERR_IO_PENDING, the completion callback will be called // on the current thread when the operation completes, and a reference to - // |buf| will be retained until the callback is called. Note that as long as + // `buf` will be retained until the callback is called. Note that as long as // the function does not complete immediately, the callback will always be // invoked, even after Close has been called; in other words, the caller may // close this entry without having to wait for all the callbacks, and still // rely on the cleanup performed from the callback code. // If truncate is true, this call will truncate the stored data at the end of // what we are writing here. + // Note that `offset` larger than int32 max is supported only by Simple Cache + // backend. It will return ERR_INVALID_ARGUMENT for other backends. virtual int WriteData(int index, - int offset, + int64_t offset, IOBuffer* buf, int buf_len, CompletionOnceCallback callback, diff --git a/naiveproxy/src/net/disk_cache/disk_cache_test_base.cc b/naiveproxy/src/net/disk_cache/disk_cache_test_base.cc index 66ec3e6142..e1497f5732 100644 --- a/naiveproxy/src/net/disk_cache/disk_cache_test_base.cc +++ b/naiveproxy/src/net/disk_cache/disk_cache_test_base.cc @@ -31,6 +31,10 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND) +#include "net/disk_cache/sql/sql_backend_impl.h" +#endif // ENABLE_DISK_CACHE_SQL_BACKEND + using net::test::IsOk; DiskCacheTest::DiskCacheTest( @@ -76,6 +80,10 @@ std::string DiskCacheTestWithCache::BackendToTestName( return "Simple"; case BackendToTest::kMemory: return "Memory"; +#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND) + case BackendToTest::kSql: + return "Sql"; +#endif // ENABLE_DISK_CACHE_SQL_BACKEND } NOTREACHED(); } @@ -249,6 +257,15 @@ void DiskCacheTestWithCache::FlushQueueForTest() { return; } +#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND) + if (sql_cache_impl_) { + net::TestCompletionCallback cb; + int rv = sql_cache_impl_->FlushQueueForTest(cb.callback()); + EXPECT_THAT(cb.GetResult(rv), IsOk()); + return; + } +#endif // ENABLE_DISK_CACHE_SQL_BACKEND + DCHECK(cache_impl_); net::TestCompletionCallback cb; int rv = cache_impl_->FlushQueueForTest(cb.callback()); @@ -354,6 +371,9 @@ void DiskCacheTestWithCache::OnExternalCacheHit(const std::string& key) { std::unique_ptr DiskCacheTestWithCache::TakeCache() { mem_cache_ = nullptr; simple_cache_impl_ = nullptr; +#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND) + sql_cache_impl_ = nullptr; +#endif // ENABLE_DISK_CACHE_SQL_BACKEND cache_impl_ = nullptr; return std::move(cache_); } @@ -372,8 +392,21 @@ void DiskCacheTestWithCache::TearDown() { } void DiskCacheTestWithCache::ResetCaches() { - // Deletion occurs by `cache` going out of scope. +#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND) + scoped_refptr background_task_runner; + if (sql_cache_impl_) { + background_task_runner = sql_cache_impl_->GetBackgroundTaskRunnerForTest(); + } +#endif // ENABLE_DISK_CACHE_SQL_BACKEND std::unique_ptr cache = TakeCache(); + cache.reset(); +#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND) + if (background_task_runner) { + base::RunLoop run_loop; + background_task_runner->PostTask(FROM_HERE, run_loop.QuitClosure()); + run_loop.Run(); + } +#endif // ENABLE_DISK_CACHE_SQL_BACKEND } void DiskCacheTestWithCache::InitMemoryCache() { @@ -425,6 +458,18 @@ void DiskCacheTestWithCache::CreateBackend(uint32_t flags) { } return; } +#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND) + if (backend_to_test_ == BackendToTest::kSql) { + net::TestCompletionCallback cb; + auto sql_backend = + std::make_unique(cache_path_, size_, type_); + sql_backend->Init(cb.callback()); + ASSERT_THAT(cb.WaitForResult(), IsOk()); + sql_cache_impl_ = sql_backend.get(); + cache_ = std::move(sql_backend); + return; + } +#endif // ENABLE_DISK_CACHE_SQL_BACKEND CHECK_EQ(backend_to_test_, BackendToTest::kBlockfile); std::unique_ptr cache; diff --git a/naiveproxy/src/net/disk_cache/disk_cache_test_base.h b/naiveproxy/src/net/disk_cache/disk_cache_test_base.h index 53ef748fbb..1dc8fbb098 100644 --- a/naiveproxy/src/net/disk_cache/disk_cache_test_base.h +++ b/naiveproxy/src/net/disk_cache/disk_cache_test_base.h @@ -14,7 +14,9 @@ #include "base/memory/raw_ptr.h" #include "base/test/task_environment.h" #include "base/threading/thread.h" +#include "build/buildflag.h" #include "net/base/cache_type.h" +#include "net/disk_cache/buildflags.h" #include "net/disk_cache/disk_cache.h" #include "net/test/test_with_task_environment.h" #include "testing/gtest/include/gtest/gtest.h" @@ -35,6 +37,10 @@ class MemBackendImpl; class SimpleBackendImpl; class SimpleFileTracker; +#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND) +class SqlBackendImpl; +#endif // ENABLE_DISK_CACHE_SQL_BACKEND + } // namespace disk_cache // These tests can use the path service, which uses autoreleased objects on the @@ -65,7 +71,14 @@ class DiskCacheTest : public PlatformTest, public net::WithTaskEnvironment { // Provides basic support for cache related tests. class DiskCacheTestWithCache : public DiskCacheTest { public: - enum class BackendToTest { kBlockfile, kSimple, kMemory }; + enum class BackendToTest { + kBlockfile, + kSimple, + kMemory, +#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND) + kSql +#endif // ENABLE_DISK_CACHE_SQL_BACKEND + }; static std::string BackendToTestName(BackendToTest backend_to_test); protected: @@ -212,6 +225,9 @@ class DiskCacheTestWithCache : public DiskCacheTest { raw_ptr cache_impl_ = nullptr; std::unique_ptr simple_file_tracker_; raw_ptr simple_cache_impl_ = nullptr; +#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND) + raw_ptr sql_cache_impl_ = nullptr; +#endif // ENABLE_DISK_CACHE_SQL_BACKEND raw_ptr mem_cache_ = nullptr; uint32_t mask_ = 0; diff --git a/naiveproxy/src/net/disk_cache/memory/mem_entry_impl.cc b/naiveproxy/src/net/disk_cache/memory/mem_entry_impl.cc index da4dee2e60..d79bfbf309 100644 --- a/naiveproxy/src/net/disk_cache/memory/mem_entry_impl.cc +++ b/naiveproxy/src/net/disk_cache/memory/mem_entry_impl.cc @@ -170,24 +170,37 @@ Time MemEntryImpl::GetLastUsed() const { return last_used_; } -int32_t MemEntryImpl::GetDataSize(int index) const { +int64_t MemEntryImpl::GetDataSize(int index) const { if (index < 0 || index >= kNumStreams) return 0; return data_[index].size(); } int MemEntryImpl::ReadData(int index, - int offset, + int64_t offset, IOBuffer* buf, int buf_len, CompletionOnceCallback callback) { + // TODO(crbug.com/391398191): Update the maximum to size_t max when it's + // supported. `offset` must be within size_t range anyway so that the data + // will be in-mmory. + if (offset > std::numeric_limits::max()) { + if (net_log_.IsCapturing()) { + NetLogReadWriteComplete(net_log_, net::NetLogEventType::ENTRY_READ_DATA, + net::NetLogEventPhase::NONE, + net::ERR_INVALID_ARGUMENT); + } + return net::ERR_INVALID_ARGUMENT; + } + if (net_log_.IsCapturing()) { NetLogReadWriteData(net_log_, net::NetLogEventType::ENTRY_READ_DATA, net::NetLogEventPhase::BEGIN, index, offset, buf_len, false); } - int result = InternalReadData(index, offset, buf, buf_len); + int result = InternalReadData(index, base::checked_cast(offset), buf, + buf_len); if (net_log_.IsCapturing()) { NetLogReadWriteComplete(net_log_, net::NetLogEventType::ENTRY_READ_DATA, @@ -197,18 +210,31 @@ int MemEntryImpl::ReadData(int index, } int MemEntryImpl::WriteData(int index, - int offset, + int64_t offset, IOBuffer* buf, int buf_len, CompletionOnceCallback callback, bool truncate) { + // TODO(crbug.com/391398191): Update the maximum to size_t max when it's + // supported. `offset` must be within size_t range anyway so that the data + // will be in-mmory. + if (offset > std::numeric_limits::max()) { + if (net_log_.IsCapturing()) { + NetLogReadWriteComplete(net_log_, net::NetLogEventType::ENTRY_READ_DATA, + net::NetLogEventPhase::NONE, + net::ERR_INVALID_ARGUMENT); + } + return net::ERR_INVALID_ARGUMENT; + } + if (net_log_.IsCapturing()) { NetLogReadWriteData(net_log_, net::NetLogEventType::ENTRY_WRITE_DATA, net::NetLogEventPhase::BEGIN, index, offset, buf_len, truncate); } - int result = InternalWriteData(index, offset, buf, buf_len, truncate); + int result = InternalWriteData(index, base::checked_cast(offset), + buf, buf_len, truncate); if (net_log_.IsCapturing()) { NetLogReadWriteComplete(net_log_, net::NetLogEventType::ENTRY_WRITE_DATA, @@ -404,6 +430,10 @@ int MemEntryImpl::InternalWriteData(int index, int offset, IOBuffer* buf, if (offset < 0 || buf_len < 0) return net::ERR_INVALID_ARGUMENT; + if (!buf && buf_len != 0) { + return net::ERR_INVALID_ARGUMENT; + } + unsigned u_offset = static_cast(offset); unsigned u_buf_len = static_cast(buf_len); diff --git a/naiveproxy/src/net/disk_cache/memory/mem_entry_impl.h b/naiveproxy/src/net/disk_cache/memory/mem_entry_impl.h index f97bf0d829..4d996b9420 100644 --- a/naiveproxy/src/net/disk_cache/memory/mem_entry_impl.h +++ b/naiveproxy/src/net/disk_cache/memory/mem_entry_impl.h @@ -104,14 +104,14 @@ class NET_EXPORT_PRIVATE MemEntryImpl final void Close() override; std::string GetKey() const override; base::Time GetLastUsed() const override; - int32_t GetDataSize(int index) const override; + int64_t GetDataSize(int index) const override; int ReadData(int index, - int offset, + int64_t offset, IOBuffer* buf, int buf_len, CompletionOnceCallback callback) override; int WriteData(int index, - int offset, + int64_t offset, IOBuffer* buf, int buf_len, CompletionOnceCallback callback, diff --git a/naiveproxy/src/net/disk_cache/mock/mock_entry_impl.h b/naiveproxy/src/net/disk_cache/mock/mock_entry_impl.h index aeb4be60d1..caf2715c0d 100644 --- a/naiveproxy/src/net/disk_cache/mock/mock_entry_impl.h +++ b/naiveproxy/src/net/disk_cache/mock/mock_entry_impl.h @@ -22,11 +22,11 @@ class EntryMock : public Entry { MOCK_METHOD(void, Doom, (), (override)); MOCK_METHOD(std::string, GetKey, (), (const, override)); MOCK_METHOD(base::Time, GetLastUsed, (), (const, override)); - MOCK_METHOD(int32_t, GetDataSize, (int index), (const, override)); + MOCK_METHOD(int64_t, GetDataSize, (int index), (const, override)); MOCK_METHOD(int, ReadData, (int index, - int offset, + int64_t offset, IOBuffer* buf, int buf_len, CompletionOnceCallback callback), @@ -34,7 +34,7 @@ class EntryMock : public Entry { MOCK_METHOD(int, WriteData, (int index, - int offset, + int64_t offset, IOBuffer* buf, int buf_len, CompletionOnceCallback callback, 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 9edfcaba5b..730d05d27b 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_backend_impl.cc +++ b/naiveproxy/src/net/disk_cache/simple/simple_backend_impl.cc @@ -21,13 +21,13 @@ #include "base/files/file_util.h" #include "base/functional/bind.h" #include "base/functional/callback.h" -#include "base/lazy_instance.h" #include "base/location.h" #include "base/memory/ptr_util.h" #include "base/metrics/field_trial.h" #include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" +#include "base/no_destructor.h" #include "base/system/sys_info.h" #include "base/task/thread_pool/thread_pool_instance.h" #include "base/time/time.h" @@ -65,8 +65,10 @@ constexpr int64_t kMinFileSizeLimit = 5 * 1024 * 1024; // Global context of all the files we have open --- this permits some to be // closed on demand if too many FDs are being used, to avoid running out. -base::LazyInstance::Leaky g_simple_file_tracker = - LAZY_INSTANCE_INITIALIZER; +SimpleFileTracker* GetSimpleFileTracker() { + static base::NoDestructor file_tracker; + return file_tracker.get(); +} // Detects if the files in the cache directory match the current disk cache // backend type and version. If the directory contains no cache, occupies it @@ -219,8 +221,7 @@ SimpleBackendImpl::SimpleBackendImpl( ? std::move(file_operations_factory) : base::MakeRefCounted()), cleanup_tracker_(std::move(cleanup_tracker)), - file_tracker_(file_tracker ? file_tracker - : g_simple_file_tracker.Pointer()), + file_tracker_(file_tracker ? file_tracker : GetSimpleFileTracker()), path_(path), orig_max_size_(max_bytes), entry_operations_mode_(CacheTypeToOperationsMode(cache_type)), diff --git a/naiveproxy/src/net/disk_cache/simple/simple_entry_format.h b/naiveproxy/src/net/disk_cache/simple/simple_entry_format.h index 01a7a35565..2bde6f16fb 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_entry_format.h +++ b/naiveproxy/src/net/disk_cache/simple/simple_entry_format.h @@ -75,7 +75,8 @@ struct NET_EXPORT_PRIVATE SimpleFileEOF { uint64_t final_magic_number = 0; uint32_t flags = 0; uint32_t data_crc32 = 0; - // |stream_size| is only used in the EOF record for stream 0. + // |stream_size| is only used in the EOF record for stream 0. The value must + // smaller than int32 max. uint32_t stream_size = 0; // Avoid implicit padding so `std::has_unique_object_representations_v<>` will diff --git a/naiveproxy/src/net/disk_cache/simple/simple_entry_impl.cc b/naiveproxy/src/net/disk_cache/simple/simple_entry_impl.cc index 581066672d..338d0fe96e 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_entry_impl.cc +++ b/naiveproxy/src/net/disk_cache/simple/simple_entry_impl.cc @@ -45,6 +45,30 @@ namespace { // the cache. constexpr int64_t kMaxSparseDataSizeDivisor = 10; +// Due to the data structure of EntryMetadata limitation, the total size of the +// all data must fit in 38 bits. +// For the file containing Stream 1, we have +// 1. Stream 0: limited to int32 max size +// 2. Stream 1: no limitation +// 3. Stream 2: no limitation +// (Sparse data does not exist at the same time with Stream 1.) +// +// Also, stream 1 data includes the key, header and the file eof. The key is +// int32 max size. +// The size limitation is following: +// (Stream 0: 32 bits) + (Stream 1: 32 bits key + header size + eof size + +// 38 bits content) + (Stream 2) <= 38 bits +// +// Therefore, we set the Stream 1 size limit to the following assuming that +// stream 1 and Stream 2 uses the similar amount of size. +// (38 bits max - stream 0 max (32 bits)) / 2 - key max (32 bits) - header - eof +// +// TODO(crbug.com/391398191): Make the file size limit consistent and move them +// to MaxFileSize in the backend. +constexpr int64_t kStream1SizeLimit = ((1LL << 38) - (1LL << 32)) / 2 - + (1LL << 32) - sizeof(SimpleFileHeader) - + sizeof(SimpleFileEOF); + OpenEntryIndexEnum ComputeIndexState(SimpleBackendImpl* backend, uint64_t entry_hash) { if (!backend->index()->initialized()) @@ -363,14 +387,14 @@ Time SimpleEntryImpl::GetLastUsed() const { return last_used_; } -int32_t SimpleEntryImpl::GetDataSize(int stream_index) const { +int64_t SimpleEntryImpl::GetDataSize(int stream_index) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_LE(0, data_size_[stream_index]); return data_size_[stream_index]; } int SimpleEntryImpl::ReadData(int stream_index, - int offset, + int64_t offset, net::IOBuffer* buf, int buf_len, CompletionOnceCallback callback) { @@ -412,7 +436,7 @@ int SimpleEntryImpl::ReadData(int stream_index, } int SimpleEntryImpl::WriteData(int stream_index, - int offset, + int64_t offset, net::IOBuffer* buf, int buf_len, CompletionOnceCallback callback, @@ -426,7 +450,7 @@ int SimpleEntryImpl::WriteData(int stream_index, } if (stream_index < 0 || stream_index >= kSimpleEntryStreamCount || - offset < 0 || buf_len < 0) { + offset < 0 || buf_len < 0 || (!buf && buf_len != 0)) { if (net_log_.IsCapturing()) { NetLogReadWriteComplete( net_log_, net::NetLogEventType::SIMPLE_CACHE_ENTRY_WRITE_END, @@ -435,9 +459,10 @@ int SimpleEntryImpl::WriteData(int stream_index, return net::ERR_INVALID_ARGUMENT; } - int end_offset; + int64_t end_offset; if (!base::CheckAdd(offset, buf_len).AssignIfValid(&end_offset) || - (backend_.get() && end_offset > backend_->MaxFileSize())) { + (backend_.get() && end_offset > backend_->MaxFileSize()) || + end_offset > kStream1SizeLimit) { if (net_log_.IsCapturing()) { NetLogReadWriteComplete( net_log_, net::NetLogEventType::SIMPLE_CACHE_ENTRY_WRITE_END, @@ -445,6 +470,19 @@ int SimpleEntryImpl::WriteData(int stream_index, } return net::ERR_FAILED; } + + // Stream 0 data size limitation is int32_t max. + // TODO(crbug.com/433856002): int32 max is too large for stream 0 where stream + // 0 needs consecutive memory space. Set the proper size limitation. + if (stream_index == 0 && end_offset > std::numeric_limits::max()) { + if (net_log_.IsCapturing()) { + NetLogReadWriteComplete( + net_log_, net::NetLogEventType::SIMPLE_CACHE_ENTRY_WRITE_END, + net::NetLogEventPhase::NONE, net::ERR_INVALID_ARGUMENT); + } + return net::ERR_INVALID_ARGUMENT; + } + ScopedOperationRunner operation_runner(this); // Stream 0 data is kept in memory, so can be written immediatly if there are @@ -452,7 +490,7 @@ int SimpleEntryImpl::WriteData(int stream_index, if (stream_index == 0 && state_ == STATE_READY && pending_operations_.size() == 0) { state_ = STATE_IO_PENDING; - SetStream0Data(buf, offset, buf_len, truncate); + SetStream0Data(buf, base::checked_cast(offset), buf_len, truncate); state_ = STATE_READY; return buf_len; } @@ -795,7 +833,7 @@ void SimpleEntryImpl::OpenEntryInternal( auto results = std::make_unique( SimpleEntryStat(last_used_, data_size_, sparse_data_size_)); - int32_t trailer_prefetch_size = -1; + uint32_t trailer_prefetch_size = 0; base::Time last_used_time; if (SimpleBackendImpl* backend = backend_.get()) { if (cache_type_ == net::APP_CACHE) { @@ -902,7 +940,7 @@ void SimpleEntryImpl::OpenOrCreateEntryInternal( auto results = std::make_unique( SimpleEntryStat(last_used_, data_size_, sparse_data_size_)); - int32_t trailer_prefetch_size = -1; + uint32_t trailer_prefetch_size = 0; base::Time last_used_time; if (SimpleBackendImpl* backend = backend_.get()) { if (cache_type_ == net::APP_CACHE) { @@ -978,7 +1016,7 @@ void SimpleEntryImpl::CloseInternal() { int SimpleEntryImpl::ReadDataInternal(bool sync_possible, int stream_index, - int offset, + int64_t offset, net::IOBuffer* buf, int buf_len, net::CompletionOnceCallback callback) { @@ -1011,13 +1049,21 @@ int SimpleEntryImpl::ReadDataInternal(bool sync_possible, return PostToCallbackIfNeeded(sync_possible, std::move(callback), 0); } - // Truncate read to not go past end of stream. - buf_len = std::min(buf_len, GetDataSize(stream_index) - offset); + // Truncate read to not go past end of stream. Note that `buf_len` must fit + // within int range since it takes the minimum. + buf_len = std::min(static_cast(buf_len), + GetDataSize(stream_index) - offset); // Since stream 0 data is kept in memory, it is read immediately. if (stream_index == 0) { + // Stream 0 data size limitation is int32_t max. + // TODO(crbug.com/433856002): int32 max is too large for stream 0 where + // stream 0 needs consecutive memory space. Set the proper size limitation. + CHECK_LE(GetDataSize(stream_index), std::numeric_limits::max()); + state_ = STATE_IO_PENDING; - ReadFromBuffer(stream_0_data_.get(), offset, buf_len, buf); + ReadFromBuffer(stream_0_data_.get(), static_cast(offset), buf_len, + buf); state_ = STATE_READY; return PostToCallbackIfNeeded(sync_possible, std::move(callback), buf_len); } @@ -1025,8 +1071,13 @@ int SimpleEntryImpl::ReadDataInternal(bool sync_possible, // Sometimes we can read in-ram prefetched stream 1 data immediately, too. if (stream_index == 1) { if (stream_1_prefetch_data_) { + CHECK_EQ(stream_1_prefetch_data_->size(), GetDataSize(1)); + // Prefetch data size limitation is int32_t max. + CHECK_LE(GetDataSize(stream_index), std::numeric_limits::max()); + state_ = STATE_IO_PENDING; - ReadFromBuffer(stream_1_prefetch_data_.get(), offset, buf_len, buf); + ReadFromBuffer(stream_1_prefetch_data_.get(), static_cast(offset), + buf_len, buf); state_ = STATE_READY; return PostToCallbackIfNeeded(sync_possible, std::move(callback), buf_len); @@ -1066,7 +1117,7 @@ int SimpleEntryImpl::ReadDataInternal(bool sync_possible, } void SimpleEntryImpl::WriteDataInternal(int stream_index, - int offset, + int64_t offset, net::IOBuffer* buf, int buf_len, net::CompletionOnceCallback callback, @@ -1099,7 +1150,7 @@ void SimpleEntryImpl::WriteDataInternal(int stream_index, // Since stream 0 data is kept in memory, it will be written immediatly. if (stream_index == 0) { state_ = STATE_IO_PENDING; - SetStream0Data(buf, offset, buf_len, truncate); + SetStream0Data(buf, base::checked_cast(offset), buf_len, truncate); state_ = STATE_READY; if (!callback.is_null()) { base::SequencedTaskRunner::GetCurrentDefault()->PostTask( @@ -1110,7 +1161,7 @@ void SimpleEntryImpl::WriteDataInternal(int stream_index, // Ignore zero-length writes that do not change the file size. if (buf_len == 0) { - int32_t data_size = data_size_[stream_index]; + int64_t data_size = data_size_[stream_index]; if (truncate ? (offset == data_size) : (offset <= data_size)) { if (!callback.is_null()) { base::SequencedTaskRunner::GetCurrentDefault()->PostTask( @@ -1504,7 +1555,7 @@ void SimpleEntryImpl::EntryOperationComplete( void SimpleEntryImpl::ReadOperationComplete( int stream_index, - int offset, + int64_t offset, net::CompletionOnceCallback completion_callback, std::unique_ptr entry_stat, std::unique_ptr read_result) { @@ -1659,28 +1710,28 @@ void SimpleEntryImpl::UpdateDataFromEntryStat( SimpleBackendImpl* backend_ptr = backend_.get(); if (doom_state_ == DOOM_NONE && backend_ptr) { - backend_ptr->index()->UpdateEntrySize( - entry_hash_, base::checked_cast(GetDiskUsage())); + backend_ptr->index()->UpdateEntrySize(entry_hash_, GetDiskUsage()); } } -int64_t SimpleEntryImpl::GetDiskUsage() const { - int64_t file_size = 0; - for (int data_size : data_size_) { - file_size += simple_util::GetFileSizeFromDataSize(key_->size(), data_size); +uint64_t SimpleEntryImpl::GetDiskUsage() const { + uint64_t file_size = 0; + for (int64_t data_size : data_size_) { + file_size += base::checked_cast( + simple_util::GetFileSizeFromDataSize(key_->size(), data_size)); } file_size += sparse_data_size_; return file_size; } void SimpleEntryImpl::ReadFromBuffer(net::GrowableIOBuffer* in_buf, - int offset, + size_t offset, int buf_len, net::IOBuffer* out_buf) { DCHECK_GE(buf_len, 0); - out_buf->span().copy_prefix_from(in_buf->span().subspan( - base::checked_cast(offset), base::checked_cast(buf_len))); + out_buf->span().copy_prefix_from( + in_buf->span().subspan(offset, base::checked_cast(buf_len))); UpdateDataFromEntryStat( SimpleEntryStat(base::Time::Now(), data_size_, sparse_data_size_)); } @@ -1694,30 +1745,37 @@ void SimpleEntryImpl::SetStream0Data(net::IOBuffer* buf, // changes of the headers. Also, support writes to stream 0 that have // different access patterns, as required by the API contract. // All other clients of the Simple Cache are encouraged to use stream 1. + + // stream 0 data size limitation is int32_t max. + CHECK_LE(GetDataSize(0), std::numeric_limits::max()); + CHECK_LE(0, GetDataSize(0)); + CHECK_LE(0, offset); + CHECK_LE(0, buf_len); + size_t u_offset = static_cast(offset); + have_written_[0] = true; - int data_size = GetDataSize(0); + size_t data_size = static_cast(GetDataSize(0)); if (offset == 0 && truncate) { stream_0_data_->SetCapacity(buf_len); - stream_0_data_->span().copy_from( - buf->first(base::checked_cast(buf_len))); + if (buf_len) { + stream_0_data_->span().copy_from( + buf->first(base::checked_cast(buf_len))); + } data_size_[0] = buf_len; } else { - const int buffer_size = - truncate ? offset + buf_len : std::max(offset + buf_len, data_size); - stream_0_data_->SetCapacity(buffer_size); - // If |stream_0_data_| was extended, the extension until offset needs to be + const size_t buffer_size = + truncate ? u_offset + buf_len : std::max(u_offset + buf_len, data_size); + stream_0_data_->SetCapacity(base::checked_cast(buffer_size)); + // If `stream_0_data_` was extended, the extension until offset needs to be // zero-filled. - const int fill_size = offset <= data_size ? 0 : offset - data_size; + const size_t fill_size = u_offset <= data_size ? 0 : u_offset - data_size; if (fill_size > 0) { - std::ranges::fill( - stream_0_data_->span().subspan(base::checked_cast(data_size), - base::checked_cast(fill_size)), - 0); + std::ranges::fill(stream_0_data_->span().subspan(data_size, fill_size), + 0); } if (buf) { - stream_0_data_->span() - .subspan(base::checked_cast(offset)) - .copy_prefix_from(buf->first(base::checked_cast(buf_len))); + stream_0_data_->span().subspan(u_offset).copy_prefix_from( + buf->first(base::checked_cast(buf_len))); } data_size_[0] = buffer_size; } diff --git a/naiveproxy/src/net/disk_cache/simple/simple_entry_impl.h b/naiveproxy/src/net/disk_cache/simple/simple_entry_impl.h index a345e63dd1..5bc42d8093 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_entry_impl.h +++ b/naiveproxy/src/net/disk_cache/simple/simple_entry_impl.h @@ -120,14 +120,14 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry, // GetLastUsed() should not be called in net::APP_CACHE mode since the times // are not updated. base::Time GetLastUsed() const override; - int32_t GetDataSize(int index) const override; + int64_t GetDataSize(int index) const override; int ReadData(int stream_index, - int offset, + int64_t offset, net::IOBuffer* buf, int buf_len, CompletionOnceCallback callback) override; int WriteData(int stream_index, - int offset, + int64_t offset, net::IOBuffer* buf, int buf_len, CompletionOnceCallback callback, @@ -241,13 +241,13 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry, int ReadDataInternal(bool sync_possible, int index, - int offset, + int64_t offset, net::IOBuffer* buf, int buf_len, CompletionOnceCallback callback); void WriteDataInternal(int index, - int offset, + int64_t offset, net::IOBuffer* buf, int buf_len, CompletionOnceCallback callback, @@ -300,7 +300,7 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry, // Called after an asynchronous read. Updates |crc32s_| if possible. void ReadOperationComplete( int stream_index, - int offset, + int64_t offset, CompletionOnceCallback completion_callback, std::unique_ptr entry_stat, std::unique_ptr read_result); @@ -340,20 +340,21 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry, // operations. void UpdateDataFromEntryStat(const SimpleEntryStat& entry_stat); - int64_t GetDiskUsage() const; + uint64_t GetDiskUsage() const; // Completes a read from the stream data kept in memory, logging metrics // and updating metadata. This assumes the caller has already range-checked // offset and buf_len appropriately, and therefore always reads `buf_len` // bytes. void ReadFromBuffer(net::GrowableIOBuffer* in_buf, - int offset, + size_t offset, int buf_len, net::IOBuffer* out_buf); - // Copies data from |buf| to the internal in-memory buffer for stream 0. If - // |truncate| is set to true, the target buffer will be truncated at |offset| - // + |buf_len| before being written. + // Copies data from `buf` to the internal in-memory buffer for stream 0. If + // `truncate` is set to true, the target buffer will be truncated at `offset` + // + `buf_len` before being written. + // `offset` + `buf_len` must be smaller than int32_t max. void SetStream0Data(net::IOBuffer* buf, int offset, int buf_len, @@ -382,7 +383,7 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry, // synchronous entry at the completion of each item of asynchronous IO. // TODO(clamy): Unify last_used_ with data in the index. base::Time last_used_; - std::array data_size_; + std::array data_size_; uint64_t sparse_data_size_ = 0; // Number of times this object has been returned from Backend::OpenEntry() and diff --git a/naiveproxy/src/net/disk_cache/simple/simple_entry_operation.cc b/naiveproxy/src/net/disk_cache/simple/simple_entry_operation.cc index 497f3e3ac6..7ad3035cc0 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_entry_operation.cc +++ b/naiveproxy/src/net/disk_cache/simple/simple_entry_operation.cc @@ -65,7 +65,7 @@ SimpleEntryOperation SimpleEntryOperation::CloseOperation( SimpleEntryOperation SimpleEntryOperation::ReadOperation( SimpleEntryImpl* entry, int index, - int offset, + int64_t offset, int length, net::IOBuffer* buf, CompletionOnceCallback callback) { @@ -78,7 +78,7 @@ SimpleEntryOperation SimpleEntryOperation::ReadOperation( SimpleEntryOperation SimpleEntryOperation::WriteOperation( SimpleEntryImpl* entry, int index, - int offset, + int64_t offset, int length, net::IOBuffer* buf, bool truncate, @@ -147,7 +147,7 @@ SimpleEntryOperation SimpleEntryOperation::DoomOperation( SimpleEntryOperation::SimpleEntryOperation(SimpleEntryImpl* entry, net::IOBuffer* buf, net::CompletionOnceCallback callback, - int offset, + int64_t offset, uint64_t sparse_offset, int length, size_t sparse_length, diff --git a/naiveproxy/src/net/disk_cache/simple/simple_entry_operation.h b/naiveproxy/src/net/disk_cache/simple/simple_entry_operation.h index 0f034f7c29..8a6bb0e004 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_entry_operation.h +++ b/naiveproxy/src/net/disk_cache/simple/simple_entry_operation.h @@ -64,13 +64,13 @@ class SimpleEntryOperation { static SimpleEntryOperation CloseOperation(SimpleEntryImpl* entry); static SimpleEntryOperation ReadOperation(SimpleEntryImpl* entry, int index, - int offset, + int64_t offset, int length, net::IOBuffer* buf, CompletionOnceCallback callback); static SimpleEntryOperation WriteOperation(SimpleEntryImpl* entry, int index, - int offset, + int64_t offset, int length, net::IOBuffer* buf, bool truncate, @@ -111,7 +111,7 @@ class SimpleEntryOperation { OpenEntryIndexEnum index_state() const { return index_state_; } int index() const { return index_; } - int offset() const { return offset_; } + int64_t offset() const { return offset_; } int64_t sparse_offset() const { return sparse_offset_; } int length() const { return length_; } size_t sparse_length() const { return sparse_length_; } @@ -123,7 +123,7 @@ class SimpleEntryOperation { SimpleEntryOperation(SimpleEntryImpl* entry, net::IOBuffer* buf, CompletionOnceCallback callback, - int offset, + int64_t offset, uint64_t sparse_offset, int length, size_t sparse_length, @@ -143,7 +143,7 @@ class SimpleEntryOperation { EntryResultState entry_result_state_; // Used in write and read operations. - const int offset_; + const int64_t offset_; const int64_t sparse_offset_; const int length_; const size_t sparse_length_; diff --git a/naiveproxy/src/net/disk_cache/simple/simple_index.cc b/naiveproxy/src/net/disk_cache/simple/simple_index.cc index bd9c209691..fd53e5e5c7 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_index.cc +++ b/naiveproxy/src/net/disk_cache/simple/simple_index.cc @@ -48,7 +48,7 @@ constexpr int kWriteToDiskOnBackgroundDelayMSecs = 100; // is left. constexpr uint32_t kEvictionMarginDivisor = 20; -constexpr uint32_t kBytesInKb = 1024; +constexpr uint32_t kBytesInMiB = 1024 * 1024; // This is added to the size of each entry before using the size // to determine which entries to evict first. It's basically an @@ -110,7 +110,7 @@ EntryMetadata::EntryMetadata(base::Time last_used_time, SetLastUsedTime(last_used_time); } -EntryMetadata::EntryMetadata(int32_t trailer_prefetch_size, +EntryMetadata::EntryMetadata(uint32_t trailer_prefetch_size, base::StrictNumeric entry_size) : trailer_prefetch_size_(0), entry_size_256b_chunks_(0), @@ -131,7 +131,7 @@ base::Time EntryMetadata::GetLastUsedTime() const { base::Seconds(last_used_time_seconds_since_epoch_); } -void EntryMetadata::SetLastUsedTime(const base::Time& last_used_time) { +void EntryMetadata::SetLastUsedTime(base::Time last_used_time) { // Preserve nullity. if (last_used_time.is_null()) { last_used_time_seconds_since_epoch_ = 0; @@ -145,13 +145,15 @@ void EntryMetadata::SetLastUsedTime(const base::Time& last_used_time) { last_used_time_seconds_since_epoch_ = 1; } -int32_t EntryMetadata::GetTrailerPrefetchSize() const { +uint32_t EntryMetadata::GetTrailerPrefetchSize() const { return trailer_prefetch_size_; } -void EntryMetadata::SetTrailerPrefetchSize(int32_t size) { - if (size <= 0) +void EntryMetadata::SetTrailerPrefetchSize(uint32_t size) { + if (size == 0) { return; + } + trailer_prefetch_size_ = size; } @@ -216,8 +218,8 @@ bool EntryMetadata::Deserialize(net::CacheType cache_type, if (cache_type == net::APP_CACHE) { if (app_cache_has_trailer_prefetch_size) { - int32_t trailer_prefetch_size = 0; - base::CheckedNumeric numeric_size(tmp_time_or_prefetch_size); + uint32_t trailer_prefetch_size = 0; + base::CheckedNumeric numeric_size(tmp_time_or_prefetch_size); if (numeric_size.AssignIfValid(&trailer_prefetch_size)) { SetTrailerPrefetchSize(trailer_prefetch_size); } @@ -556,14 +558,15 @@ void SimpleIndex::SetTrailerPrefetchSize(uint64_t entry_hash, int32_t size) { auto it = entries_set_.find(entry_hash); if (it == entries_set_.end()) return; - int32_t original_size = it->second.GetTrailerPrefetchSize(); + uint32_t original_size = it->second.GetTrailerPrefetchSize(); it->second.SetTrailerPrefetchSize(size); - if (original_size != it->second.GetTrailerPrefetchSize()) + if (original_size != it->second.GetTrailerPrefetchSize()) { PostponeWritingToDisk(); + } } bool SimpleIndex::UpdateEntrySize(uint64_t entry_hash, - base::StrictNumeric entry_size) { + base::StrictNumeric entry_size) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); auto it = entries_set_.find(entry_hash); if (it == entries_set_.end()) @@ -618,11 +621,11 @@ void SimpleIndex::PostponeWritingToDisk() { bool SimpleIndex::UpdateEntryIteratorSize( EntrySet::iterator* it, - base::StrictNumeric entry_size) { + base::StrictNumeric entry_size) { // Update the total cache size with the new entry size. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_GE(cache_size_, (*it)->second.GetEntrySize()); - uint32_t original_size = (*it)->second.GetEntrySize(); + uint64_t original_size = (*it)->second.GetEntrySize(); // If SetEntrySize fails, we cannot update the entry iterator correctly. if (!(*it)->second.SetEntrySize(entry_size)) { @@ -677,11 +680,11 @@ void SimpleIndex::MergeInitializingSet( SIMPLE_CACHE_UMA(CUSTOM_COUNTS, "IndexNumEntriesOnInit", cache_type_, entries_set_.size(), 0, 100000, 50); SIMPLE_CACHE_UMA( - MEMORY_KB, "CacheSizeOnInit", cache_type_, - static_cast(cache_size_ / kBytesInKb)); + MEMORY_MEDIUM_MB, "CacheSizeOnInit2", cache_type_, + static_cast(cache_size_ / kBytesInMiB)); SIMPLE_CACHE_UMA( - MEMORY_KB, "MaxCacheSizeOnInit", cache_type_, - static_cast(max_size_ / kBytesInKb)); + MEMORY_MEDIUM_MB, "MaxCacheSizeOnInit2", cache_type_, + static_cast(max_size_ / kBytesInMiB)); // Run all callbacks waiting for the index to come up. for (auto& callback : to_run_when_initialized_) { diff --git a/naiveproxy/src/net/disk_cache/simple/simple_index.h b/naiveproxy/src/net/disk_cache/simple/simple_index.h index 1f9c52fee4..b6ca8a4b46 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_index.h +++ b/naiveproxy/src/net/disk_cache/simple/simple_index.h @@ -51,14 +51,14 @@ class NET_EXPORT_PRIVATE EntryMetadata { EntryMetadata(); EntryMetadata(base::Time last_used_time, base::StrictNumeric entry_size); - EntryMetadata(int32_t trailer_prefetch_size, + EntryMetadata(uint32_t trailer_prefetch_size, base::StrictNumeric entry_size); base::Time GetLastUsedTime() const; - void SetLastUsedTime(const base::Time& last_used_time); + void SetLastUsedTime(base::Time last_used_time); - int32_t GetTrailerPrefetchSize() const; - void SetTrailerPrefetchSize(int32_t size); + uint32_t GetTrailerPrefetchSize() const; + void SetTrailerPrefetchSize(uint32_t size); uint32_t RawTimeForSorting() const { return last_used_time_seconds_since_epoch_; @@ -103,7 +103,7 @@ class NET_EXPORT_PRIVATE EntryMetadata { // how much entry file trailer should be prefetched when its opened. union { uint32_t last_used_time_seconds_since_epoch_; - int32_t trailer_prefetch_size_; // in bytes + uint32_t trailer_prefetch_size_; // in bytes }; uint32_t entry_size_256b_chunks_ : 30; // in 256-byte blocks, rounded up. @@ -175,7 +175,7 @@ class NET_EXPORT_PRIVATE SimpleIndex final { // index. This should be the total disk-file size including all streams of the // entry. bool UpdateEntrySize(uint64_t entry_hash, - base::StrictNumeric entry_size); + base::StrictNumeric entry_size); using EntrySet = absl::flat_hash_map; @@ -259,7 +259,7 @@ class NET_EXPORT_PRIVATE SimpleIndex final { // Update the size of the entry pointed to by the given iterator. Return // true if the new size actually results in a change. bool UpdateEntryIteratorSize(EntrySet::iterator* it, - base::StrictNumeric entry_size); + base::StrictNumeric entry_size); // Must run on IO Thread. void MergeInitializingSet(std::unique_ptr load_result); diff --git a/naiveproxy/src/net/disk_cache/simple/simple_synchronous_entry.cc b/naiveproxy/src/net/disk_cache/simple/simple_synchronous_entry.cc index bf7db72f41..6226daa872 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_synchronous_entry.cc +++ b/naiveproxy/src/net/disk_cache/simple/simple_synchronous_entry.cc @@ -109,14 +109,14 @@ int FileIndexForSubFile(SimpleFileTracker::SubFile sub_file) { // Helper class to track a range of data prefetched from a file. class SimpleSynchronousEntry::PrefetchData final { public: - explicit PrefetchData(size_t file_size) + explicit PrefetchData(uint64_t file_size) : file_size_(file_size), earliest_requested_offset_(file_size) {} // Returns true if the specified range within the file has been completely // prefetched. Returns false if any part of the range has not been // prefetched. - bool HasData(size_t offset, size_t length) { - size_t end = 0; + bool HasData(uint64_t offset, size_t length) { + uint64_t end = 0; if (!base::CheckAdd(offset, length).AssignIfValid(&end)) return false; UpdateEarliestOffset(offset); @@ -128,13 +128,15 @@ class SimpleSynchronousEntry::PrefetchData final { // destination buffer. If the range is not wholely contained within // the prefetch buffer than no data will be written to the target // buffer. Returns true if the range has been copied. - bool ReadData(size_t offset, size_t length, base::span dest) { + bool ReadData(uint64_t offset, size_t length, base::span dest) { if (!length) return true; if (!HasData(offset, length)) return false; DCHECK(offset >= offset_in_file_); - size_t buffer_offset = offset - offset_in_file_; + // `offset` could be larger than size_t but `buffer_offset` must be within + // size_t range. + size_t buffer_offset = base::checked_cast(offset - offset_in_file_); dest.copy_prefix_from( base::as_byte_span(buffer_).subspan(buffer_offset, length)); return true; @@ -143,7 +145,7 @@ class SimpleSynchronousEntry::PrefetchData final { // Populate the prefetch buffer from the given file and range. Returns // true if the data is successfully read. bool PrefetchFromFile(SimpleFileTracker::FileHandle* file, - size_t offset, + uint64_t offset, size_t length) { DCHECK(file); if (!buffer_.empty()) { @@ -162,26 +164,28 @@ class SimpleSynchronousEntry::PrefetchData final { // Return how much trailing data has been requested via HasData() or // ReadData(). The intent is that this value can be used to tune // future prefetching behavior. - size_t GetDesiredTrailerPrefetchSize() const { - return file_size_ - earliest_requested_offset_; + uint32_t GetDesiredTrailerPrefetchSize() const { + // Trailer prefetch size must be within uint32_t. + return std::min(std::numeric_limits::max(), + (file_size_ - earliest_requested_offset_)); } private: // Track the earliest offset requested in order to return an optimal trailer // prefetch amount in GetDesiredTrailerPrefetchSize(). - void UpdateEarliestOffset(size_t offset) { + void UpdateEarliestOffset(uint64_t offset) { DCHECK_LE(earliest_requested_offset_, file_size_); earliest_requested_offset_ = std::min(earliest_requested_offset_, offset); } - const size_t file_size_; + const uint64_t file_size_; // Prefer to read the prefetch data into a stack buffer to minimize // memory pressure on the OS disk cache. absl::InlinedVector buffer_; - size_t offset_in_file_ = 0; + uint64_t offset_in_file_ = 0; - size_t earliest_requested_offset_; + uint64_t earliest_requested_offset_; }; class SimpleSynchronousEntry::ScopedFileOperationsBinding final { @@ -224,11 +228,11 @@ constexpr base::FeatureParam kSimpleCacheTrailerPrefetchSpeculativeBytes{ &kSimpleCachePrefetchExperiment, kSimpleCacheTrailerPrefetchSpeculativeBytesParam, 0}; -int GetSimpleCacheFullPrefetchSize() { +uint32_t GetSimpleCacheFullPrefetchSize() { return kSimpleCacheFullPrefetchSize.Get(); } -int GetSimpleCacheTrailerPrefetchSize(int hint_size) { +uint32_t GetSimpleCacheTrailerPrefetchSize(int hint_size) { if (hint_size > 0) return hint_size; return kSimpleCacheTrailerPrefetchSpeculativeBytes.Get(); @@ -236,7 +240,7 @@ int GetSimpleCacheTrailerPrefetchSize(int hint_size) { SimpleEntryStat::SimpleEntryStat( base::Time last_used, - const std::array& data_size, + const std::array& data_size, const uint64_t sparse_data_size) : last_used_(last_used), data_size_(data_size), @@ -246,35 +250,34 @@ SimpleEntryStat::SimpleEntryStat( // since this version of the cache always writes it. In the read case, it may // not be present and these methods can't be relied upon. -int SimpleEntryStat::GetOffsetInFile(size_t key_length, - int offset, - int stream_index) const { - const size_t headers_size = sizeof(SimpleFileHeader) + key_length; - const size_t additional_offset = +int64_t SimpleEntryStat::GetOffsetInFile(size_t key_length, + int64_t offset, + int stream_index) const { + const int64_t headers_size = + sizeof(SimpleFileHeader) + base::checked_cast(key_length); + const int64_t additional_offset = stream_index == 0 ? data_size_[1] + sizeof(SimpleFileEOF) : 0; return headers_size + offset + additional_offset; } -int SimpleEntryStat::GetEOFOffsetInFile(size_t key_length, - int stream_index) const { - size_t additional_offset; - if (stream_index != 0) - additional_offset = 0; - else - additional_offset = sizeof(net::SHA256HashValue); +int64_t SimpleEntryStat::GetEOFOffsetInFile(size_t key_length, + int stream_index) const { + const int64_t additional_offset = + stream_index == 0 ? sizeof(net::SHA256HashValue) : 0; return additional_offset + GetOffsetInFile(key_length, data_size_[stream_index], stream_index); } -int SimpleEntryStat::GetLastEOFOffsetInFile(size_t key_length, - int stream_index) const { - if (stream_index == 1) +int64_t SimpleEntryStat::GetLastEOFOffsetInFile(size_t key_length, + int stream_index) const { + if (stream_index == 1) { return GetEOFOffsetInFile(key_length, 0); + } return GetEOFOffsetInFile(key_length, stream_index); } int64_t SimpleEntryStat::GetFileSize(size_t key_length, int file_index) const { - int32_t total_data_size; + int64_t total_data_size; if (file_index == 0) { total_data_size = data_size_[0] + data_size_[1] + sizeof(net::SHA256HashValue) + sizeof(SimpleFileEOF); @@ -306,12 +309,12 @@ SimpleSynchronousEntry::CRCRecord::CRCRecord(int index_p, : index(index_p), has_crc32(has_crc32_p), data_crc32(data_crc32_p) {} SimpleSynchronousEntry::ReadRequest::ReadRequest(int index_p, - int offset_p, + int64_t offset_p, int buf_len_p) : index(index_p), offset(offset_p), buf_len(buf_len_p) {} SimpleSynchronousEntry::WriteRequest::WriteRequest(int index_p, - int offset_p, + int64_t offset_p, int buf_len_p, uint32_t previous_crc32_p, bool truncate_p, @@ -337,7 +340,7 @@ void SimpleSynchronousEntry::OpenEntry( const uint64_t entry_hash, SimpleFileTracker* file_tracker, std::unique_ptr file_operations, - int32_t trailer_prefetch_size, + uint32_t trailer_prefetch_size, SimpleEntryCreationResults* out_results) { base::TimeTicks start_sync_open_entry = base::TimeTicks::Now(); @@ -383,7 +386,7 @@ void SimpleSynchronousEntry::CreateEntry( auto sync_entry = std::make_unique( cache_type, path, key, entry_hash, file_tracker, - std::move(file_operations), -1); + std::move(file_operations), /*trailer_prefetch_size=*/0); { BackendFileOperations* bound_file_operations = nullptr; ScopedFileOperationsBinding binding(sync_entry.get(), @@ -416,7 +419,7 @@ void SimpleSynchronousEntry::OpenOrCreateEntry( bool optimistic_create, SimpleFileTracker* file_tracker, std::unique_ptr file_operations, - int32_t trailer_prefetch_size, + uint32_t trailer_prefetch_size, SimpleEntryCreationResults* out_results) { base::TimeTicks start = base::TimeTicks::Now(); if (index_state == INDEX_MISS) { @@ -656,7 +659,7 @@ void SimpleSynchronousEntry::WriteData(const WriteRequest& in_entry_op, return; } } - int offset = in_entry_op.offset; + int64_t offset = in_entry_op.offset; int buf_len = in_entry_op.buf_len; bool truncate = in_entry_op.truncate; bool doomed = in_entry_op.doomed; @@ -727,7 +730,7 @@ void SimpleSynchronousEntry::WriteData(const WriteRequest& in_entry_op, index, std::max(out_entry_stat->data_size(index), offset + buf_len)); } else { out_entry_stat->set_data_size(index, offset + buf_len); - int file_eof_offset = + const int64_t file_eof_offset = out_entry_stat->GetLastEOFOffsetInFile(key_size, index); if (!file->SetLength(file_eof_offset)) { RecordWriteResult(cache_type_, SYNC_WRITE_RESULT_TRUNCATE_FAILURE); @@ -1007,7 +1010,8 @@ int SimpleSynchronousEntry::CheckEOFRecord( uint32_t expected_crc32) { DCHECK(initialized_); SimpleFileEOF eof_record; - int file_offset = entry_stat.GetEOFOffsetInFile(key_->size(), stream_index); + int64_t file_offset = + entry_stat.GetEOFOffsetInFile(key_->size(), stream_index); int file_index = GetFileIndexFromStreamIndex(stream_index); int rv = GetEOFRecordData(file, nullptr, file_index, file_offset, &eof_record); @@ -1037,18 +1041,28 @@ int SimpleSynchronousEntry::PreReadStreamPayload( SimpleStreamPrefetchData* out) { DCHECK(stream_index == 0 || stream_index == 1); - int stream_size = entry_stat.data_size(stream_index); - int read_size = stream_size + extra_size; + int64_t stream_size = entry_stat.data_size(stream_index); + + // The data must be on GrowableIOBuffer. + // TODO(crbug.com/433856002): int32 max is too large for stream 0 where stream + // 0 needs consecutive memory space. Set the proper size limitation. + if (stream_size + extra_size > std::numeric_limits::max() || + stream_size < 0 || extra_size < 0) { + return net::ERR_INVALID_ARGUMENT; + } + + int read_size = static_cast(stream_size + extra_size); out->data = base::MakeRefCounted(); out->data->SetCapacity(read_size); - int file_offset = entry_stat.GetOffsetInFile(key_->size(), 0, stream_index); + int64_t file_offset = + entry_stat.GetOffsetInFile(key_->size(), 0, stream_index); if (!ReadFromFileOrPrefetched(file, prefetch_data, 0, file_offset, read_size, out->data->span())) { return net::ERR_FAILED; } // Check the CRC32. - uint32_t expected_crc32 = simple_util::Crc32(out->data->data(), stream_size); + uint32_t expected_crc32 = simple_util::Crc32(out->data->first(stream_size)); if ((eof_record.flags & SimpleFileEOF::FLAG_HAS_CRC32) && eof_record.data_crc32 != expected_crc32) { DVLOG(1) << "EOF record had bad crc."; @@ -1090,9 +1104,11 @@ void SimpleSynchronousEntry::Close( if (stream_index == 0) { // Write stream 0 data. - int stream_0_offset = entry_stat.GetOffsetInFile(key.size(), 0, 0); + int64_t stream_0_offset = entry_stat.GetOffsetInFile(key.size(), 0, 0); + // Stream 0 data must be within int range. + CHECK_LE(entry_stat.data_size(0), std::numeric_limits::max()); if (!file->WriteAndCheck(stream_0_offset, - stream_0_data->first(base::checked_cast( + stream_0_data->first(static_cast( entry_stat.data_size(0))))) { RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE); DVLOG(1) << "Could not write stream 0 data."; @@ -1110,8 +1126,8 @@ void SimpleSynchronousEntry::Close( // if it didn't change if stream 0's position on disk got changed due to // stream 1 write). if (!crc_record.has_crc32) { - crc_record.data_crc32 = - simple_util::Crc32(stream_0_data->data(), entry_stat.data_size(0)); + crc_record.data_crc32 = simple_util::Crc32( + stream_0_data->first(static_cast(entry_stat.data_size(0)))); crc_record.has_crc32 = true; } @@ -1120,7 +1136,10 @@ void SimpleSynchronousEntry::Close( } SimpleFileEOF eof_record; - eof_record.stream_size = entry_stat.data_size(stream_index); + eof_record.stream_size = + stream_index == 0 + ? static_cast(entry_stat.data_size(stream_index)) + : 0; eof_record.final_magic_number = kSimpleFinalMagicNumber; eof_record.flags = 0; if (crc_record.has_crc32) @@ -1128,7 +1147,8 @@ void SimpleSynchronousEntry::Close( if (stream_index == 0) eof_record.flags |= SimpleFileEOF::FLAG_HAS_KEY_SHA256; eof_record.data_crc32 = crc_record.data_crc32; - int eof_offset = entry_stat.GetEOFOffsetInFile(key.size(), stream_index); + int64_t eof_offset = + entry_stat.GetEOFOffsetInFile(key.size(), stream_index); // If stream 0 changed size, the file needs to be resized, otherwise the // next open will yield wrong stream sizes. On stream 1 and stream 2 proper // resizing of the file is handled in SimpleSynchronousEntry::WriteData(). @@ -1177,7 +1197,7 @@ SimpleSynchronousEntry::SimpleSynchronousEntry( const uint64_t entry_hash, SimpleFileTracker* file_tracker, std::unique_ptr unbound_file_operations, - int32_t trailer_prefetch_size) + uint32_t trailer_prefetch_size) : cache_type_(cache_type), path_(path), entry_file_key_(entry_hash), @@ -1308,11 +1328,8 @@ bool SimpleSynchronousEntry::OpenFiles(BackendFileOperations* file_operations, // 0, stream 1 and one EOF record. The exact distribution of sizes between // stream 1 and stream 0 is only determined after reading the EOF record // for stream 0 in ReadAndValidateStream0AndMaybe1. - if (!base::IsValueInRangeForNumericType(file_info.size)) { - RecordSyncOpenResult(cache_type_, OPEN_ENTRY_INVALID_FILE_LENGTH); - return false; - } - out_entry_stat->set_data_size(i + 1, static_cast(file_info.size)); + + out_entry_stat->set_data_size(i + 1, file_info.size); } return true; @@ -1484,7 +1501,7 @@ int SimpleSynchronousEntry::InitializeForOpen( } else { out_entry_stat->set_data_size( 2, GetDataSizeFromFileSize(key_size, out_entry_stat->data_size(2))); - const int32_t data_size_2 = out_entry_stat->data_size(2); + const int64_t data_size_2 = out_entry_stat->data_size(2); int ret_value_stream_2 = net::OK; if (data_size_2 < 0) { DLOG(WARNING) << "Stream 2 file is too small."; @@ -1494,7 +1511,7 @@ int SimpleSynchronousEntry::InitializeForOpen( SimpleFileEOF eof_record; SimpleFileTracker::FileHandle file = file_tracker_->Acquire( file_operations, this, SubFileForFileIndex(i)); - int file_offset = + int64_t file_offset = out_entry_stat->GetEOFOffsetInFile(key_size, 2 /*stream index*/); ret_value_stream_2 = GetEOFRecordData(file.get(), nullptr, i, file_offset, &eof_record); @@ -1581,13 +1598,17 @@ int SimpleSynchronousEntry::InitializeForCreate( int SimpleSynchronousEntry::ReadAndValidateStream0AndMaybe1( BackendFileOperations* file_operations, - int file_size, + int64_t file_size, SimpleEntryStat* out_entry_stat, std::array& stream_prefetch_data) { SimpleFileTracker::FileHandle file = file_tracker_->Acquire(file_operations, this, SubFileForFileIndex(0)); - if (!file.IsOK()) + if (!file.IsOK()) { return net::ERR_FAILED; + } + + // `file_size` must be a non-negative value. + uint64_t u_file_size = base::checked_cast(file_size); // We may prefetch data from file in a couple cases: // 1) If the file is small enough we may prefetch it entirely. @@ -1603,30 +1624,36 @@ int SimpleSynchronousEntry::ReadAndValidateStream0AndMaybe1( // Determine a threshold for fully prefetching the entire entry file. If // the entry file is less than or equal to this number of bytes it will // be fully prefetched. - int full_prefetch_size = GetSimpleCacheFullPrefetchSize(); + uint32_t full_prefetch_size = GetSimpleCacheFullPrefetchSize(); // Determine how much trailer data to prefetch. If the full file prefetch // does not trigger then this is the number of bytes to read from the end // of the file in a single file operation. Ideally the trailer prefetch // will contain at least stream 0 and its EOF record. - int trailer_prefetch_size = + uint32_t trailer_prefetch_size = GetSimpleCacheTrailerPrefetchSize(trailer_prefetch_size_); OpenPrefetchMode prefetch_mode = OPEN_PREFETCH_NONE; - if (file_size <= full_prefetch_size || file_size <= trailer_prefetch_size) { + if (u_file_size <= full_prefetch_size || + u_file_size <= trailer_prefetch_size) { // Prefetch the entire file. prefetch_mode = OPEN_PREFETCH_FULL; RecordOpenPrefetchMode(cache_type_, prefetch_mode); - if (!prefetch_data.PrefetchFromFile(&file, 0, file_size)) + if (!prefetch_data.PrefetchFromFile(&file, 0, u_file_size)) { return net::ERR_FAILED; + } } else if (trailer_prefetch_size > 0) { // Prefetch trailer data from the end of the file. prefetch_mode = OPEN_PREFETCH_TRAILER; RecordOpenPrefetchMode(cache_type_, prefetch_mode); - size_t length = std::min(trailer_prefetch_size, file_size); - size_t offset = file_size - length; - if (!prefetch_data.PrefetchFromFile(&file, offset, length)) + // `trailer_prefetch_size is in uint32_t range, so `length` is safe to cast + // to size_t. + size_t length = std::min( + static_cast(trailer_prefetch_size), u_file_size); + uint64_t offset = u_file_size - length; + if (!prefetch_data.PrefetchFromFile(&file, offset, length)) { return net::ERR_FAILED; + } } else { // Do no prefetching. RecordOpenPrefetchMode(cache_type_, prefetch_mode); @@ -1637,13 +1664,15 @@ int SimpleSynchronousEntry::ReadAndValidateStream0AndMaybe1( SimpleFileEOF stream_0_eof; int rv = GetEOFRecordData( file.get(), &prefetch_data, /* file_index = */ 0, - /* file_offset = */ file_size - sizeof(SimpleFileEOF), &stream_0_eof); - if (rv != net::OK) + /* file_offset = */ u_file_size - sizeof(SimpleFileEOF), &stream_0_eof); + if (rv != net::OK) { return rv; + } - int32_t stream_0_size = stream_0_eof.stream_size; - if (stream_0_size < 0 || stream_0_size > file_size) + int32_t stream_0_size = static_cast(stream_0_eof.stream_size); + if (stream_0_size > file_size) { return net::ERR_FAILED; + } out_entry_stat->set_data_size(0, stream_0_size); // Calculate size for stream 1, now we know stream 0's. @@ -1651,16 +1680,16 @@ int SimpleSynchronousEntry::ReadAndValidateStream0AndMaybe1( bool has_key_sha256 = (stream_0_eof.flags & SimpleFileEOF::FLAG_HAS_KEY_SHA256) == SimpleFileEOF::FLAG_HAS_KEY_SHA256; - int extra_post_stream_0_read = 0; - if (has_key_sha256) - extra_post_stream_0_read += sizeof(net::SHA256HashValue); + const int extra_post_stream_0_read = + has_key_sha256 ? sizeof(net::SHA256HashValue) : 0; const std::string& key = *key_; - int32_t stream1_size = file_size - 2 * sizeof(SimpleFileEOF) - stream_0_size - + int64_t stream1_size = file_size - 2 * sizeof(SimpleFileEOF) - stream_0_size - sizeof(SimpleFileHeader) - key.size() - extra_post_stream_0_read; - if (stream1_size < 0 || stream1_size > file_size) + if (stream1_size < 0 || stream1_size > file_size) { return net::ERR_FAILED; + } out_entry_stat->set_data_size(1, stream1_size); @@ -1668,8 +1697,9 @@ int SimpleSynchronousEntry::ReadAndValidateStream0AndMaybe1( rv = PreReadStreamPayload(file.get(), &prefetch_data, /* stream_index = */ 0, extra_post_stream_0_read, *out_entry_stat, stream_0_eof, &stream_prefetch_data[0]); - if (rv != net::OK) + if (rv != net::OK) { return rv; + } // Note the exact range needed in order to read the EOF record and stream 0. // In APP_CACHE mode this will be stored directly in the index so we can @@ -1679,26 +1709,28 @@ int SimpleSynchronousEntry::ReadAndValidateStream0AndMaybe1( // If prefetch buffer is available, and we have sha256(key) (so we don't need // to look at the header), extract out stream 1 info as well. - int stream_1_offset = out_entry_stat->GetOffsetInFile( + int64_t stream_1_offset = out_entry_stat->GetOffsetInFile( key.size(), /* offset= */ 0, /* stream_index = */ 1); - int stream_1_read_size = + int64_t stream_1_read_size = sizeof(SimpleFileEOF) + out_entry_stat->data_size(/* stream_index = */ 1); if (has_key_sha256 && prefetch_data.HasData(stream_1_offset, stream_1_read_size)) { SimpleFileEOF stream_1_eof; - int stream_1_eof_offset = + int64_t stream_1_eof_offset = out_entry_stat->GetEOFOffsetInFile(key.size(), /* stream_index = */ 1); rv = GetEOFRecordData(file.get(), &prefetch_data, /* file_index = */ 0, stream_1_eof_offset, &stream_1_eof); - if (rv != net::OK) + if (rv != net::OK) { return rv; + } rv = PreReadStreamPayload(file.get(), &prefetch_data, /* stream_index = */ 1, /* extra_size = */ 0, *out_entry_stat, stream_1_eof, &stream_prefetch_data[1]); - if (rv != net::OK) + if (rv != net::OK) { return rv; + } } // If present, check the key SHA256. @@ -1706,7 +1738,7 @@ int SimpleSynchronousEntry::ReadAndValidateStream0AndMaybe1( auto hash_value = crypto::hash::Sha256(key); if (base::byte_span_from_ref(hash_value) != stream_prefetch_data[0].data->span().subspan( - static_cast(stream_0_size), sizeof(hash_value))) { + static_cast(stream_0_size), sizeof(hash_value))) { return net::ERR_FAILED; } @@ -1727,38 +1759,29 @@ bool SimpleSynchronousEntry::ReadFromFileOrPrefetched( base::File* file, PrefetchData* prefetch_data, int file_index, - int offset, - int size, + int64_t offset, + size_t size, base::span dest) { if (offset < 0 || size < 0) return false; if (size == 0) return true; - base::CheckedNumeric start(offset); - size_t start_numeric; - if (!start.AssignIfValid(&start_numeric)) - return false; - - base::CheckedNumeric length(size); - size_t length_numeric; - if (!length.AssignIfValid(&length_numeric)) - return false; - // First try to extract the desired range from the PrefetchData. if (file_index == 0 && prefetch_data && - prefetch_data->ReadData(start_numeric, length_numeric, dest)) { + prefetch_data->ReadData(base::checked_cast(offset), size, + dest)) { return true; } // If we have not prefetched the range then we must read it from disk. - return file->ReadAndCheck(start_numeric, dest.first(length_numeric)); + return file->ReadAndCheck(offset, dest.first(size)); } int SimpleSynchronousEntry::GetEOFRecordData(base::File* file, PrefetchData* prefetch_data, int file_index, - int file_offset, + int64_t file_offset, SimpleFileEOF* eof_record) { if (!ReadFromFileOrPrefetched(file, prefetch_data, file_index, file_offset, sizeof(SimpleFileEOF), diff --git a/naiveproxy/src/net/disk_cache/simple/simple_synchronous_entry.h b/naiveproxy/src/net/disk_cache/simple/simple_synchronous_entry.h index db62f7b855..6c7a74b08e 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_synchronous_entry.h +++ b/naiveproxy/src/net/disk_cache/simple/simple_synchronous_entry.h @@ -60,19 +60,21 @@ struct RangeResult; class NET_EXPORT_PRIVATE SimpleEntryStat { public: SimpleEntryStat(base::Time last_used, - const std::array& data_size, + const std::array& data_size, const uint64_t sparse_data_size); - int GetOffsetInFile(size_t key_length, int offset, int stream_index) const; - int GetEOFOffsetInFile(size_t key_length, int stream_index) const; - int GetLastEOFOffsetInFile(size_t key_length, int file_index) const; + int64_t GetOffsetInFile(size_t key_length, + int64_t offset, + int stream_index) const; + int64_t GetEOFOffsetInFile(size_t key_length, int stream_index) const; + int64_t GetLastEOFOffsetInFile(size_t key_length, int file_index) const; int64_t GetFileSize(size_t key_length, int file_index) const; base::Time last_used() const { return last_used_; } void set_last_used(base::Time last_used) { last_used_ = last_used; } - int32_t data_size(int stream_index) const { return data_size_[stream_index]; } - void set_data_size(int stream_index, int data_size) { + int64_t data_size(int stream_index) const { return data_size_[stream_index]; } + void set_data_size(int stream_index, int64_t data_size) { data_size_[stream_index] = data_size; } @@ -83,7 +85,7 @@ class NET_EXPORT_PRIVATE SimpleEntryStat { private: base::Time last_used_; - std::array data_size_; + std::array data_size_; uint64_t sparse_data_size_; }; @@ -107,7 +109,7 @@ struct SimpleEntryCreationResults { std::array stream_prefetch_data; SimpleEntryStat entry_stat; - int32_t computed_trailer_prefetch_size = -1; + uint32_t computed_trailer_prefetch_size = 0; int result = net::OK; bool created = false; }; @@ -132,9 +134,9 @@ class SimpleSynchronousEntry { struct ReadRequest { // Also sets request_update_crc to false. - ReadRequest(int index_p, int offset_p, int buf_len_p); + ReadRequest(int index_p, int64_t offset_p, int buf_len_p); int index; - int offset; + int64_t offset; int buf_len; // Partial CRC of data immediately preceeding this read. Only relevant if @@ -153,14 +155,14 @@ class SimpleSynchronousEntry { struct WriteRequest { WriteRequest(int index_p, - int offset_p, + int64_t offset_p, int buf_len_p, uint32_t previous_crc32_p, bool truncate_p, bool doomed_p, bool request_update_crc_p); int index; - int offset; + int64_t offset; int buf_len; uint32_t previous_crc32; bool truncate; @@ -189,7 +191,7 @@ class SimpleSynchronousEntry { uint64_t entry_hash, SimpleFileTracker* simple_file_tracker, std::unique_ptr file_operations, - int32_t stream_0_size); + uint32_t trailer_prefetch_size); // Like Entry, the SimpleSynchronousEntry self releases when Close() is // called, but sometimes temporary ones are kept in unique_ptr. @@ -204,7 +206,7 @@ class SimpleSynchronousEntry { uint64_t entry_hash, SimpleFileTracker* file_tracker, std::unique_ptr file_operations, - int32_t trailer_prefetch_size, + uint32_t trailer_prefetch_size, SimpleEntryCreationResults* out_results); static void CreateEntry( @@ -225,7 +227,7 @@ class SimpleSynchronousEntry { bool optimistic_create, SimpleFileTracker* file_tracker, std::unique_ptr file_operations, - int32_t trailer_prefetch_size, + uint32_t trailer_prefetch_size, SimpleEntryCreationResults* out_results); // Renames the entry on the file system, making it no longer possible to open @@ -307,7 +309,7 @@ class SimpleSynchronousEntry { NET_EXPORT_PRIVATE base::FilePath GetFilenameForSubfile( SimpleFileTracker::SubFile sub_file) const; - int32_t computed_trailer_prefetch_size() const { + uint32_t computed_trailer_prefetch_size() const { return computed_trailer_prefetch_size_; } @@ -385,7 +387,7 @@ class SimpleSynchronousEntry { // crc, but might decide not to. int ReadAndValidateStream0AndMaybe1( BackendFileOperations* file_operations, - int file_size, + int64_t file_size, SimpleEntryStat* out_entry_stat, std::array& stream_prefetch_data); @@ -396,7 +398,7 @@ class SimpleSynchronousEntry { int GetEOFRecordData(base::File* file, PrefetchData* prefetch_data, int file_index, - int file_offset, + int64_t file_offset, SimpleFileEOF* eof_record); // Reads either from |file_0_prefetch| or |file|. @@ -404,8 +406,8 @@ class SimpleSynchronousEntry { bool ReadFromFileOrPrefetched(base::File* file, PrefetchData* prefetch_data, int file_index, - int offset, - int size, + int64_t offset, + size_t size, base::span dest); // Extracts out the payload of stream |stream_index|, reading either from @@ -515,13 +517,13 @@ class SimpleSynchronousEntry { // prefetched in order to read the EOF record and stream 0. This is // a hint from the index and may not be exactly right. -1 if we // don't have a hinted value. - int32_t trailer_prefetch_size_; + uint32_t trailer_prefetch_size_; // The exact number of trailing bytes that were needed to read the // EOF record and stream 0 when the entry was actually opened. This // may be different from the trailer_prefetch_size_ hint and is // propagated back to the index in order to optimize the next open. - int32_t computed_trailer_prefetch_size_ = -1; + uint32_t computed_trailer_prefetch_size_ = 0; // True if the corresponding stream is empty and therefore no on-disk file // was created to store it. diff --git a/naiveproxy/src/net/disk_cache/simple/simple_util.cc b/naiveproxy/src/net/disk_cache/simple/simple_util.cc index 1d15a493f1..ac20cba388 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_util.cc +++ b/naiveproxy/src/net/disk_cache/simple/simple_util.cc @@ -86,13 +86,13 @@ size_t GetHeaderSize(size_t key_length) { return sizeof(SimpleFileHeader) + key_length; } -int32_t GetDataSizeFromFileSize(size_t key_length, int64_t file_size) { +int64_t GetDataSizeFromFileSize(size_t key_length, int64_t file_size) { int64_t data_size = file_size - key_length - sizeof(SimpleFileHeader) - sizeof(SimpleFileEOF); - return base::checked_cast(data_size); + return data_size; } -int64_t GetFileSizeFromDataSize(size_t key_length, int32_t data_size) { +int64_t GetFileSizeFromDataSize(size_t key_length, int64_t data_size) { return data_size + key_length + sizeof(SimpleFileHeader) + sizeof(SimpleFileEOF); } diff --git a/naiveproxy/src/net/disk_cache/simple/simple_util.h b/naiveproxy/src/net/disk_cache/simple/simple_util.h index 3c7ab10dd2..5918394d34 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_util.h +++ b/naiveproxy/src/net/disk_cache/simple/simple_util.h @@ -59,13 +59,13 @@ size_t GetHeaderSize(size_t key_length); // Given the size of a file holding a stream in the simple backend and the key // to an entry, returns the number of bytes in the stream. -NET_EXPORT_PRIVATE int32_t GetDataSizeFromFileSize(size_t key_length, +NET_EXPORT_PRIVATE int64_t GetDataSizeFromFileSize(size_t key_length, int64_t file_size); // Given the size of a stream in the simple backend and the key to an entry, // returns the number of bytes in the file. NET_EXPORT_PRIVATE int64_t GetFileSizeFromDataSize(size_t key_length, - int32_t data_size); + int64_t data_size); // Given the stream index, returns the number of the file the stream is stored // in. diff --git a/naiveproxy/src/net/disk_cache/sql/exclusive_operation_coordinator.cc b/naiveproxy/src/net/disk_cache/sql/exclusive_operation_coordinator.cc new file mode 100644 index 0000000000..50b0db4d09 --- /dev/null +++ b/naiveproxy/src/net/disk_cache/sql/exclusive_operation_coordinator.cc @@ -0,0 +1,198 @@ +// Copyright 2025 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/disk_cache/sql/exclusive_operation_coordinator.h" + +#include +#include + +#include "base/check.h" +#include "base/metrics/histogram_functions.h" +#include "base/timer/elapsed_timer.h" +#include "net/disk_cache/sql/cache_entry_key.h" + +namespace disk_cache { + +namespace { + +// Wraps an operation to record its queuing time in a UMA histogram. +base::OnceCallback< + void(std::unique_ptr)> +WrapWithUmaQueuingTime( + base::OnceCallback< + void(std::unique_ptr)> + operation, + const std::string_view histogram_name) { + return base::BindOnce( + [](base::OnceCallback)> + operation, + const std::string_view histogram_name, base::ElapsedTimer timer, + std::unique_ptr + handle) { + base::UmaHistogramMicrosecondsTimes(histogram_name, timer.Elapsed()); + std::move(operation).Run(std::move(handle)); + }, + std::move(operation), histogram_name, base::ElapsedTimer()); +} + +} // namespace + +ExclusiveOperationCoordinator::OperationHandle::OperationHandle( + base::PassKey, + base::WeakPtr coordinator, + std::optional key) + : coordinator_(std::move(coordinator)), key_(std::move(key)) {} + +ExclusiveOperationCoordinator::OperationHandle::~OperationHandle() { + if (coordinator_) { + coordinator_->OnOperationFinished(key_); + } +} + +ExclusiveOperationCoordinator::ExclusiveOperationCoordinator() = default; +ExclusiveOperationCoordinator::~ExclusiveOperationCoordinator() = default; + +void ExclusiveOperationCoordinator::PostOrRunExclusiveOperation( + OperationCallback operation) { + CHECK(operation); + operation = WrapWithUmaQueuingTime( + std::move(operation), "Net.SqlDiskCache.ExclusiveOperationDelay"); + queue_.emplace(std::move(operation)); + TryToRunNextOperation(std::nullopt); +} + +void ExclusiveOperationCoordinator::PostOrRunNormalOperation( + const CacheEntryKey& key, + OperationCallback operation) { + CHECK(operation); + operation = WrapWithUmaQueuingTime(std::move(operation), + "Net.SqlDiskCache.NormalOperationDelay"); + // If there is no queue, or the back of the queue is an exclusive operation, + // add a new `NormalOperationsQueueMap` to the back of the queue. + if (queue_.empty() || + std::holds_alternative(queue_.back())) { + queue_.push(NormalOperationsQueueMap()); + } + // Add the callback to the queue for the given `key`. + // Normal operations with the same key are serialized. + std::get(queue_.back())[key].push( + std::move(operation)); + TryToRunNextOperation(key); +} + +void ExclusiveOperationCoordinator::OnOperationFinished( + const std::optional& key) { + CHECK(!queue_.empty()); + // Verify that the front of the queue is a `NormalOperationsQueueMap` iff a + // `key` was provided. + CHECK_EQ(std::holds_alternative(queue_.front()), + key.has_value()); + + if (key.has_value()) { + // The operation that just finished was a normal operation. + // Get a reference to the `NormalOperationsQueueMap` at the front of the + // queue. + NormalOperationsQueueMap& normal_operations_map = + std::get(queue_.front()); + auto it = normal_operations_map.find(key.value()); + // The `NormalOperationsQueueMap` at the front of `queue_` must have a + // `base::queue` corresponding to `key`, + CHECK(it != normal_operations_map.end()); + // and that `base::queue` must not be empty, + CHECK(!it->second.empty()); + // and the OperationCallback at the front must be a null callback. + CHECK(it->second.front().is_null()); + // Remove the OperationCallback that just finished running. + it->second.pop(); + if (it->second.empty()) { + // There are no more operations for this key, so remove the key from the + // map. + normal_operations_map.erase(it); + if (normal_operations_map.empty()) { + // There are no more operations in the map, so remove the map from the + // queue. This phase has completed. + queue_.pop(); + } + } + } else { + // The operation that just finished was an exclusive operation. + // Get a reference to the `ExclusiveOperation` at the front of the queue. + ExclusiveOperation& exclusive_operation = + std::get(queue_.front()); + // The ExclusiveOperation at the front of `queue_` must be a null callback. + CHECK(exclusive_operation.is_null()); + // Remove the ExclusiveOperation from the queue. This phase has completed. + queue_.pop(); + } + + // The completion of an operation might allow the next one to start. + TryToRunNextOperation(key); +} + +void ExclusiveOperationCoordinator::TryToRunNextOperation( + const std::optional& key) { + if (queue_.empty()) { + // Nothing to do. + return; + } + + // A list of operations that can be run in this pass. We collect them first + // and run them later to avoid iterator invalidation issues caused by + // re-entrant calls if an operation completes synchronously. + std::vector runnable_ops; + + if (std::holds_alternative(queue_.front())) { + // The next phase in the queue is a batch of normal operations. + // Get a reference to the `NormalOperationsQueueMap` at the front of the + // queue. + NormalOperationsQueueMap& normal_operations_map = + std::get(queue_.front()); + // If a `key` was provided, attempt to run the next operation for that + // `key`. Otherwise, attempt to run operations for all keys. + if (key.has_value()) { + if (auto it = normal_operations_map.find(key.value()); + it != normal_operations_map.end()) { + CHECK(!it->second.empty()); + MaybeTakeAndResetPendingOperation(it->second.front(), key, + runnable_ops); + } + } else { + // Attempt to run one operation for each key in the map. + for (auto& pair : normal_operations_map) { + CHECK(!pair.second.empty()); + MaybeTakeAndResetPendingOperation(pair.second.front(), pair.first, + runnable_ops); + } + } + } else { + // The next phase in the queue is an exclusive operation. + MaybeTakeAndResetPendingOperation( + std::get(queue_.front()), std::nullopt, + runnable_ops); + } + + // Run the collected operations. + for (auto& runnable_op : runnable_ops) { + std::move(runnable_op).Run(); + } +} + +void ExclusiveOperationCoordinator::MaybeTakeAndResetPendingOperation( + ExclusiveOperationCoordinator::OperationCallback& operation, + const std::optional& key, + std::vector& runnable_ops) { + if (!operation) { + return; + } + runnable_ops.push_back(base::BindOnce( + std::move(operation), std::make_unique( + base::PassKey(), + weak_factory_.GetWeakPtr(), key))); + // Reset to a null callback to indicate that the operation is + // currently running. + operation.Reset(); +} + +} // namespace disk_cache diff --git a/naiveproxy/src/net/disk_cache/sql/exclusive_operation_coordinator.h b/naiveproxy/src/net/disk_cache/sql/exclusive_operation_coordinator.h new file mode 100644 index 0000000000..93e6b93a51 --- /dev/null +++ b/naiveproxy/src/net/disk_cache/sql/exclusive_operation_coordinator.h @@ -0,0 +1,127 @@ +// Copyright 2025 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_DISK_CACHE_SQL_EXCLUSIVE_OPERATION_COORDINATOR_H_ +#define NET_DISK_CACHE_SQL_EXCLUSIVE_OPERATION_COORDINATOR_H_ + +#include +#include +#include +#include +#include +#include + +#include "base/containers/queue.h" +#include "base/functional/callback.h" +#include "base/memory/weak_ptr.h" +#include "base/types/pass_key.h" +#include "net/base/net_export.h" +#include "net/disk_cache/sql/cache_entry_key.h" + +namespace disk_cache { + +// This class coordinates the execution of "normal" and "exclusive" operations +// to ensure that exclusive operations have exclusive access to a resource. +// +// - Normal operations are serialized by key. Operations with different keys can +// run concurrently with each other. +// - Exclusive operations run one at a time, and only when no normal operations +// are running. +// - When an exclusive operation is requested, it waits for all running normal +// operations to complete. +// - While an exclusive operation is pending or running, any new normal +// operations are queued and will only be executed after all pending +// exclusive operations have finished. +class NET_EXPORT_PRIVATE ExclusiveOperationCoordinator { + public: + // An RAII-style handle that represents a running operation. The operation + // is considered "finished" when this handle is destroyed. The destructor + // notifies the coordinator to potentially start the next operation. + // An operation is considered "exclusive" if its `key_` is `std::nullopt`, and + // "normal" if it has a value. + class NET_EXPORT_PRIVATE OperationHandle { + public: + OperationHandle(base::PassKey, + base::WeakPtr coordinator, + std::optional key); + ~OperationHandle(); + + OperationHandle(const OperationHandle&) = delete; + OperationHandle& operator=(const OperationHandle&) = delete; + OperationHandle(OperationHandle&&) = delete; + OperationHandle& operator=(OperationHandle&&) = delete; + + private: + base::WeakPtr coordinator_; + const std::optional key_; + }; + + using OperationCallback = + base::OnceCallback)>; + + ExclusiveOperationCoordinator(); + ~ExclusiveOperationCoordinator(); + + ExclusiveOperationCoordinator(const ExclusiveOperationCoordinator&) = delete; + ExclusiveOperationCoordinator& operator=( + const ExclusiveOperationCoordinator&) = delete; + ExclusiveOperationCoordinator(ExclusiveOperationCoordinator&&) = delete; + ExclusiveOperationCoordinator& operator=(ExclusiveOperationCoordinator&&) = + delete; + + // Posts an exclusive operation. The operation will be executed after all + // currently running normal operations have completed. While this and any + // other exclusive operations are pending or running, no new normal + // operations will start. + void PostOrRunExclusiveOperation(OperationCallback operation); + + // Posts a normal operation. If no exclusive operations are pending or + // running, the operation is executed immediately. Otherwise, it is queued + // and will be executed after all exclusive operations have finished. This + // operation will be serialized with other normal operations that have the + // same `key`. + void PostOrRunNormalOperation(const CacheEntryKey& key, + OperationCallback operation); + + private: + using NormalOperationsQueueMap = + std::map>; + using ExclusiveOperation = OperationCallback; + using NormalOperationsQueueMapOrExclusiveOperation = + std::variant; + + // Called by OperationHandle's destructor. `key` has a value for a normal + // operation, and is `std::nullopt` for an exclusive operation. + void OnOperationFinished(const std::optional& key); + + // Checks the current state and runs the next appropriate operation. `key` has + // a value if a normal operation was posted or finished, and is `std::nullopt` + // if an exclusive operation was posted or finished. + void TryToRunNextOperation(const std::optional& key); + + // Prepares a pending `operation` for execution if it is not already running. + // The `operation` is moved into a `base::OnceClosure`, bound with an + // `OperationHandle`, and added to `runnable_ops`. The original `operation` + // callback is reset to a null state to mark it as in-flight. + void MaybeTakeAndResetPendingOperation( + OperationCallback& operation, + const std::optional& key, + std::vector& runnable_ops); + + // A queue of operation "phases". Each element is either a + // `NormalOperationsQueueMap` (a batch of normal operations) or a single + // `ExclusiveOperation`. This structure enforces the serialization between + // normal and exclusive operations. For example, an exclusive operation will + // only run after all operations in the preceding `NormalOperationsQueueMap` + // batch have completed. Normal operations that arrive while an exclusive + // operation is pending are added to a new batch that runs after the exclusive + // operation completes. + base::queue queue_; + + base::WeakPtrFactory weak_factory_{this}; +}; + +} // namespace disk_cache + +#endif // NET_DISK_CACHE_SQL_EXCLUSIVE_OPERATION_COORDINATOR_H_ diff --git a/naiveproxy/src/net/disk_cache/sql/sql_backend_constants.h b/naiveproxy/src/net/disk_cache/sql/sql_backend_constants.h index 396987ecc7..bfbcec974f 100644 --- a/naiveproxy/src/net/disk_cache/sql/sql_backend_constants.h +++ b/naiveproxy/src/net/disk_cache/sql/sql_backend_constants.h @@ -9,6 +9,7 @@ #include #include "base/files/file_path.h" +#include "base/time/time.h" namespace disk_cache { @@ -31,6 +32,17 @@ inline constexpr std::string_view kSqlBackendMetaTableKeyTotalSize = inline constexpr base::FilePath::CharType kSqlBackendDatabaseFileName[] = FILE_PATH_LITERAL("sqldb"); +// The name of the fake index file. This file is created to signal the presence +// of the SQL backend and to prevent other backends from trying to use the same +// directory. +inline constexpr base::FilePath::CharType kSqlBackendFakeIndexFileName[] = + FILE_PATH_LITERAL("index"); + +// The magic number for the fake index file. This is "SQLCache" in +// little-endian. +inline constexpr uint64_t kSqlBackendFakeIndexMagicNumber = + UINT64_C(0x65686361434c5153); + // The oldest database schema version that the current code can read. // A database with a version older than this will be razed as it's considered // obsolete and the code no longer supports migrating from it. @@ -52,10 +64,27 @@ inline constexpr int kSqlBackendCompatibleDatabaseVersion = 1; // miscellaneous metadata. The // `SqlPersistentStoreTest.StaticResourceSizeEstimation` test provides a basic // validation of this constant against the actual file size. -// TODO(crbug.com/422065015): Re-evaluate this constant when head and body -// writing is implemented and new indexes are added, as the storage pattern may -// affect overhead. -inline constexpr int kSqlBackendStaticResourceSize = 100; +inline constexpr int kSqlBackendStaticResourceSize = 300; + +// Defines the number of streams supported by the SQL backend. +// The SQL backend only supports stream 0 and stream 1. +static const int kSqlBackendStreamCount = 2; + +// Divisor used to calculate the high and low watermarks for cache eviction. +// The high watermark is `max_size - (max_size / divisor)`, and the low +// watermark is `max_size - 2 * (max_size / divisor)`. Eviction is triggered +// when the cache size exceeds the high watermark and continues until it is +// below the low watermark. +inline constexpr int kSqlBackendEvictionMarginDivisor = 20; + +// The delay after backend initialization before running a one-time cleanup task +// to delete doomed entries. This task removes entries that were doomed in a +// previous session but not fully deleted (e.g., due to a crash), ensuring +// that their disk space is reclaimed. +// Note: This value is set assuming use with HTTP Cache, but if the SQL backend +// is used with Cache Storage, it should be a shorter value. +inline constexpr base::TimeDelta kSqlBackendDeleteDoomedEntriesDelay = + base::Minutes(10); } // namespace disk_cache diff --git a/naiveproxy/src/net/disk_cache/sql/sql_backend_impl.cc b/naiveproxy/src/net/disk_cache/sql/sql_backend_impl.cc index bb2bacede9..0a279b37a3 100644 --- a/naiveproxy/src/net/disk_cache/sql/sql_backend_impl.cc +++ b/naiveproxy/src/net/disk_cache/sql/sql_backend_impl.cc @@ -4,102 +4,650 @@ #include "net/disk_cache/sql/sql_backend_impl.h" +#include +#include + +#include "base/barrier_callback.h" +#include "base/containers/flat_set.h" +#include "base/containers/span.h" +#include "base/files/file.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/functional/callback_helpers.h" +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "base/metrics/histogram_functions.h" #include "base/notimplemented.h" +#include "base/strings/string_number_conversions.h" +#include "base/task/task_runner.h" +#include "base/task/thread_pool.h" +#include "base/types/expected.h" +#include "net/base/io_buffer.h" #include "net/base/net_errors.h" +#include "net/disk_cache/sql/sql_entry_impl.h" +#include "net/disk_cache/sql/sql_persistent_store.h" +#include "sql_backend_constants.h" namespace disk_cache { +namespace { -SqlBackendImpl::SqlBackendImpl(net::CacheType cache_type) - : Backend(cache_type) {} +using FakeIndexFileError = SqlBackendImpl::FakeIndexFileError; + +// Checks the fake index file, creating it if it doesn't exist. Returns an +// error code if the file is corrupted or cannot be created. +FakeIndexFileError CheckFakeIndexFileInternal(const base::FilePath& path) { + const base::FilePath file_path = path.Append(kSqlBackendFakeIndexFileName); + const std::optional file_size = base::GetFileSize(file_path); + if (file_size.has_value()) { + if (file_size != sizeof(kSqlBackendFakeIndexMagicNumber)) { + return FakeIndexFileError::kWrongFileSize; + } + base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ); + if (!file.IsValid()) { + return FakeIndexFileError::kOpenFileFailed; + } + uint64_t magic_number = 0; + if (!file.ReadAndCheck(0, base::byte_span_from_ref(magic_number))) { + return FakeIndexFileError::kReadFileFailed; + } + if (magic_number != kSqlBackendFakeIndexMagicNumber) { + return FakeIndexFileError::kWrongMagicNumber; + } + return FakeIndexFileError::kOkExisting; + } + if (!base::DirectoryExists(path) && !base::CreateDirectory(path)) { + return FakeIndexFileError::kFailedToCreateDirectory; + } + base::File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE); + if (!file.IsValid()) { + return FakeIndexFileError::kCreateFileFailed; + } + if (!file.WriteAndCheck( + 0, base::byte_span_from_ref(kSqlBackendFakeIndexMagicNumber))) { + return FakeIndexFileError::kWriteFileFailed; + } + return FakeIndexFileError::kOkNew; +} + +// Checks the fake index file and records a histogram of the result. +bool CheckFakeIndexFile(const base::FilePath& path) { + FakeIndexFileError error = CheckFakeIndexFileInternal(path); + base::UmaHistogramEnumeration("Net.SqlDiskCache.FakeIndexFileError", error); + return error == FakeIndexFileError::kOkNew || + error == FakeIndexFileError::kOkExisting; +} + +// A helper to handle methods that may complete synchronously. +// +// This allows a caller to dispatch an async operation and immediately check if +// it completed synchronously. If so, the result is returned directly. If not, +// a provided callback is invoked later. +template +class SyncResultReceiver : public base::RefCounted> { + public: + using ResultCallback = base::OnceCallback; + + explicit SyncResultReceiver(ResultCallback callback) + : callback_(std::move(callback)) {} + + ~SyncResultReceiver() { + // As a contract, FinishSyncCall() must be called. If it's not, it's a + // bug in the calling code. + CHECK(sync_call_finished_); + } + + SyncResultReceiver(const SyncResultReceiver&) = delete; + SyncResultReceiver& operator=(const SyncResultReceiver&) = delete; + + // Returns a callback to pass to the async operation. + ResultCallback GetCallback() { + return base::BindOnce(&SyncResultReceiver::OnResult, this); + } + + // Checks for a synchronous result. If the operation already completed, + // returns the result. Otherwise, returns nullopt and the original callback + // will be run asynchronously. + std::optional FinishSyncCall() { + sync_call_finished_ = true; + if (result_) { + callback_.Reset(); + return std::move(result_); + } + return std::nullopt; + } + + private: + // Receives the result from the async operation. + void OnResult(T result) { + if (sync_call_finished_) { + // The caller is already waiting for the async result. + if (callback_) { + std::move(callback_).Run(std::move(result)); + } + } else { + // The result arrived synchronously. Store it for FinishSyncCall. + result_ = std::move(result); + } + } + + // The original callback, to be run on async completion. + ResultCallback callback_; + // Holds the result if it arrives synchronously. + std::optional result_; + // Set to true when FinishSyncCall is called. + bool sync_call_finished_ = false; +}; + +// Creates a `base::OnceClosure` that takes ownership of an `OperationHandle`. +// When the closure is run, the handle is destroyed, signaling the completion +// of the operation to the `ExclusiveOperationCoordinator`. This is typically +// used with `base::OnceCallback::Then()` to ensure the handle is released only +// after the primary callback has finished. +base::OnceClosure DoNothingWithBoundHandle( + std::unique_ptr handle) { + return base::OnceClosure(base::DoNothingWithBoundArgs(std::move(handle))); +} + +} // namespace + +// IteratorImpl provides an implementation of Backend::Iterator for the +// SqlBackendImpl. It allows iterating through cache entries stored in the +// SQLite database. Iteration is performed in reverse `res_id` order (from +// newest to oldest entry in the database). +class SqlBackendImpl::IteratorImpl : public Backend::Iterator { + public: + explicit IteratorImpl(base::WeakPtr backend) + : backend_(backend) {} + ~IteratorImpl() override = default; + EntryResult OpenNextEntry(EntryResultCallback callback) override { + CHECK(!callback_); + if (!backend_) { + return EntryResult::MakeError(net::ERR_FAILED); + } + callback_ = std::move(callback); + // Schedule `DoOpenNextEntry` as an exclusive operation to ensure that + // iteration does not conflict with other backend-wide operations (e.g., + // mass deletion). + backend_->exclusive_operation_coordinator_.PostOrRunExclusiveOperation( + base::BindOnce(&IteratorImpl::DoOpenNextEntry, + weak_factory_.GetWeakPtr())); + return EntryResult::MakeError(net::ERR_IO_PENDING); + } + + private: + // Performs the actual logic for opening the next entry. This method is + // executed when it's its turn in the exclusive operation queue. + void DoOpenNextEntry( + std::unique_ptr handle) { + if (!backend_) { + std::move(callback_).Run(EntryResult::MakeError(net::ERR_FAILED)); + // `handle` is destroyed here, but `backend_` is null, so it's a no-op. + return; + } + // Request the next entry from the persistent store. `res_id_iterator_` + // keeps track of the last `res_id` returned, allowing the store to fetch + // entries older than that. + // `handle` will be destroyed after executing + // `OnOpenLatestEntryBeforeResIdFinished()`, may be triggering queued + // operations. + backend_->store_->OpenLatestEntryBeforeResId( + res_id_iterator_, + base::BindOnce(&IteratorImpl::OnOpenLatestEntryBeforeResIdFinished, + weak_factory_.GetWeakPtr()) + .Then(DoNothingWithBoundHandle(std::move(handle)))); + } + + // Callback for `SqlPersistentStore::OpenLatestEntryBeforeResId`. + void OnOpenLatestEntryBeforeResIdFinished( + SqlPersistentStore::OptionalEntryInfoWithIdAndKey result) { + CHECK(callback_); + if (!backend_) { + std::move(callback_).Run(EntryResult::MakeError(net::ERR_FAILED)); + return; + } + // If no more entries are found or an error occurred in the store. + if (!result.has_value()) { + std::move(callback_).Run(EntryResult::MakeError(net::ERR_FAILED)); + return; + } + SqlPersistentStore::EntryInfoWithIdAndKey& entry_info = *result; + + // Update the iterator's cursor to the `res_id` of the current entry, + // so the next call to `OpenLatestEntryBeforeResId` starts from here. + res_id_iterator_ = entry_info.res_id; + + // Check if the entry is already active in `active_entries_`. If so, + // reuse the existing `SqlEntryImpl` instance. + if (SqlEntryImpl* entry = backend_->GetActiveEntry(entry_info.key)) { + entry->AddRef(); + std::move(callback_).Run(EntryResult::MakeOpened(entry)); + return; + } + + // This DCHECK ensures that an entry returned by the store for iteration + // is not already in the `doomed_entries_` set. This invariant is + // maintained because iterator operations are "exclusive" and dooming + // operations are "normal", and the `ExclusiveOperationCoordinator` + // ensures they do not run concurrently. If a doom operation runs first, + // the entry is marked as doomed in the database and + // `OpenLatestEntryBeforeResId` will not return it. If the iterator + // operation runs first, any subsequent doom operation will be queued until + // the iteration step is complete. + DCHECK(std::none_of( + backend_->doomed_entries_.begin(), backend_->doomed_entries_.end(), + [&](const raw_ref& doomed_entry) { + return doomed_entry.get().token() == entry_info.info.token; + })); + + // Apply any in-flight modifications (e.g., last_used time updates, header + // changes) that were queued for this entry while it was not active. + backend_->ApplyInFlightEntryModifications(entry_info.key, entry_info.info); + + // If the entry is not active, create a new `SqlEntryImpl`. + scoped_refptr new_entry = base::MakeRefCounted( + backend_, entry_info.key, entry_info.info.token, + entry_info.info.last_used, entry_info.info.body_end, + entry_info.info.head); + new_entry->AddRef(); + CHECK(backend_->active_entries_ + .insert(std::make_pair(entry_info.key, + raw_ref(*new_entry.get()))) + .second); + + // Return the newly opened entry. + std::move(callback_).Run(EntryResult::MakeOpened(new_entry.get())); + } + + base::WeakPtr backend_; + // The `res_id` of the last entry returned by the iterator. Used to fetch + // entries with smaller `res_id`s in subsequent calls. + int64_t res_id_iterator_ = std::numeric_limits::max(); + EntryResultCallback callback_; + base::WeakPtrFactory weak_factory_{this}; +}; + +SqlBackendImpl::SqlBackendImpl(const base::FilePath& path, + int64_t max_bytes, + net::CacheType cache_type) + : Backend(cache_type), + path_(path), + background_task_runner_(base::ThreadPool::CreateSequencedTaskRunner( + {base::MayBlock(), base::TaskPriority::USER_BLOCKING, + base::TaskShutdownBehavior::BLOCK_SHUTDOWN})), + store_(SqlPersistentStore::Create(path, + max_bytes > 0 ? max_bytes : 0, + GetCacheType(), + background_task_runner_)) { + DVLOG(1) << "SqlBackendImpl::SqlBackendImpl " << path; +} SqlBackendImpl::~SqlBackendImpl() = default; +void SqlBackendImpl::Init(CompletionOnceCallback callback) { + auto barrier_callback = base::BarrierCallback( + 2, base::BindOnce(&SqlBackendImpl::OnInitialized, + weak_factory_.GetWeakPtr(), std::move(callback))); + + store_->Initialize(base::BindOnce([](SqlPersistentStore::Error result) { + return result == SqlPersistentStore::Error::kOk; + }).Then(barrier_callback)); + + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, + {base::MayBlock(), base::TaskPriority::USER_BLOCKING, + base::TaskShutdownBehavior::BLOCK_SHUTDOWN}, + base::BindOnce(&CheckFakeIndexFile, path_), + base::OnceCallback(barrier_callback)); +} + +void SqlBackendImpl::OnInitialized(CompletionOnceCallback callback, + const std::vector& results) { + const bool success = std::all_of(results.begin(), results.end(), + [](bool result) { return result; }); + if (success) { + // Schedule a one-time task to clean up doomed entries from previous + // sessions. This runs after a delay to avoid impacting startup performance. + base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&SqlBackendImpl::TriggerDeleteDoomedEntries, + weak_factory_.GetWeakPtr()), + kSqlBackendDeleteDoomedEntriesDelay); + } + std::move(callback).Run(success ? net::OK : net::ERR_FAILED); +} + int64_t SqlBackendImpl::MaxFileSize() const { - // TODO(crbug.com/422065015): Implement this method. - NOTIMPLEMENTED(); - return net::ERR_NOT_IMPLEMENTED; + // Delegates to the persistent store to get the max file size. + return store_->MaxFileSize(); } int32_t SqlBackendImpl::GetEntryCount( net::Int32CompletionOnceCallback callback) const { - // TODO(crbug.com/422065015): Implement this method. - NOTIMPLEMENTED(); - return net::ERR_NOT_IMPLEMENTED; + // Asynchronously retrieves the entry count from the persistent store. + store_->GetEntryCount(std::move(callback)); + return net::ERR_IO_PENDING; } EntryResult SqlBackendImpl::OpenOrCreateEntry(const std::string& key, net::RequestPriority priority, EntryResultCallback callback) { - // TODO(crbug.com/422065015): Implement this method. - NOTIMPLEMENTED(); - return EntryResult::MakeError(net::ERR_NOT_IMPLEMENTED); + return OpenOrCreateEntryInternal( + OpenOrCreateEntryOperationType::kOpenOrCreateEntry, key, + std::move(callback)); } EntryResult SqlBackendImpl::OpenEntry(const std::string& key, net::RequestPriority priority, EntryResultCallback callback) { - // TODO(crbug.com/422065015): Implement this method. - NOTIMPLEMENTED(); - return EntryResult::MakeError(net::ERR_NOT_IMPLEMENTED); + return OpenOrCreateEntryInternal(OpenOrCreateEntryOperationType::kOpenEntry, + key, std::move(callback)); } EntryResult SqlBackendImpl::CreateEntry(const std::string& key, net::RequestPriority priority, EntryResultCallback callback) { - // TODO(crbug.com/422065015): Implement this method. - NOTIMPLEMENTED(); - return EntryResult::MakeError(net::ERR_NOT_IMPLEMENTED); + return OpenOrCreateEntryInternal(OpenOrCreateEntryOperationType::kCreateEntry, + key, std::move(callback)); +} + +EntryResult SqlBackendImpl::OpenOrCreateEntryInternal( + OpenOrCreateEntryOperationType type, + const std::string& key, + EntryResultCallback callback) { + const CacheEntryKey entry_key(key); + auto sync_result_receiver = + base::MakeRefCounted>( + std::move(callback)); + exclusive_operation_coordinator_.PostOrRunNormalOperation( + entry_key, + base::BindOnce(&SqlBackendImpl::HandleOpenOrCreateEntryOperation, + weak_factory_.GetWeakPtr(), type, entry_key, + sync_result_receiver->GetCallback())); + auto sync_result = sync_result_receiver->FinishSyncCall(); + return sync_result ? std::move(*sync_result) + : EntryResult::MakeError(net::ERR_IO_PENDING); +} + +void SqlBackendImpl::HandleOpenOrCreateEntryOperation( + OpenOrCreateEntryOperationType type, + const CacheEntryKey& entry_key, + EntryResultCallback callback, + std::unique_ptr handle) { + if (SqlEntryImpl* entry = GetActiveEntry(entry_key)) { + if (type == OpenOrCreateEntryOperationType::kCreateEntry) { + std::move(callback).Run(EntryResult::MakeError(net::ERR_FAILED)); + } else { + entry->AddRef(); + std::move(callback).Run(EntryResult::MakeOpened(entry)); + } + return; + } + + switch (type) { + case OpenOrCreateEntryOperationType::kOpenOrCreateEntry: + store_->OpenOrCreateEntry( + entry_key, base::BindOnce(&SqlBackendImpl::OnEntryOperationFinished, + base::Unretained(this), entry_key, + std::move(callback), std::move(handle))); + break; + case OpenOrCreateEntryOperationType::kOpenEntry: + store_->OpenEntry( + entry_key, + base::BindOnce(&SqlBackendImpl::OnOptionalEntryOperationFinished, + base::Unretained(this), entry_key, std::move(callback), + std::move(handle))); + break; + case OpenOrCreateEntryOperationType::kCreateEntry: + store_->CreateEntry( + entry_key, base::BindOnce(&SqlBackendImpl::OnEntryOperationFinished, + base::Unretained(this), entry_key, + std::move(callback), std::move(handle))); + break; + } +} + +SqlEntryImpl* SqlBackendImpl::GetActiveEntry(const CacheEntryKey& key) { + if (auto it = active_entries_.find(key); it != active_entries_.end()) { + // Return a pointer to the SqlEntryImpl if found. + return &it->second.get(); + } + return nullptr; +} + +void SqlBackendImpl::DoomActiveEntry(SqlEntryImpl& entry, + CompletionOnceCallback callback) { + exclusive_operation_coordinator_.PostOrRunNormalOperation( + entry.cache_key(), + base::BindOnce(&SqlBackendImpl::HandleDoomActiveEntryOperation, + weak_factory_.GetWeakPtr(), + scoped_refptr(&entry), std::move(callback))); +} + +void SqlBackendImpl::HandleDoomActiveEntryOperation( + scoped_refptr entry, + CompletionOnceCallback callback, + std::unique_ptr handle) { + if (entry->doomed()) { + return; + } + DoomActiveEntryInternal( + *entry, + std::move(callback).Then(DoNothingWithBoundHandle(std::move(handle)))); +} + +void SqlBackendImpl::DoomActiveEntryInternal(SqlEntryImpl& entry, + CompletionOnceCallback callback) { + // Mark the entry as doomed internally. + entry.MarkAsDoomed(); + // Move it from the active_entries_ map to the doomed_entries_ set. + ReleaseActiveEntry(entry); + doomed_entries_.emplace(entry); + + // Ask the store to mark the entry as doomed in the database. + store_->DoomEntry( + entry.cache_key(), entry.token(), + base::BindOnce( + [](base::WeakPtr weak_ptr, + CompletionOnceCallback callback, SqlPersistentStore::Error error) { + // Do not call the `callback` if the backend has been destroyed. + // This is safe for both backend-initiated and entry-initiated + // dooms: + // - For backend operations (e.g., `DoomEntry`), the provided + // callback should be cancelled if the backend is gone. + // - For entry operations (`SqlEntryImpl::Doom`), the callback is a + // `base::DoNothing()`, so cancelling it has no effect. + if (weak_ptr) { + // Return net::OK even if the entry is not found. This matches + // the behavior of SimpleCache. This is tested by + // BackendFailedOpenThenMultipleDoomsNonExistentEntry in + // DiskCacheGenericBackendTest. + std::move(callback).Run(net::OK); + } + }, + weak_factory_.GetWeakPtr(), std::move(callback))); } net::Error SqlBackendImpl::DoomEntry(const std::string& key, net::RequestPriority priority, CompletionOnceCallback callback) { - // TODO(crbug.com/422065015): Implement this method. - NOTIMPLEMENTED(); - return net::ERR_NOT_IMPLEMENTED; + const CacheEntryKey entry_key(key); + exclusive_operation_coordinator_.PostOrRunNormalOperation( + entry_key, base::BindOnce(&SqlBackendImpl::HandleDoomEntryOperation, + weak_factory_.GetWeakPtr(), entry_key, priority, + std::move(callback))); + return net::ERR_IO_PENDING; +} + +void SqlBackendImpl::HandleDoomEntryOperation( + const CacheEntryKey& key, + net::RequestPriority priority, + CompletionOnceCallback callback, + std::unique_ptr handle) { + // If the entry is currently active, doom it directly. + if (auto* active_entry = GetActiveEntry(key)) { + DoomActiveEntryInternal(*active_entry, std::move(callback)); + // The handle for this operation is released upon returning, allowing the + // next queued operation to run. + return; + } + + // If the entry is not active and no operation is pending, it means the entry + // is not currently open. In this case, we can directly ask the store to + // delete the "live" (not yet doomed) entry from the database. + store_->DeleteLiveEntry( + key, base::BindOnce( + [](base::WeakPtr weak_ptr, + CompletionOnceCallback callback, + SqlPersistentStore::Error result) { + // Convert store error to net error. kNotFound is + // considered a success for dooming (idempotency). + std::move(callback).Run( + (result == SqlPersistentStore::Error::kOk || + result == SqlPersistentStore::Error::kNotFound) + ? net::OK + : net::ERR_FAILED); + }, + weak_factory_.GetWeakPtr(), std::move(callback)) + .Then(DoNothingWithBoundHandle(std::move(handle)))); } net::Error SqlBackendImpl::DoomAllEntries(CompletionOnceCallback callback) { - // TODO(crbug.com/422065015): Implement this method. - NOTIMPLEMENTED(); - return net::ERR_NOT_IMPLEMENTED; + // DoomAllEntries is a special case of DoomEntriesBetween with an unbounded + // time range. + return DoomEntriesBetween(base::Time::Min(), base::Time::Max(), + std::move(callback)); } net::Error SqlBackendImpl::DoomEntriesBetween(base::Time initial_time, base::Time end_time, CompletionOnceCallback callback) { - // TODO(crbug.com/422065015): Implement this method. - NOTIMPLEMENTED(); - return net::ERR_NOT_IMPLEMENTED; + exclusive_operation_coordinator_.PostOrRunExclusiveOperation(base::BindOnce( + &SqlBackendImpl::HandleDoomEntriesBetweenOperation, + weak_factory_.GetWeakPtr(), initial_time, end_time, std::move(callback))); + return net::ERR_IO_PENDING; +} + +void SqlBackendImpl::HandleDoomEntriesBetweenOperation( + base::Time initial_time, + base::Time end_time, + CompletionOnceCallback callback, + std::unique_ptr handle) { + if (initial_time.is_null()) { + // If initial_time is null, use the minimum possible time. + initial_time = base::Time::Min(); + } + if (end_time.is_null()) { + // If end_time is null, use the maximum possible time. + end_time = base::Time::Max(); + } + + // Optimization: If dooming all entries (min to max time) and there are no + // active, doomed, or pending entries, we can directly ask the store to + // delete all entries, which is more efficient. + if (initial_time.is_min() && end_time.is_max() && active_entries_.empty() && + doomed_entries_.empty()) { + // Ask the store to delete all entries from the database. + store_->DeleteAllEntries( + base::BindOnce( + [](CompletionOnceCallback callback, + SqlPersistentStore::Error result) { + std::move(callback).Run(result == SqlPersistentStore::Error::kOk + ? net::OK + : net::ERR_FAILED); + }, + std::move(callback)) + .Then(DoNothingWithBoundHandle(std::move(handle)))); + return; + } + + // Collect keys of active entries to exclude them from the store's + // DeleteLiveEntriesBetween operation, as they will be handled by dooming them + // directly within this method. + std::vector excluded_keys_vec; + excluded_keys_vec.reserve(active_entries_.size()); + std::vector active_entries_to_be_doomed; + for (auto& it : active_entries_) { + excluded_keys_vec.push_back(it.first); + // Check if the active entry falls within the specified time range. + const base::Time last_used_time = it.second->GetLastUsed(); + if (last_used_time >= initial_time && last_used_time < end_time) { + active_entries_to_be_doomed.push_back(&it.second.get()); + } + } + base::flat_set excluded_keys(base::sorted_unique, + std::move(excluded_keys_vec)); + + auto barrier_callback = base::BarrierCallback( + active_entries_to_be_doomed.size() + // For active entries being doomed + 1, // For store's DeleteLiveEntriesBetween + base::BindOnce( + // This final callback is run after all individual doom operations + // complete. + [](base::WeakPtr weak_ptr, + CompletionOnceCallback callback, const std::vector& result) { + if (weak_ptr) { + std::move(callback).Run(net::OK); + } + }, + weak_factory_.GetWeakPtr(), std::move(callback)) + .Then(DoNothingWithBoundHandle(std::move(handle)))); + + // Doom active entries that fall within the time range. + for (auto* entry : active_entries_to_be_doomed) { + DoomActiveEntryInternal(*entry, barrier_callback); + } + + + // Ask the store to delete all other "live" (not doomed, not active, not + // pending) entries within the specified time range, excluding those already + // handled. + store_->DeleteLiveEntriesBetween( + initial_time, end_time, std::move(excluded_keys), + base::BindOnce( + [](CompletionOnceCallback callback, + SqlPersistentStore::Error result) { + std::move(callback).Run(result == SqlPersistentStore::Error::kOk + ? net::OK + : net::ERR_FAILED); + }, + std::move(barrier_callback))); } net::Error SqlBackendImpl::DoomEntriesSince(base::Time initial_time, CompletionOnceCallback callback) { - // TODO(crbug.com/422065015): Implement this method. - NOTIMPLEMENTED(); - return net::ERR_NOT_IMPLEMENTED; + // DoomEntriesSince is a special case of DoomEntriesBetween with end_time set + // to the maximum possible time. + return DoomEntriesBetween(initial_time, base::Time::Max(), + std::move(callback)); } int64_t SqlBackendImpl::CalculateSizeOfAllEntries( Int64CompletionOnceCallback callback) { - // TODO(crbug.com/422065015): Implement this method. - NOTIMPLEMENTED(); - return net::ERR_NOT_IMPLEMENTED; + return CalculateSizeOfEntriesBetween(base::Time::Min(), base::Time::Max(), + std::move(callback)); } int64_t SqlBackendImpl::CalculateSizeOfEntriesBetween( base::Time initial_time, base::Time end_time, Int64CompletionOnceCallback callback) { - // TODO(crbug.com/422065015): Implement this method. - NOTIMPLEMENTED(); - return net::ERR_NOT_IMPLEMENTED; + store_->CalculateSizeOfEntriesBetween( + initial_time, end_time, + base::BindOnce( + [](base::WeakPtr weak_ptr, + Int64CompletionOnceCallback callback, + SqlPersistentStore::Int64OrError result) { + if (weak_ptr) { + std::move(callback).Run(result.has_value() ? result.value() + : net::ERR_FAILED); + } + }, + weak_factory_.GetWeakPtr(), std::move(callback))); + return net::ERR_IO_PENDING; } std::unique_ptr SqlBackendImpl::CreateIterator() { - // TODO(crbug.com/422065015): Implement this method. - NOTIMPLEMENTED(); - return nullptr; + return std::make_unique(weak_factory_.GetWeakPtr()); } void SqlBackendImpl::GetStats(base::StringPairs* stats) { @@ -108,8 +656,390 @@ void SqlBackendImpl::GetStats(base::StringPairs* stats) { } void SqlBackendImpl::OnExternalCacheHit(const std::string& key) { - // TODO(crbug.com/422065015): Implement this method. - NOTIMPLEMENTED(); + const CacheEntryKey entry_key(key); + if (auto it = active_entries_.find(entry_key); it != active_entries_.end()) { + it->second->UpdateLastUsed(); + return; + } + const base::Time now = base::Time::Now(); + in_flight_entry_modifications_[entry_key].emplace_back( + base::UnguessableToken(), now); + exclusive_operation_coordinator_.PostOrRunNormalOperation( + entry_key, + base::BindOnce(&SqlBackendImpl::HandleOnExternalCacheHitOperation, + weak_factory_.GetWeakPtr(), entry_key, now)); } +void SqlBackendImpl::HandleOnExternalCacheHitOperation( + const CacheEntryKey& key, + base::Time now, + std::unique_ptr handle) { + store_->UpdateEntryLastUsed( + key, now, + WrapErrorCallbackToPopInFlightEntryModification(key, base::DoNothing()) + .Then(DoNothingWithBoundHandle(std::move(handle)))); +} + +void SqlBackendImpl::OnOptionalEntryOperationFinished( + const CacheEntryKey& key, + EntryResultCallback callback, + std::unique_ptr handle, + SqlPersistentStore::OptionalEntryInfoOrError result) { + // If the store operation failed or the entry was not found (for OpenEntry). + if (!result.has_value() || !result->has_value()) { + std::move(callback).Run(EntryResult::MakeError(net::ERR_FAILED)); + return; + } + + SqlPersistentStore::EntryInfo& entry_info = *(*result); + ApplyInFlightEntryModifications(key, entry_info); + + // Create a new SqlEntryImpl instance. + scoped_refptr new_entry = base::MakeRefCounted( + weak_factory_.GetWeakPtr(), key, entry_info.token, entry_info.last_used, + entry_info.body_end, entry_info.head); + + // Add a reference for passing to the `callback`. + new_entry->AddRef(); + // Add the new entry to the active_entries_ map. + auto insert_result = active_entries_.insert( + std::make_pair(key, raw_ref(*new_entry.get()))); + CHECK(insert_result.second); + + // Run the original callback with the newly created/opened entry. + std::move(callback).Run((*result)->opened + ? EntryResult::MakeOpened(new_entry.get()) + : EntryResult::MakeCreated(new_entry.get())); + + MaybeTriggerEviction(); +} + +void SqlBackendImpl::OnEntryOperationFinished( + const CacheEntryKey& key, + EntryResultCallback callback, + std::unique_ptr handle, + SqlPersistentStore::EntryInfoOrError result) { + // This is a helper to adapt EntryInfoOrError to + // OnOptionalEntryOperationFinished which expects OptionalEntryInfoOrError. + if (result.has_value()) { + OnOptionalEntryOperationFinished(key, std::move(callback), + std::move(handle), std::move(*result)); + } else { + OnOptionalEntryOperationFinished(key, std::move(callback), + std::move(handle), + base::unexpected(result.error())); + } +} + +void SqlBackendImpl::ReleaseActiveEntry(SqlEntryImpl& entry) { + auto it = active_entries_.find(entry.cache_key()); + // The entry must exist in the active_entries_ map. + CHECK(it != active_entries_.end()); + CHECK_EQ(&it->second.get(), &entry); + active_entries_.erase(it); +} + +void SqlBackendImpl::ReleaseDoomedEntry(SqlEntryImpl& entry) { + auto it = doomed_entries_.find(entry); + // The entry must exist in the doomed_entries_ set. + CHECK(it != doomed_entries_.end()); + doomed_entries_.erase(it); + exclusive_operation_coordinator_.PostOrRunNormalOperation( + entry.cache_key(), + base::BindOnce(&SqlBackendImpl::HandleDeleteDoomedEntry, + weak_factory_.GetWeakPtr(), entry.cache_key(), + entry.token())); +} + +void SqlBackendImpl::HandleDeleteDoomedEntry( + const CacheEntryKey& key, + const base::UnguessableToken& token, + std::unique_ptr handle) { + store_->DeleteDoomedEntry( + key, token, + base::BindOnce( + [](std::unique_ptr + handle, + SqlPersistentStore::Error error) {}, + std::move(handle))); +} + +void SqlBackendImpl::UpdateEntryLastUsed( + const CacheEntryKey& key, + const base::UnguessableToken& token, + base::Time last_used, + SqlPersistentStore::ErrorCallback callback) { + in_flight_entry_modifications_[key].emplace_back(token, last_used); + exclusive_operation_coordinator_.PostOrRunNormalOperation( + key, base::BindOnce(&SqlBackendImpl::HandleUpdateEntryLastUsedOperation, + weak_factory_.GetWeakPtr(), key, token, last_used, + std::move(callback))); +} + +void SqlBackendImpl::HandleUpdateEntryLastUsedOperation( + const CacheEntryKey& key, + const base::UnguessableToken& token, + base::Time last_used, + SqlPersistentStore::ErrorCallback callback, + std::unique_ptr handle) { + store_->UpdateEntryLastUsed( + key, last_used, + WrapErrorCallbackToPopInFlightEntryModification(key, std::move(callback)) + .Then(DoNothingWithBoundHandle(std::move(handle)))); +} + +void SqlBackendImpl::UpdateEntryHeaderAndLastUsed( + const CacheEntryKey& key, + const base::UnguessableToken& token, + base::Time last_used, + scoped_refptr buffer, + int64_t header_size_delta, + SqlPersistentStore::ErrorCallback callback) { + in_flight_entry_modifications_[key].emplace_back(token, last_used, buffer); + exclusive_operation_coordinator_.PostOrRunNormalOperation( + key, base::BindOnce( + &SqlBackendImpl::HandleUpdateEntryHeaderAndLastUsedOperation, + weak_factory_.GetWeakPtr(), key, token, last_used, + std::move(buffer), header_size_delta, std::move(callback))); +} + +void SqlBackendImpl::HandleUpdateEntryHeaderAndLastUsedOperation( + const CacheEntryKey& key, + const base::UnguessableToken& token, + base::Time last_used, + scoped_refptr buffer, + int64_t header_size_delta, + SqlPersistentStore::ErrorCallback callback, + std::unique_ptr handle) { + store_->UpdateEntryHeaderAndLastUsed( + key, token, last_used, std::move(buffer), header_size_delta, + WrapErrorCallbackToPopInFlightEntryModification(key, std::move(callback)) + .Then(DoNothingWithBoundHandle(std::move(handle)))); +} + +void SqlBackendImpl::WriteEntryData( + const CacheEntryKey& key, + const base::UnguessableToken& token, + int64_t old_body_end, + int64_t body_end, + int64_t offset, + scoped_refptr buffer, + int buf_len, + bool truncate, + SqlPersistentStore::ErrorCallback callback) { + in_flight_entry_modifications_[key].emplace_back(token, body_end); + exclusive_operation_coordinator_.PostOrRunNormalOperation( + key, base::BindOnce(&SqlBackendImpl::HandleWriteEntryDataOperation, + weak_factory_.GetWeakPtr(), key, token, old_body_end, + offset, std::move(buffer), buf_len, truncate, + std::move(callback))); +} + +void SqlBackendImpl::HandleWriteEntryDataOperation( + const CacheEntryKey& key, + const base::UnguessableToken& token, + int64_t old_body_end, + int64_t offset, + scoped_refptr buffer, + int buf_len, + bool truncate, + SqlPersistentStore::ErrorCallback callback, + std::unique_ptr handle) { + store_->WriteEntryData( + key, token, old_body_end, offset, std::move(buffer), buf_len, truncate, + WrapErrorCallbackToPopInFlightEntryModification(key, std::move(callback)) + .Then(DoNothingWithBoundHandle(std::move(handle)))); +} + +void SqlBackendImpl::ReadEntryData( + const CacheEntryKey& key, + const base::UnguessableToken& token, + int64_t offset, + scoped_refptr buffer, + int buf_len, + int64_t body_end, + bool sparse_reading, + SqlPersistentStore::IntOrErrorCallback callback) { + exclusive_operation_coordinator_.PostOrRunNormalOperation( + key, base::BindOnce(&SqlBackendImpl::HandleReadEntryDataOperation, + weak_factory_.GetWeakPtr(), token, offset, + std::move(buffer), buf_len, body_end, sparse_reading, + std::move(callback))); +} + +void SqlBackendImpl::HandleReadEntryDataOperation( + const base::UnguessableToken& token, + int64_t offset, + scoped_refptr buffer, + int buf_len, + int64_t body_end, + bool sparse_reading, + SqlPersistentStore::IntOrErrorCallback callback, + std::unique_ptr handle) { + store_->ReadEntryData( + token, offset, buffer, buf_len, body_end, sparse_reading, + std::move(callback).Then(DoNothingWithBoundHandle(std::move(handle)))); +} + +void SqlBackendImpl::GetEntryAvailableRange(const CacheEntryKey& key, + const base::UnguessableToken& token, + int64_t offset, + int len, + RangeResultCallback callback) { + exclusive_operation_coordinator_.PostOrRunNormalOperation( + key, + base::BindOnce(&SqlBackendImpl::HandleGetEntryAvailableRangeOperation, + weak_factory_.GetWeakPtr(), token, offset, len, + std::move(callback))); +} + +void SqlBackendImpl::HandleGetEntryAvailableRangeOperation( + const base::UnguessableToken& token, + int64_t offset, + int len, + RangeResultCallback callback, + std::unique_ptr handle) { + store_->GetEntryAvailableRange(token, offset, len, std::move(callback)); +} + +void SqlBackendImpl::ApplyInFlightEntryModifications( + const CacheEntryKey& key, + SqlPersistentStore::EntryInfo& entry_info) { + auto it = in_flight_entry_modifications_.find(key); + if (it == in_flight_entry_modifications_.end()) { + return; + } + for (const auto& modification : it->second) { + if (modification.token.is_empty() || + modification.token == entry_info.token) { + if (modification.last_used.has_value()) { + entry_info.last_used = *modification.last_used; + } + if (modification.head.has_value()) { + entry_info.head = *modification.head; + } + if (modification.body_end.has_value()) { + entry_info.body_end = *modification.body_end; + } + } + } +} + +SqlPersistentStore::ErrorCallback +SqlBackendImpl::WrapErrorCallbackToPopInFlightEntryModification( + const CacheEntryKey& key, + SqlPersistentStore::ErrorCallback callback) { + return base::BindOnce( + [](base::WeakPtr weak_ptr, const CacheEntryKey& key, + SqlPersistentStore::ErrorCallback callback, + SqlPersistentStore::Error result) { + if (weak_ptr) { + // The in-flight modifications for a given key are queued and removed + // in FIFO order. This is safe because + // `exclusive_operation_coordinator_` serializes all normal operations + // for the same key. This guarantees that modifications are enqueued + // and the corresponding store operations are executed in the same + // order. + auto it = weak_ptr->in_flight_entry_modifications_.find(key); + CHECK(it != weak_ptr->in_flight_entry_modifications_.end()); + CHECK(!it->second.empty()); + it->second.pop_front(); + if (it->second.empty()) { + weak_ptr->in_flight_entry_modifications_.erase(it); + } + } + std::move(callback).Run(result); + }, + weak_factory_.GetWeakPtr(), key, std::move(callback)); +} + +int SqlBackendImpl::FlushQueueForTest(CompletionOnceCallback callback) { + exclusive_operation_coordinator_.PostOrRunExclusiveOperation(base::BindOnce( + [](scoped_refptr background_task_runner, + CompletionOnceCallback callback, + std::unique_ptr + handle) { + background_task_runner->PostTaskAndReply( + // Post a no-op task to the background runner. + FROM_HERE, base::BindOnce([]() {}), + base::BindOnce(std::move(callback), net::OK) + .Then(DoNothingWithBoundHandle(std::move(handle)))); + }, + background_task_runner_, std::move(callback))); + + return net::ERR_IO_PENDING; +} + +void SqlBackendImpl::MaybeTriggerEviction() { + if (!store_->ShouldStartEviction() || eviction_operation_queued_) { + return; + } + eviction_operation_queued_ = true; + exclusive_operation_coordinator_.PostOrRunExclusiveOperation(base::BindOnce( + base::BindOnce(&SqlBackendImpl::HandleTriggerEvictionOperation, + weak_factory_.GetWeakPtr()))); +} + +void SqlBackendImpl::HandleTriggerEvictionOperation( + std::unique_ptr handle) { + eviction_operation_queued_ = false; + if (!store_->ShouldStartEviction()) { + return; + } + std::vector excluded_keys_vec; + excluded_keys_vec.reserve(active_entries_.size()); + for (const auto& pair : active_entries_) { + excluded_keys_vec.push_back(pair.first); + } + base::flat_set excluded_keys(base::sorted_unique, + std::move(excluded_keys_vec)); + store_->StartEviction( + std::move(excluded_keys), + base::BindOnce([](SqlPersistentStore::Error result) {})); +} + +void SqlBackendImpl::TriggerDeleteDoomedEntries() { + exclusive_operation_coordinator_.PostOrRunExclusiveOperation(base::BindOnce( + base::BindOnce(&SqlBackendImpl::HandleDeleteDoomedEntriesOperation, + weak_factory_.GetWeakPtr()))); +} + +void SqlBackendImpl::HandleDeleteDoomedEntriesOperation( + std::unique_ptr handle) { + std::vector excluded_tokens_vec; + excluded_tokens_vec.reserve(doomed_entries_.size()); + for (const auto& entry : doomed_entries_) { + excluded_tokens_vec.push_back(entry->token()); + } + std::sort(excluded_tokens_vec.begin(), excluded_tokens_vec.end()); + base::flat_set excluded_tokens( + base::sorted_unique, std::move(excluded_tokens_vec)); + store_->DeleteDoomedEntries( + std::move(excluded_tokens), + base::BindOnce([](SqlPersistentStore::Error result) { + }).Then(DoNothingWithBoundHandle(std::move(handle)))); +} + +void SqlBackendImpl::EnableStrictCorruptionCheckForTesting() { + store_->EnableStrictCorruptionCheckForTesting(); // IN-TEST +} + +SqlBackendImpl::InFlightEntryModification::InFlightEntryModification( + const base::UnguessableToken& token, + base::Time last_used) + : token(token), last_used(last_used) {} +SqlBackendImpl::InFlightEntryModification::InFlightEntryModification( + const base::UnguessableToken& token, + base::Time last_used, + scoped_refptr head) + : token(token), last_used(last_used), head(std::move(head)) {} +SqlBackendImpl::InFlightEntryModification::InFlightEntryModification( + const base::UnguessableToken& token, + int64_t body_end) + : token(token), body_end(body_end) {} +SqlBackendImpl::InFlightEntryModification::~InFlightEntryModification() = + default; +SqlBackendImpl::InFlightEntryModification::InFlightEntryModification( + InFlightEntryModification&&) = default; + } // namespace disk_cache diff --git a/naiveproxy/src/net/disk_cache/sql/sql_backend_impl.h b/naiveproxy/src/net/disk_cache/sql/sql_backend_impl.h index 695fa57d0f..649aa258da 100644 --- a/naiveproxy/src/net/disk_cache/sql/sql_backend_impl.h +++ b/naiveproxy/src/net/disk_cache/sql/sql_backend_impl.h @@ -5,31 +5,75 @@ #ifndef NET_DISK_CACHE_SQL_SQL_BACKEND_IMPL_H_ #define NET_DISK_CACHE_SQL_SQL_BACKEND_IMPL_H_ +#include +#include +#include +#include +#include + +#include "base/files/file_path.h" +#include "base/memory/raw_ref.h" +#include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "net/base/net_export.h" #include "net/disk_cache/buildflags.h" #include "net/disk_cache/disk_cache.h" +#include "net/disk_cache/sql/cache_entry_key.h" +#include "net/disk_cache/sql/exclusive_operation_coordinator.h" +#include "net/disk_cache/sql/sql_persistent_store.h" // This backend is experimental and only available when the build flag is set. static_assert(BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND)); +namespace base { +class SequencedTaskRunner; +} // namespace base + namespace disk_cache { +class SqlEntryImpl; + // Provides a concrete implementation of the disk cache backend that stores // entries in a SQLite database. This class is responsible for all operations // related to creating, opening, dooming, and enumerating cache entries. // -// NOTE: This is currently a skeleton implementation, and most methods are not +// NOTE: This is currently a skeleton implementation, and some methods are not // yet implemented, returning `net::ERR_NOT_IMPLEMENTED`. class NET_EXPORT_PRIVATE SqlBackendImpl final : public Backend { public: - explicit SqlBackendImpl(net::CacheType cache_type); + // An enumeration of errors that can occur during the fake index file check. + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. + // + // LINT.IfChange(FakeIndexFileError) + enum class FakeIndexFileError { + kOkNew = 0, + kOkExisting = 1, + kCreateFileFailed = 2, + kWriteFileFailed = 3, + kWrongFileSize = 4, + kOpenFileFailed = 5, + kReadFileFailed = 6, + kWrongMagicNumber = 7, + kFailedToCreateDirectory = 8, + kMaxValue = kFailedToCreateDirectory, + }; + // LINT.ThenChange(//tools/metrics/histograms/metadata/net/enums.xml:SqlDiskCacheFakeIndexFileError) + + SqlBackendImpl(const base::FilePath& path, + int64_t max_bytes, + net::CacheType cache_type); SqlBackendImpl(const SqlBackendImpl&) = delete; SqlBackendImpl& operator=(const SqlBackendImpl&) = delete; ~SqlBackendImpl() override; + // Initializes the backend, which includes initializing the persistent store + // and checking for a fake index file. These two operations are performed in + // parallel. + void Init(CompletionOnceCallback callback); + // Backend interface. int64_t MaxFileSize() const override; int32_t GetEntryCount( @@ -61,6 +105,325 @@ class NET_EXPORT_PRIVATE SqlBackendImpl final : public Backend { std::unique_ptr CreateIterator() override; void GetStats(base::StringPairs* stats) override; void OnExternalCacheHit(const std::string& key) override; + + // Called by SqlEntryImpl when it's being closed and is not doomed. + // Removes the entry from `active_entries_`. + void ReleaseActiveEntry(SqlEntryImpl& entry); + // Called by SqlEntryImpl when it's being closed and is doomed. + // Removes the entry from `doomed_entries_`. + void ReleaseDoomedEntry(SqlEntryImpl& entry); + + // Marks an active entry as doomed and initiates its removal from the store. + // If `callback` is provided, it will be run upon completion. + void DoomActiveEntry(SqlEntryImpl& entry, CompletionOnceCallback callback); + + // Updates the `last_used` timestamp for an entry. + void UpdateEntryLastUsed(const CacheEntryKey& key, + const base::UnguessableToken& token, + base::Time last_used, + SqlPersistentStore::ErrorCallback callback); + + // Updates the header data and `last_used` timestamp for an entry. + void UpdateEntryHeaderAndLastUsed(const CacheEntryKey& key, + const base::UnguessableToken& token, + base::Time last_used, + scoped_refptr buffer, + int64_t header_size_delta, + SqlPersistentStore::ErrorCallback callback); + + // Writes data to an entry's body (stream 1). This can be used to write new + // data, overwrite existing data, or append to the entry. The operation is + // scheduled via the `ExclusiveOperationCoordinator` to ensure proper + // serialization. + void WriteEntryData(const CacheEntryKey& key, + const base::UnguessableToken& token, + int64_t old_body_end, + int64_t body_end, + int64_t offset, + scoped_refptr buffer, + int buf_len, + bool truncate, + SqlPersistentStore::ErrorCallback callback); + + // Reads data from an entry's body (stream 1). The operation is scheduled via + // the `ExclusiveOperationCoordinator`. `sparse_reading` controls whether + // gaps in the data are filled with zeros or cause the read to stop. + void ReadEntryData(const CacheEntryKey& key, + const base::UnguessableToken& token, + int64_t offset, + scoped_refptr buffer, + int buf_len, + int64_t body_end, + bool sparse_reading, + SqlPersistentStore::IntOrErrorCallback callback); + + // Finds the available contiguous range of data for a given entry. The + // operation is scheduled via the `ExclusiveOperationCoordinator` to ensure + // proper serialization. + void GetEntryAvailableRange(const CacheEntryKey& key, + const base::UnguessableToken& token, + int64_t offset, + int len, + RangeResultCallback callback); + + // Sends a dummy operation through the background task runner via the + // operation coordinator, for unit tests. + int FlushQueueForTest(CompletionOnceCallback callback); + + scoped_refptr GetBackgroundTaskRunnerForTest() { + return background_task_runner_; + } + + // Enables a strict corruption checking mode for testing purposes. When + // enabled, any detected database corruption will cause an immediate crash + // via a `CHECK` failure. This is primarily useful for fuzzers, which can more + // easily identify problematic inputs if the process fails fast, rather than + // silently recovering. + void EnableStrictCorruptionCheckForTesting(); + + private: + class IteratorImpl; + + // Identifies the type of a entry operation. + enum class OpenOrCreateEntryOperationType { + kCreateEntry, + kOpenEntry, + kOpenOrCreateEntry, + }; + + // Represents an in-flight modification to an entry's metadata (e.g., + // last_used, header). These modifications are queued and applied when the + // entry is re-activated by `Iterator::OpenNextEntry()`. + struct InFlightEntryModification { + InFlightEntryModification(const base::UnguessableToken& token, + base::Time last_used); + InFlightEntryModification(const base::UnguessableToken& token, + base::Time last_used, + scoped_refptr head); + InFlightEntryModification(const base::UnguessableToken& token, + int64_t body_end); + ~InFlightEntryModification(); + InFlightEntryModification(InFlightEntryModification&&); + + base::UnguessableToken token; + std::optional last_used; + std::optional> head; + std::optional body_end; + }; + + void OnInitialized(CompletionOnceCallback callback, + const std::vector& results); + + SqlEntryImpl* GetActiveEntry(const CacheEntryKey& key); + + // Checks if the cache size has exceeded the high watermark and, if so, + // schedules an eviction task. This is typically called after operations that + // might increase the cache size. The eviction itself is run as an exclusive + // operation to prevent conflicts with other cache activities. + void MaybeTriggerEviction(); + + // Internal helper for Open/Create/OpenOrCreate operations. It uses + // `ExclusiveOperationCoordinator` to serialize operations on the same key and + // to correctly handle synchronous vs. asynchronous returns. + EntryResult OpenOrCreateEntryInternal(OpenOrCreateEntryOperationType type, + const std::string& key, + EntryResultCallback callback); + + // Handles the backend logic for Open/Create/OpenOrCreate operations. This + // method is scheduled as a normal operation via the + // `ExclusiveOperationCoordinator` to ensure proper serialization against + // other operations on the same key. + void HandleOpenOrCreateEntryOperation( + OpenOrCreateEntryOperationType type, + const CacheEntryKey& entry_key, + EntryResultCallback callback, + std::unique_ptr handle); + + // Callback for store operations that return an EntryInfo (`OpenOrCreate()`, + // `Create()`). + void OnEntryOperationFinished( + const CacheEntryKey& key, + EntryResultCallback callback, + std::unique_ptr handle, + SqlPersistentStore::EntryInfoOrError result); + // Callback for store operations that return an optional + // (`Open()`). + void OnOptionalEntryOperationFinished( + const CacheEntryKey& key, + EntryResultCallback callback, + std::unique_ptr handle, + SqlPersistentStore::OptionalEntryInfoOrError result); + + // Handles the backend logic for `DoomActiveEntry()`. This method is scheduled + // as a normal operation via the `ExclusiveOperationCoordinator`. + void HandleDoomActiveEntryOperation( + scoped_refptr entry, + CompletionOnceCallback callback, + std::unique_ptr handle); + + // Dooms an active entry. This method must be called while holding an + // `ExclusiveOperationCoordinator::OperationHandle` to ensure proper + // serialization of operations on the entry. + void DoomActiveEntryInternal(SqlEntryImpl& entry, + CompletionOnceCallback callback); + + // Handles the backend logic for `ReleaseDoomedEntry()`. This method is + // scheduled as a normal operation via the `ExclusiveOperationCoordinator`. + void HandleDeleteDoomedEntry( + const CacheEntryKey& key, + const base::UnguessableToken& token, + std::unique_ptr handle); + + // Handles the backend logic for `DoomEntry()`. This method is scheduled as a + // normal operation via the `ExclusiveOperationCoordinator`. + void HandleDoomEntryOperation( + const CacheEntryKey& key, + net::RequestPriority priority, + CompletionOnceCallback callback, + std::unique_ptr handle); + + // Handles the backend logic for `DoomEntriesBetween()`. This method is + // scheduled as an exclusive operation via the + // `ExclusiveOperationCoordinator`. + void HandleDoomEntriesBetweenOperation( + base::Time initial_time, + base::Time end_time, + CompletionOnceCallback callback, + std::unique_ptr handle); + + // Handles the backend logic for `UpdateEntryLastUsed()`. This method is + // scheduled as a normal operation via the `ExclusiveOperationCoordinator`. + void HandleUpdateEntryLastUsedOperation( + const CacheEntryKey& key, + const base::UnguessableToken& token, + base::Time last_used, + SqlPersistentStore::ErrorCallback callback, + std::unique_ptr handle); + + // Handles the backend logic for `UpdateEntryHeaderAndLastUsed()`. This method + // is scheduled as a normal operation via the `ExclusiveOperationCoordinator`. + void HandleUpdateEntryHeaderAndLastUsedOperation( + const CacheEntryKey& key, + const base::UnguessableToken& token, + base::Time last_used, + scoped_refptr buffer, + int64_t header_size_delta, + SqlPersistentStore::ErrorCallback callback, + std::unique_ptr handle); + + // Handles the backend logic for `WriteEntryData()`. This method is scheduled + // as a normal operation via the `ExclusiveOperationCoordinator` and forwards + // the call to the persistent store. + void HandleWriteEntryDataOperation( + const CacheEntryKey& key, + const base::UnguessableToken& token, + int64_t old_body_end, + int64_t offset, + scoped_refptr buffer, + int buf_len, + bool truncate, + SqlPersistentStore::ErrorCallback callback, + std::unique_ptr handle); + + // Handles the backend logic for `ReadEntryData()`. This method is scheduled + // as a normal operation via the `ExclusiveOperationCoordinator` and forwards + // the call to the persistent store. + void HandleReadEntryDataOperation( + const base::UnguessableToken& token, + int64_t offset, + scoped_refptr buffer, + int buf_len, + int64_t body_end, + bool sparse_reading, + SqlPersistentStore::IntOrErrorCallback callback, + std::unique_ptr handle); + + // Handles the backend logic for `GetEntryAvailableRange()`. This method is + // scheduled as a normal operation via the `ExclusiveOperationCoordinator` + // and forwards the call to the persistent store. + void HandleGetEntryAvailableRangeOperation( + const base::UnguessableToken& token, + int64_t offset, + int len, + RangeResultCallback callback, + std::unique_ptr handle); + + // Handles the backend logic for cache eviction. This method is scheduled as + // an exclusive operation to ensure no other cache activities are running. It + // gathers the keys of all active entries to prevent them from being evicted + // and then delegates the actual eviction logic to the persistent store. + void HandleTriggerEvictionOperation( + std::unique_ptr handle); + + // Handles the backend logic for `OnExternalCacheHit()`. This method is + // scheduled as a normal operation via the `ExclusiveOperationCoordinator`. + void HandleOnExternalCacheHitOperation( + const CacheEntryKey& key, + base::Time now, + std::unique_ptr handle); + + // Applies in-flight modifications to an entry's info. + void ApplyInFlightEntryModifications( + const CacheEntryKey& key, + SqlPersistentStore::EntryInfo& entry_info); + + // Wraps an `ErrorCallback` to pop the oldest in-flight entry modification + // from `in_flight_entry_modifications_` once the callback is invoked. This + // ensures that the queue of in-flight modifications is managed correctly. + SqlPersistentStore::ErrorCallback + WrapErrorCallbackToPopInFlightEntryModification( + const CacheEntryKey& key, + SqlPersistentStore::ErrorCallback callback); + + // Schedules the `HandleDeleteDoomedEntriesOperation` task to run. This is the + // entry point for the one-time cleanup of entries that were doomed in a + // previous session. + void TriggerDeleteDoomedEntries(); + + // Physically deletes entries that were marked as "doomed" in previous + // sessions from the database. It excludes any currently active doomed entries + // to prevent data corruption. This method is executed as an exclusive + // operation to ensure it has sole access to the cache during cleanup. + void HandleDeleteDoomedEntriesOperation( + std::unique_ptr handle); + + const base::FilePath path_; + + // Task runner for all background SQLite operations. + scoped_refptr background_task_runner_; + + // The persistent store that manages the SQLite database. + std::unique_ptr store_; + + // Map of cache keys to currently active (opened) entries. + // `raw_ref` is used because the SqlEntryImpl objects are ref-counted and + // their lifetime is managed by their ref_count. This map only holds + // non-owning references to them. + std::map> active_entries_; + + // Set of entries that have been marked as doomed but are still active + // (i.e., have outstanding references). + std::set> doomed_entries_; + + // Coordinates exclusive and normal operations to ensure that exclusive + // operations have exclusive access. + ExclusiveOperationCoordinator exclusive_operation_coordinator_; + + // Queue of in-flight entry modifications that need to be applied. + // These are typically updates to `last_used` or header data that occur + // while an entry is not actively open. + std::map> + in_flight_entry_modifications_; + + // A flag to prevent queuing multiple eviction operations. It is set to true + // when an eviction operation is posted to the `ExclusiveOperationCoordinator` + // and reset to false when the operation begins execution. This ensures that + // even if `MaybeTriggerEviction()` is called multiple times while an eviction + // task is pending, only one will be in the queue at any time. + bool eviction_operation_queued_ = false; + + // Weak pointer factory for this class. + base::WeakPtrFactory weak_factory_{this}; }; } // namespace disk_cache diff --git a/naiveproxy/src/net/disk_cache/sql/sql_entry_impl.cc b/naiveproxy/src/net/disk_cache/sql/sql_entry_impl.cc new file mode 100644 index 0000000000..e6e3fa60fc --- /dev/null +++ b/naiveproxy/src/net/disk_cache/sql/sql_entry_impl.cc @@ -0,0 +1,364 @@ +// Copyright 2025 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/disk_cache/sql/sql_entry_impl.h" + +#include "base/functional/callback_helpers.h" +#include "base/task/bind_post_task.h" +#include "net/base/io_buffer.h" +#include "net/base/net_errors.h" +#include "net/disk_cache/sql/sql_backend_impl.h" + +namespace disk_cache { +namespace { + +// Wraps a OnceCallback. If the returned callback is destroyed without being +// run, the original callback is run with `abort_result`. +// This ensures that the callback is always run, even if the operation is +// cancelled or the owner is destroyed. +template +base::OnceCallback WrapCallbackWithAbortError( + base::OnceCallback callback, + ResultType abort_result) { + CHECK(callback); + auto [success_cb, failure_cb] = base::SplitOnceCallback(std::move(callback)); + + // The ScopedClosureRunner will run the `failure_cb` with `abort_result` if + // it's destroyed before being released. + auto runner = std::make_unique( + base::BindPostTaskToCurrentDefault( + base::BindOnce(std::move(failure_cb), abort_result))); + + // The returned callback represents the "success" path. + return base::BindOnce( + [](std::unique_ptr runner, + base::OnceCallback cb, ResultType result) { + // Release the runner to prevent the failure callback from running on + // destruction. + std::ignore = runner->Release(); + // Run the success callback with the provided result. + std::move(cb).Run(std::move(result)); + }, + std::move(runner), std::move(success_cb)); +} + +} // namespace + +SqlEntryImpl::SqlEntryImpl(base::WeakPtr backend, + CacheEntryKey key, + const base::UnguessableToken& token, + base::Time last_used, + int64_t body_end, + scoped_refptr head) + : backend_(backend), + key_(key), + token_(token), + last_used_(last_used), + body_end_(body_end), + head_(head ? std::move(head) + : base::MakeRefCounted()) {} + +SqlEntryImpl::~SqlEntryImpl() { + if (!backend_) { + return; + } + + if (doomed_) { + backend_->ReleaseDoomedEntry(*this); + } else { + if (previous_header_size_in_storage_.has_value()) { + // If the entry's header was modified (i.e., a write to stream 0 + // occurred), update both the header and `last_used_` in the persistent + // store. + const int64_t header_size_delta = static_cast(head_->size()) - + *previous_header_size_in_storage_; + backend_->UpdateEntryHeaderAndLastUsed(key_, token_, last_used_, head_, + header_size_delta, + base::DoNothing()); + } else if (last_used_modified_) { + // Otherwise, if only last_used was modified, update just last_used. + backend_->UpdateEntryLastUsed(key_, token_, last_used_, + base::DoNothing()); + } + backend_->ReleaseActiveEntry(*this); + } +} + +void SqlEntryImpl::Doom() { + if (doomed_ || !backend_) { + return; + } + backend_->DoomActiveEntry(*this, base::DoNothing()); +} + +void SqlEntryImpl::Close() { + Release(); +} + +std::string SqlEntryImpl::GetKey() const { + return key_.string(); +} + +base::Time SqlEntryImpl::GetLastUsed() const { + return last_used_; +} + +int64_t SqlEntryImpl::GetDataSize(int index) const { + if (index != 0 && index != 1) { + return net::ERR_INVALID_ARGUMENT; + } + if (index == 0) { + return head_->size(); + } + CHECK_EQ(index, 1); + return body_end_; +} + +int SqlEntryImpl::ReadData(int index, + int64_t offset, + IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback) { + UpdateLastUsed(); + if (index != 0 && index != 1) { + return net::ERR_INVALID_ARGUMENT; + } + if (buf_len == 0) { + return 0; + } + // Unlike WriteData, there is no overflow check for `offset + buf_len` here. + // This is intentional. The read path is designed to be permissive: even if + // the requested range would overflow, the underlying SqlPersistentStore will + // truncate the read length to fit within the `int64_t` range, allowing a + // partial read up to the maximum possible offset. + // + // TODO(crbug.com/422065015): To enable int64_t offset writes for stream 1 in + // the SQL backend, the check for offset against int max should be moved to + // the index == 0 logic path, as stream 1 of SQL backend is designed to handle + // offsets larger than int max. + if (!buf || buf_len < 0 || offset < 0 || + offset > std::numeric_limits::max()) { + return net::ERR_INVALID_ARGUMENT; + } + + if (index == 1) { + return ReadDataInternal(offset, buf, buf_len, std::move(callback), + /*sparse_reading=*/false); + } + // Ensure it's stream 0 (header). + CHECK_EQ(index, 0); + if (head_->size() <= offset) { + return 0; + } + buf_len = std::min(buf_len, head_->size() - static_cast(offset)); + buf->first(buf_len).copy_from_nonoverlapping(head_->span().subspan( + static_cast(offset), static_cast(buf_len))); + return buf_len; +} + +int SqlEntryImpl::ReadDataInternal(int64_t offset, + IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback, + bool sparse_reading) { + if (!backend_) { + return net::ERR_FAILED; + } + if (body_end_ <= offset) { + return 0; + } + backend_->ReadEntryData( + key_, token_, offset, buf, buf_len, body_end_, sparse_reading, + base::BindOnce( + [](CompletionOnceCallback callback, + SqlPersistentStore::IntOrError result) { + std::move(callback).Run(result.value_or(net::ERR_FAILED)); + }, + WrapCallbackWithAbortError(std::move(callback), + net::ERR_ABORTED))); + return net::ERR_IO_PENDING; +} + +int SqlEntryImpl::WriteData(int index, + int64_t offset, + IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback, + bool truncate) { + UpdateLastUsed(); + if ((index != 0 && index != 1) || (offset < 0) || (buf_len < 0) || + (!buf && buf_len > 0) || !base::CheckAdd(offset, buf_len).IsValid()) { + return net::ERR_INVALID_ARGUMENT; + } + + // TODO(crbug.com/422065015): To enable int64_t offset reads for stream 1 in + // the SQL backend, the check should be moved to the index == 0 logic path, as + // stream 1 of SQL backend is designed to handle offsets larger than int max. + if (offset + buf_len > std::numeric_limits::max()) { + return net::ERR_INVALID_ARGUMENT; + } + + if (index == 1) { + return WriteDataInternal(offset, buf, buf_len, std::move(callback), + truncate, /*sparse_write=*/false); + } + CHECK_EQ(index, 0); + + // If this is the first write to the header, store its original size for later + // persistence. + if (!previous_header_size_in_storage_) { + previous_header_size_in_storage_ = head_->size(); + } + + size_t u_offset = base::checked_cast(offset); + size_t u_buf_len = base::checked_cast(buf_len); + if (offset == 0 && truncate) { + head_->SetCapacity(buf_len); + if (buf_len) { + head_->span().copy_from(buf->first(u_buf_len)); + } + } else { + const size_t original_size = head_->size(); + const size_t buffer_size = + truncate ? u_offset + u_buf_len + : std::max(u_offset + u_buf_len, original_size); + head_->SetCapacity(base::checked_cast(buffer_size)); + + // Fill any gap with zeros if writing beyond current size. + const size_t fill_size = + u_offset <= original_size ? 0 : u_offset - original_size; + if (fill_size > 0) { + std::ranges::fill(head_->span().subspan(original_size, fill_size), 0); + } + // Copy new data into the buffer. + if (buf) { + head_->span().subspan(u_offset).copy_prefix_from(buf->first(u_buf_len)); + } + } + return buf_len; +} + +int SqlEntryImpl::WriteDataInternal(int64_t offset, + IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback, + bool truncate, + bool sparse_write) { + if (!backend_) { + return net::ERR_FAILED; + } + // Ignore zero-length writes that do not change the file size. + if (buf_len == 0) { + if (truncate ? (offset == body_end_) : (offset <= body_end_)) { + return buf_len; + } + } + // The end of the current write must not cause an integer overflow. Callers + // are responsible for validating this, so we CHECK it here. + const int64_t end_offset = base::CheckAdd(offset, buf_len).ValueOrDie(); + // Calculate the new size of the body (stream 1). If `truncate` is true, the + // new size is the end of the current write. Otherwise, the body is extended + // if the write goes past the current end. + const int64_t new_body_end = + truncate ? end_offset : std::max(end_offset, body_end_); + + if (!sparse_write && new_body_end > backend_->MaxFileSize()) { + return net::ERR_FAILED; + } + + const auto old_body_end = body_end_; + body_end_ = new_body_end; + + // TODO(crbug.com/422065015): Consider implementing optimistic writes, similar + // to Simple Cache (see https://chromiumcodereview.appspot.com/13907009). This + // would allow returning synchronously if no other operations are pending. + backend_->WriteEntryData( + key_, token_, old_body_end, body_end_, offset, buf, buf_len, truncate, + base::BindOnce( + [](CompletionOnceCallback callback, int buf_len, + SqlPersistentStore::Error result) { + std::move(callback).Run(result == SqlPersistentStore::Error::kOk + ? buf_len + : net::ERR_FAILED); + }, + WrapCallbackWithAbortError(std::move(callback), + net::ERR_ABORTED), + buf_len)); + return net::ERR_IO_PENDING; +} + +int SqlEntryImpl::ReadSparseData(int64_t offset, + IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback) { + UpdateLastUsed(); + if (buf_len == 0) { + return net::OK; + } + if (!buf || buf_len < 0 || offset < 0) { + return net::ERR_INVALID_ARGUMENT; + } + return ReadDataInternal(offset, buf, buf_len, std::move(callback), + /*sparse_reading=*/true); +} + +int SqlEntryImpl::WriteSparseData(int64_t offset, + IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback) { + UpdateLastUsed(); + if ((offset < 0) || (buf_len < 0) || (!buf && buf_len > 0) || + !base::CheckAdd(offset, buf_len).IsValid()) { + return net::ERR_INVALID_ARGUMENT; + } + return WriteDataInternal(offset, buf, buf_len, std::move(callback), + /*truncate=*/false, /*sparse_write=*/true); +} + +RangeResult SqlEntryImpl::GetAvailableRange(int64_t offset, + int len, + RangeResultCallback callback) { + if (!backend_) { + return RangeResult(net::ERR_FAILED); + } + if (offset < 0 || len < 0) { + return RangeResult(net::ERR_INVALID_ARGUMENT); + } + + backend_->GetEntryAvailableRange( + key_, token_, offset, len, + WrapCallbackWithAbortError( + std::move(callback), RangeResult(net::ERR_ABORTED))); + return RangeResult(net::ERR_IO_PENDING); +} + +bool SqlEntryImpl::CouldBeSparse() const { + // SqlEntryImpl doesn't distinguish the stream 1 data and the sparse data. + return true; +} + +void SqlEntryImpl::CancelSparseIO() { + // SqlEntryImpl doesn't distinguish the stream 1 data and the sparse data. +} + +net::Error SqlEntryImpl::ReadyForSparseIO(CompletionOnceCallback callback) { + // SqlEntryImpl doesn't distinguish the stream 1 data and the sparse data. + return net::OK; +} + +void SqlEntryImpl::SetLastUsedTimeForTest(base::Time time) { + last_used_ = time; + last_used_modified_ = true; +} + +void SqlEntryImpl::UpdateLastUsed() { + last_used_ = base::Time::Now(); + last_used_modified_ = true; +} + +void SqlEntryImpl::MarkAsDoomed() { + doomed_ = true; +} + +} // namespace disk_cache diff --git a/naiveproxy/src/net/disk_cache/sql/sql_entry_impl.h b/naiveproxy/src/net/disk_cache/sql/sql_entry_impl.h new file mode 100644 index 0000000000..7e03f2caa8 --- /dev/null +++ b/naiveproxy/src/net/disk_cache/sql/sql_entry_impl.h @@ -0,0 +1,153 @@ +// Copyright 2025 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_DISK_CACHE_SQL_SQL_ENTRY_IMPL_H_ +#define NET_DISK_CACHE_SQL_SQL_ENTRY_IMPL_H_ + +#include +#include + +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/unguessable_token.h" +#include "net/disk_cache/buildflags.h" +#include "net/disk_cache/disk_cache.h" +#include "net/disk_cache/sql/cache_entry_key.h" +#include "net/disk_cache/sql/sql_persistent_store.h" +#include "net/log/net_log_with_source.h" + +// This backend is experimental and only available when the build flag is set. +static_assert(BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND)); + +namespace net { +class GrowableIOBuffer; +} // namespace net + +namespace disk_cache { + +class SqlBackendImpl; + +// Represents a single entry in the SQL-based disk cache. +// This class implements the `disk_cache::Entry` interface and is responsible +// for managing the data and metadata of a cache entry. +class NET_EXPORT_PRIVATE SqlEntryImpl final + : public Entry, + public base::RefCounted { + public: + // Constructs a SqlEntryImpl. + SqlEntryImpl(base::WeakPtr backend, + CacheEntryKey key, + const base::UnguessableToken& token, + base::Time last_used, + int64_t body_end, + scoped_refptr head); + + // From disk_cache::Entry: + void Doom() override; + void Close() override; + std::string GetKey() const override; + base::Time GetLastUsed() const override; + int64_t GetDataSize(int index) const override; + int ReadData(int index, + int64_t offset, + IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback) override; + int WriteData(int index, + int64_t offset, + IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback, + bool truncate) override; + int ReadSparseData(int64_t offset, + IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback) override; + int WriteSparseData(int64_t offset, + IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback) override; + RangeResult GetAvailableRange(int64_t offset, + int len, + RangeResultCallback callback) override; + bool CouldBeSparse() const override; + void CancelSparseIO() override; + net::Error ReadyForSparseIO(CompletionOnceCallback callback) override; + void SetLastUsedTimeForTest(base::Time time) override; + + // Returns the cache key of the entry. + const CacheEntryKey& cache_key() const { return key_; } + + // Returns the unique token for this entry instance. + const base::UnguessableToken& token() const { return token_; } + + // Marks the entry as doomed. This is called by the backend when an + // active entry is doomed. + void MarkAsDoomed(); + + bool doomed() const { return doomed_; } + + // Updates the `last_used_` timestamp to the current time. + void UpdateLastUsed(); + + private: + friend class base::RefCounted; + ~SqlEntryImpl() override; + + // Internal implementation for writing data to stream 1. This is called by + // both `WriteData` and `WriteSparseData`. It forwards the write operation to + // the backend. + int WriteDataInternal(int64_t offset, + IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback, + bool truncate, + bool sparse_write); + // Internal implementation for reading data from stream 1. This is called by + // both `ReadData` and `ReadSparseData`. It forwards the read operation to the + // backend. + int ReadDataInternal(int64_t offset, + IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback, + bool sparse_reading); + + base::WeakPtr backend_; + + // The key for this cache entry. + const CacheEntryKey key_; + + // A unique token identifying this specific instance of the entry. + // This is used to ensure that operations (like dooming or deleting) + // target the correct version of an entry if it's reopened. + const base::UnguessableToken token_; + + // The last time this entry was accessed. + base::Time last_used_; + + // Flag indicating if `last_used_` has been modified since the entry was + // opened. + bool last_used_modified_ = false; + + // The end offset of the entry's body data (stream 1). + int64_t body_end_; + + // The entry's header data (stream 0). + scoped_refptr head_; + + // Stores the original size of the header (stream 0) before it was first + // modified. `std::nullopt` indicates that the header has not been written to + // since the entry was opened. This is used in the destructor to determine if + // the header needs to be persisted to storage. + std::optional previous_header_size_in_storage_; + + // True if this entry has been marked for deletion. + bool doomed_ = false; + + base::WeakPtrFactory weak_factory_{this}; +}; + +} // namespace disk_cache + +#endif // NET_DISK_CACHE_SQL_SQL_ENTRY_IMPL_H_ diff --git a/naiveproxy/src/net/disk_cache/sql/sql_persistent_store.cc b/naiveproxy/src/net/disk_cache/sql/sql_persistent_store.cc index 752bf634b5..5a2ae5ede3 100644 --- a/naiveproxy/src/net/disk_cache/sql/sql_persistent_store.cc +++ b/naiveproxy/src/net/disk_cache/sql/sql_persistent_store.cc @@ -8,6 +8,7 @@ #include #include +#include "base/containers/flat_set.h" #include "base/files/file_util.h" #include "base/functional/bind.h" #include "base/memory/scoped_refptr.h" @@ -20,11 +21,12 @@ #include "base/system/sys_info.h" #include "base/threading/sequence_bound.h" #include "base/timer/elapsed_timer.h" +#include "base/trace_event/trace_event.h" #include "base/types/expected.h" #include "net/base/io_buffer.h" -#include "net/base/tracing.h" #include "net/disk_cache/cache_util.h" #include "net/disk_cache/sql/sql_backend_constants.h" +#include "net/disk_cache/sql/sql_persistent_store_queries.h" #include "sql/database.h" #include "sql/error_delegate_util.h" #include "sql/meta_table.h" @@ -52,13 +54,50 @@ struct InitResult { int64_t max_bytes = 0; }; +// A helper struct to associate an IOBuffer with a starting offset. +struct BufferWithStart { + scoped_refptr buffer; + int64_t start; +}; + +using disk_cache_sql_queries::GetQuery; +using disk_cache_sql_queries::Query; + using EntryInfo = SqlPersistentStore::EntryInfo; using Error = SqlPersistentStore::Error; using EntryInfoOrError = SqlPersistentStore::EntryInfoOrError; using OptionalEntryInfoOrError = SqlPersistentStore::OptionalEntryInfoOrError; - +using EntryInfoWithIdAndKey = SqlPersistentStore::EntryInfoWithIdAndKey; +using OptionalEntryInfoWithIdAndKey = + SqlPersistentStore::OptionalEntryInfoWithIdAndKey; +using IntOrError = SqlPersistentStore::IntOrError; using InitResultOrError = base::expected; +// A helper struct to bundle an operation's result with a flag indicating +// whether an eviction check is needed. This allows the background sequence, +// which has direct access to cache size information, to notify the main +// sequence that an eviction might be necessary without requiring an extra +// cross-sequence call to check the cache size. +template +struct ResultAndEvictionRequested { + ResultAndEvictionRequested(ResultType result, bool eviction_requested) + : result(std::move(result)), eviction_requested(eviction_requested) {} + ~ResultAndEvictionRequested() = default; + ResultAndEvictionRequested(ResultAndEvictionRequested&&) = default; + + // The actual result of the operation. + ResultType result; + + // True if the cache size has exceeded the high watermark, signaling that an + // eviction task should be considered. + bool eviction_requested; +}; + +using ErrorAndEvictionRequested = ResultAndEvictionRequested; +using EntryInfoOrErrorAndEvictionRequested = + ResultAndEvictionRequested; +using IntOrErrorAndEvictionRequested = ResultAndEvictionRequested; + std::optional ToUnguessableToken(int64_t token_high, int64_t token_low) { // There is no `sql::Statement::ColumnUint64()` method. So we cast to @@ -74,6 +113,16 @@ int64_t TokenLow(const base::UnguessableToken& token) { return static_cast(token.GetLowForSerialization()); } +bool IsBlobSizeValid(int64_t blob_start, + int64_t blob_end, + const base::span& blob) { + size_t blob_size; + if (!base::CheckSub(blob_end, blob_start).AssignIfValid(&blob_size)) { + return false; + } + return blob.size() == blob_size; +} + // Calculates the maximum size for a single cache entry's data. int64_t CalculateMaxFileSize(int64_t max_bytes) { return std::max(base::saturated_cast( @@ -82,6 +131,9 @@ int64_t CalculateMaxFileSize(int64_t max_bytes) { } // Helper functions to populate Perfetto trace events with details. +void PopulateTraceDetails(int result, perfetto::TracedDictionary& dict) { + dict.Add("result", result); +} void PopulateTraceDetails(Error error, perfetto::TracedDictionary& dict) { dict.Add("error", static_cast(error)); } @@ -106,6 +158,26 @@ void PopulateTraceDetails(const std::optional& entry_info, dict.Add("entry_info", "not found"); } } +void PopulateTraceDetails(const RangeResult& range_result, + perfetto::TracedDictionary& dict) { + dict.Add("range_start", range_result.start); + dict.Add("range_available_len", range_result.available_len); +} +void PopulateTraceDetails(const EntryInfoWithIdAndKey& result, + perfetto::TracedDictionary& dict) { + PopulateTraceDetails(result.info, dict); + dict.Add("res_id", result.res_id); + dict.Add("key", result.key.string()); +} +void PopulateTraceDetails( + const std::optional& entry_info, + perfetto::TracedDictionary& dict) { + if (entry_info) { + PopulateTraceDetails(*entry_info, dict); + } else { + dict.Add("entry_info", "not found"); + } +} void PopulateTraceDetails(Error error, const StoreStatus& store_status, perfetto::TracedDictionary& dict) { @@ -129,66 +201,30 @@ void PopulateTraceDetails(const base::expected& result, // `Error` code to a ".Result" histogram. void RecordTimeAndErrorResultHistogram(std::string_view method_name, base::TimeDelta time_delta, - Error error) { + Error error, + bool corruption_detected) { base::UmaHistogramMicrosecondsTimes( base::StrCat({kHistogramPrefix, method_name, - error == Error::kOk ? ".SuccessTime" : ".FailureTime"}), + error == Error::kOk ? ".SuccessTime" : ".FailureTime", + corruption_detected ? "WithCorruption" : ""}), time_delta); base::UmaHistogramEnumeration( - base::StrCat({kHistogramPrefix, method_name, ".Result"}), error); + base::StrCat({kHistogramPrefix, method_name, + corruption_detected ? ".ResultWithCorruption" : ".Result"}), + error); } -// Sets up the database schema. +// Sets up the database schema and indexes. [[nodiscard]] bool InitSchema(sql::Database& db) { - // The `resources` table stores the main metadata for each cache entry. - static constexpr char kSqlCreateTableResources[] = - // clang-format off - "CREATE TABLE IF NOT EXISTS resources(" - // Unique ID for the resource - "res_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," - // High part of an unguessable token - "token_high INTEGER NOT NULL," - // Low part of an unguessable token - "token_low INTEGER NOT NULL," - // Timestamp for LRU - "last_used INTEGER NOT NULL," - // End offset of the body - "body_end INTEGER NOT NULL," - // Total bytes consumed by the entry - "bytes_usage INTEGER NOT NULL," - // Flag for entries pending deletion - "doomed INTEGER NOT NULL," - // The cache key created by HttpCache::GenerateCacheKeyForRequest() - "cache_key TEXT NOT NULL," - // Serialized response headers - "head BLOB)"; - // clang-format on - - // The `blobs` table stores the data chunks of the cached body. - static constexpr char kSqlCreateTableBlobs[] = - // clang-format off - "CREATE TABLE IF NOT EXISTS blobs(" - // Unique ID for the blob - "blob_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," - // Foreign key to resources.token_high - "token_high INTEGER NOT NULL," - // Foreign key to resources.token_low - "token_low INTEGER NOT NULL," - // Start offset of this blob chunk - "start INTEGER NOT NULL," - // End offset of this blob chunk - "end INTEGER NOT NULL," - // The actual data chunk - "blob BLOB NOT NULL)"; - // clang-format on - - if (!db.Execute(kSqlCreateTableResources) || - !db.Execute(kSqlCreateTableBlobs)) { + if (!db.Execute(GetQuery(Query::kInitSchema_CreateTableResources)) || + !db.Execute(GetQuery(Query::kInitSchema_CreateTableBlobs)) || + !db.Execute(GetQuery(Query::kIndex_ResourcesToken)) || + !db.Execute(GetQuery(Query::kIndex_ResourcesCacheKeyDoomed)) || + !db.Execute(GetQuery(Query::kIndex_ResourcesDoomedLastUsed)) || + !db.Execute(GetQuery(Query::kIndex_ResourcesDoomedResId)) || + !db.Execute(GetQuery(Query::kIndex_BlobsTokenStart))) { return false; } - // TODO(crbug.com/422065015): Create indexes for performance-critical columns. - // TODO(crbug.com/422065015): Re-evaluate kSqlBackendStaticResourceSize after - // adding indexes, as they increase storage overhead. return true; } @@ -219,6 +255,10 @@ class Backend { ? max_bytes : PreferredCacheSize(base::SysInfo::AmountOfFreeDiskSpace(path), type)), + high_watermark_(max_bytes_ - + max_bytes_ / kSqlBackendEvictionMarginDivisor), + low_watermark_(max_bytes_ - + 2 * (max_bytes_ / kSqlBackendEvictionMarginDivisor)), db_(sql::DatabaseOptions() .set_exclusive_locking(true) #if BUILDFLAG(IS_WIN) @@ -247,47 +287,184 @@ class Backend { return result; } - EntryInfoOrError OpenOrCreateEntry(const CacheEntryKey& key); + EntryInfoOrErrorAndEvictionRequested OpenOrCreateEntry( + const CacheEntryKey& key); OptionalEntryInfoOrError OpenEntry(const CacheEntryKey& key); - EntryInfoOrError CreateEntry(const CacheEntryKey& key); - Error DoomEntry(const CacheEntryKey& key, - const base::UnguessableToken& token); - Error DeleteDoomedEntry(const CacheEntryKey& key, - const base::UnguessableToken& token); - Error DeleteLiveEntry(const CacheEntryKey& key); - Error DeleteAllEntries(); + EntryInfoOrErrorAndEvictionRequested CreateEntry(const CacheEntryKey& key); + + ErrorAndEvictionRequested DoomEntry(const CacheEntryKey& key, + const base::UnguessableToken& token); + ErrorAndEvictionRequested DeleteDoomedEntry( + const CacheEntryKey& key, + const base::UnguessableToken& token); + Error DeleteDoomedEntries( + base::flat_set excluded_tokens); + ErrorAndEvictionRequested DeleteLiveEntry(const CacheEntryKey& key); + + ErrorAndEvictionRequested DeleteAllEntries(); + ErrorAndEvictionRequested DeleteLiveEntriesBetween( + base::Time initial_time, + base::Time end_time, + base::flat_set excluded_keys); + Error UpdateEntryLastUsed(const CacheEntryKey& key, base::Time last_used); + ErrorAndEvictionRequested UpdateEntryHeaderAndLastUsed( + const CacheEntryKey& key, + const base::UnguessableToken& token, + base::Time last_used, + scoped_refptr buffer, + int64_t header_size_delta); + ErrorAndEvictionRequested WriteEntryData(const CacheEntryKey& key, + const base::UnguessableToken& token, + int64_t old_body_end, + int64_t offset, + scoped_refptr buffer, + int buf_len, + bool truncate); + IntOrError ReadEntryData(const base::UnguessableToken& token, + int64_t offset, + scoped_refptr buffer, + int buf_len, + int64_t body_end, + bool sparse_reading); + RangeResult GetEntryAvailableRange(const base::UnguessableToken& token, + int64_t offset, + int len); + int64_t CalculateSizeOfEntriesBetween(base::Time initial_time, + base::Time end_time); + OptionalEntryInfoWithIdAndKey OpenLatestEntryBeforeResId( + int64_t res_id_cursor); + ErrorAndEvictionRequested RunEviction( + base::flat_set excluded_keys); + + void EnableStrictCorruptionCheckForTesting() { + strict_corruption_check_enabled_ = true; + } private: void DatabaseErrorCallback(int error, sql::Statement* statement); - Error InitializeInternal(); - EntryInfoOrError OpenOrCreateEntryInternal(const CacheEntryKey& key); - OptionalEntryInfoOrError OpenEntryInternal(const CacheEntryKey& key); + Error InitializeInternal(bool& corruption_detected); + EntryInfoOrError OpenOrCreateEntryInternal(const CacheEntryKey& key, + bool& corruption_detected); + OptionalEntryInfoOrError OpenEntryInternal(const CacheEntryKey& key, + bool& corruption_detected); EntryInfoOrError CreateEntryInternal(const CacheEntryKey& key, - bool run_existance_check); + bool run_existance_check, + bool& corruption_detected); Error DoomEntryInternal(const CacheEntryKey& key, const base::UnguessableToken& token, bool& corruption_detected); Error DeleteDoomedEntryInternal(const CacheEntryKey& key, - const base::UnguessableToken& token); + const base::UnguessableToken& token, + bool& corruption_detected); + Error DeleteDoomedEntriesInternal( + const base::flat_set& excluded_tokens, + size_t& deleted_count, + bool& corruption_detected); Error DeleteLiveEntryInternal(const CacheEntryKey& key, bool& corruption_detected); - Error DeleteAllEntriesInternal(); + Error DeleteAllEntriesInternal(bool& corruption_detected); + Error DeleteLiveEntriesBetweenInternal( + base::Time initial_time, + base::Time end_time, + const base::flat_set& excluded_keys, + bool& corruption_detected); + Error UpdateEntryLastUsedInternal(const CacheEntryKey& key, + base::Time last_used); + Error UpdateEntryHeaderAndLastUsedInternal( + const CacheEntryKey& key, + const base::UnguessableToken& token, + base::Time last_used, + scoped_refptr buffer, + int64_t header_size_delta, + bool& corruption_detected); + Error WriteEntryDataInternal(const CacheEntryKey& key, + const base::UnguessableToken& token, + int64_t old_body_end, + int64_t offset, + scoped_refptr buffer, + int buf_len, + bool truncate, + bool& corruption_detected); + IntOrError ReadEntryDataInternal(const base::UnguessableToken& token, + int64_t offset, + scoped_refptr buffer, + int buf_len, + int64_t body_end, + bool sparse_reading, + bool& corruption_detected); + RangeResult GetEntryAvailableRangeInternal( + const base::UnguessableToken& token, + int64_t offset, + int len); + int64_t CalculateSizeOfEntriesBetweenInternal(base::Time initial_time, + base::Time end_time); + OptionalEntryInfoWithIdAndKey OpenLatestEntryBeforeResIdInternal( + int64_t res_id_cursor, + bool& corruption_detected); + Error RunEvictionInternal(const base::flat_set& excluded_keys, + bool& corruption_detected); + + // Trims blobs that overlap with the new write range [offset, end), and + // updates the total size delta. + Error TrimOverlappingBlobs( + const base::UnguessableToken& token, + int64_t offset, + int64_t end, + bool truncate, + base::CheckedNumeric& checked_total_size_delta, + bool& corruption_detected); + // Truncates data by deleting all blobs that start at or after the given + // offset. + Error TruncateBlobsAfter( + const base::UnguessableToken& token, + int64_t truncate_offset, + base::CheckedNumeric& checked_total_size_delta); + // Inserts a vector of new blobs into the database, and updates the total size + // delta. + Error InsertNewBlobs(const base::UnguessableToken& token, + const std::vector& new_blobs, + base::CheckedNumeric& checked_total_size_delta); + // Inserts a single new blob into the database, and updates the total size + // delta. + Error InsertNewBlob(const base::UnguessableToken& token, + int64_t start, + const scoped_refptr& buffer, + int buf_len, + base::CheckedNumeric& checked_total_size_delta); + // Deletes blobs by their IDs, and updates the total size delta. + Error DeleteBlobsById(const std::vector& blob_ids_to_be_removed, + base::CheckedNumeric& checked_total_size_delta, + bool& corruption_detected); + // Deletes a single blob by its ID, and updates the total size delta. + Error DeleteBlobById(int64_t blob_id, + base::CheckedNumeric& checked_total_size_delta, + bool& corruption_detected); + // Deletes all blobs associated with a given token. + Error DeleteBlobsByToken(const base::UnguessableToken& token); + // Deletes all blobs associated with a list of entry tokens. + Error DeleteBlobsByTokens(const std::vector& tokens); + // Deletes multiple resource entries from the `resources` table by their + // `res_id`s. + Error DeleteResourcesByResIds(const std::vector& res_ids); // Updates the in-memory `store_status_` by `entry_count_delta` and // `total_size_delta`. If the update results in an overflow or a negative // value, it recalculates the correct value from the database to recover from // potential metadata corruption. // It then updates the meta table values and attempts to commit the - // `transaction`. Returns true on success, false on failure. - bool UpdateStoreStatusAndCommitTransaction(sql::Transaction& transaction, - int64_t entry_count_delta, - int64_t total_size_delta); + // `transaction`. + // Returns Error::kOk on success, or an error code on failure. + Error UpdateStoreStatusAndCommitTransaction(sql::Transaction& transaction, + int64_t entry_count_delta, + int64_t total_size_delta, + bool& corruption_detected); // Recalculates the store's status (entry count and total size) directly from // the database. This is a recovery mechanism used when metadata might be // inconsistent, e.g., after a numerical overflow. - bool RecalculateStoreStatusAndCommitTransaction( + // Returns Error::kOk on success, or an error code on failure. + Error RecalculateStoreStatusAndCommitTransaction( sql::Transaction& transaction); int64_t CalculateResourceEntryCount(); @@ -300,33 +477,46 @@ class Backend { CHECK_EQ(*db_init_status_, Error::kOk); } + bool ShouldStartEviction() const { + return GetSizeOfAllEntries() > high_watermark_; + } + + void MaybeCrashIfCorrupted(bool corruption_detected) { + CHECK(!(corruption_detected && strict_corruption_check_enabled_)); + } + const base::FilePath path_; const int64_t max_bytes_; + const int64_t high_watermark_; + const int64_t low_watermark_; sql::Database db_; sql::MetaTable meta_table_; std::optional db_init_status_; StoreStatus store_status_; + bool strict_corruption_check_enabled_ = false; }; InitResultOrError Backend::Initialize() { TRACE_EVENT_BEGIN0("disk_cache", "SqlBackend.Initialize"); base::ElapsedTimer timer; CHECK(!db_init_status_.has_value()); - db_init_status_ = InitializeInternal(); + bool corruption_detected = false; + db_init_status_ = InitializeInternal(corruption_detected); RecordTimeAndErrorResultHistogram("Initialize", timer.Elapsed(), - *db_init_status_); + *db_init_status_, corruption_detected); TRACE_EVENT_END1("disk_cache", "SqlBackend.Initialize", "result", [&](perfetto::TracedValue trace_context) { auto dict = std::move(trace_context).WriteDictionary(); PopulateTraceDetails(*db_init_status_, store_status_, dict); }); + MaybeCrashIfCorrupted(corruption_detected); return *db_init_status_ == Error::kOk ? InitResultOrError(InitResult(max_bytes_)) : base::unexpected(*db_init_status_); } -Error Backend::InitializeInternal() { +Error Backend::InitializeInternal(bool& corruption_detected) { CHECK(!db_init_status_.has_value()); db_.set_error_callback(base::BindRepeating(&Backend::DatabaseErrorCallback, @@ -376,29 +566,22 @@ Error Backend::InitializeInternal() { /*default_value=*/0)) { return Error::kFailedToSetEntryCountMetadata; } - if (tmp_entry_count >= 0 && - base::IsValueInRangeForNumericType(tmp_entry_count)) { - store_status_.entry_count = base::checked_cast(tmp_entry_count); - } else { - // TODO(crbug.com/422065015): Recalculate the entry count. And store into - // the metadata table. - } - if (!GetOrInitializeMetaValue(meta_table_, kSqlBackendMetaTableKeyTotalSize, store_status_.total_size, /*default_value=*/0)) { - return Error::kFailedToSetEntryCountMetadata; - } - if (store_status_.total_size < 0) { - store_status_.total_size = 0; - // TODO(crbug.com/422065015): Recalculate the total size. And store into the - // metadata table. + return Error::kFailedToSetTotalSizeMetadata; } - if (!transaction.Commit()) { - return Error::kFailedToCommitTransaction; + if (tmp_entry_count < 0 || + !base::IsValueInRangeForNumericType(tmp_entry_count) || + store_status_.total_size < 0) { + corruption_detected = true; + return RecalculateStoreStatusAndCommitTransaction(transaction); } - return Error::kOk; + + store_status_.entry_count = static_cast(tmp_entry_count); + + return transaction.Commit() ? Error::kOk : Error::kFailedToCommitTransaction; } void Backend::DatabaseErrorCallback(int error, sql::Statement* statement) { @@ -414,7 +597,8 @@ void Backend::DatabaseErrorCallback(int error, sql::Statement* statement) { } } -EntryInfoOrError Backend::OpenOrCreateEntry(const CacheEntryKey& key) { +EntryInfoOrErrorAndEvictionRequested Backend::OpenOrCreateEntry( + const CacheEntryKey& key) { TRACE_EVENT_BEGIN1("disk_cache", "SqlBackend.OpenOrCreateEntry", "data", [&](perfetto::TracedValue trace_context) { auto dict = std::move(trace_context).WriteDictionary(); @@ -422,20 +606,25 @@ EntryInfoOrError Backend::OpenOrCreateEntry(const CacheEntryKey& key) { PopulateTraceDetails(store_status_, dict); }); base::ElapsedTimer timer; - auto result = OpenOrCreateEntryInternal(key); + bool corruption_detected = false; + auto result = OpenOrCreateEntryInternal(key, corruption_detected); RecordTimeAndErrorResultHistogram("OpenOrCreateEntry", timer.Elapsed(), - result.error_or(Error::kOk)); + result.error_or(Error::kOk), + corruption_detected); TRACE_EVENT_END1("disk_cache", "SqlBackend.OpenOrCreateEntry", "result", [&](perfetto::TracedValue trace_context) { auto dict = std::move(trace_context).WriteDictionary(); PopulateTraceDetails(result, store_status_, dict); }); - return result; + MaybeCrashIfCorrupted(corruption_detected); + return EntryInfoOrErrorAndEvictionRequested(std::move(result), + ShouldStartEviction()); } -EntryInfoOrError Backend::OpenOrCreateEntryInternal(const CacheEntryKey& key) { +EntryInfoOrError Backend::OpenOrCreateEntryInternal(const CacheEntryKey& key, + bool& corruption_detected) { // Try to open first. - auto open_result = OpenEntryInternal(key); + auto open_result = OpenEntryInternal(key, corruption_detected); if (open_result.has_value() && open_result->has_value()) { return std::move(*open_result.value()); } @@ -444,7 +633,8 @@ EntryInfoOrError Backend::OpenOrCreateEntryInternal(const CacheEntryKey& key) { return base::unexpected(open_result.error()); } // If the entry was not found, try to create a new one. - return CreateEntryInternal(key, /*run_existance_check=*/false); + return CreateEntryInternal(key, /*run_existance_check=*/false, + corruption_detected); } OptionalEntryInfoOrError Backend::OpenEntry(const CacheEntryKey& key) { @@ -455,40 +645,27 @@ OptionalEntryInfoOrError Backend::OpenEntry(const CacheEntryKey& key) { PopulateTraceDetails(store_status_, dict); }); base::ElapsedTimer timer; - auto result = OpenEntryInternal(key); + bool corruption_detected = false; + auto result = OpenEntryInternal(key, corruption_detected); RecordTimeAndErrorResultHistogram("OpenEntry", timer.Elapsed(), - result.error_or(Error::kOk)); + result.error_or(Error::kOk), + corruption_detected); TRACE_EVENT_END1("disk_cache", "SqlBackend.OpenEntry", "result", [&](perfetto::TracedValue trace_context) { auto dict = std::move(trace_context).WriteDictionary(); PopulateTraceDetails(result, store_status_, dict); }); + MaybeCrashIfCorrupted(corruption_detected); return result; } -OptionalEntryInfoOrError Backend::OpenEntryInternal(const CacheEntryKey& key) { +OptionalEntryInfoOrError Backend::OpenEntryInternal(const CacheEntryKey& key, + bool& corruption_detected) { CheckDatabaseInitStatus(); - constexpr char kSqlSelectResources[] = - // clang-format off - "SELECT " - "token_high," // 0 - "token_low," // 1 - "last_used," // 2 - "body_end," // 3 - "head " // 4 - "FROM resources " - "WHERE " - "cache_key=? AND " // 0 - "doomed=? " // 1 - "ORDER BY res_id DESC"; - // clang-format on - // Intentionally DCHECK() for performance - DCHECK(db_.IsSQLValid(kSqlSelectResources)); - sql::Statement statement( - db_.GetCachedStatement(SQL_FROM_HERE, kSqlSelectResources)); + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, GetQuery(Query::kOpenEntry_SelectLiveResources))); statement.BindString(0, key.string()); - statement.BindBool(1, false); if (!statement.Step()) { // `Step()` returned false, which means either the query completed with no // results, or an error occurred. @@ -507,6 +684,7 @@ OptionalEntryInfoOrError Backend::OpenEntryInternal(const CacheEntryKey& key) { // This indicates data corruption in the database. // TODO(crbug.com/422065015): If this error is observed in UMA, implement // recovery logic. + corruption_detected = true; return base::unexpected(Error::kInvalidData); } entry_info.token = *maybe_token; @@ -521,7 +699,8 @@ OptionalEntryInfoOrError Backend::OpenEntryInternal(const CacheEntryKey& key) { return entry_info; } -EntryInfoOrError Backend::CreateEntry(const CacheEntryKey& key) { +EntryInfoOrErrorAndEvictionRequested Backend::CreateEntry( + const CacheEntryKey& key) { TRACE_EVENT_BEGIN1("disk_cache", "SqlBackend.CreateEntry", "data", [&](perfetto::TracedValue trace_context) { auto dict = std::move(trace_context).WriteDictionary(); @@ -529,26 +708,32 @@ EntryInfoOrError Backend::CreateEntry(const CacheEntryKey& key) { PopulateTraceDetails(store_status_, dict); }); base::ElapsedTimer timer; - auto result = CreateEntryInternal(key, /*run_existance_check=*/true); + bool corruption_detected = false; + auto result = CreateEntryInternal(key, /*run_existance_check=*/true, + corruption_detected); RecordTimeAndErrorResultHistogram("CreateEntry", timer.Elapsed(), - result.error_or(Error::kOk)); + result.error_or(Error::kOk), + corruption_detected); TRACE_EVENT_END1("disk_cache", "SqlBackend.CreateEntry", "result", [&](perfetto::TracedValue trace_context) { auto dict = std::move(trace_context).WriteDictionary(); PopulateTraceDetails(result, store_status_, dict); }); - return result; + MaybeCrashIfCorrupted(corruption_detected); + return EntryInfoOrErrorAndEvictionRequested(std::move(result), + ShouldStartEviction()); } EntryInfoOrError Backend::CreateEntryInternal(const CacheEntryKey& key, - bool run_existance_check) { + bool run_existance_check, + bool& corruption_detected) { CheckDatabaseInitStatus(); sql::Transaction transaction(&db_); if (!transaction.Begin()) { return base::unexpected(Error::kFailedToStartTransaction); } if (run_existance_check) { - auto open_result = OpenEntryInternal(key); + auto open_result = OpenEntryInternal(key, corruption_detected); if (open_result.has_value() && open_result->has_value()) { return base::unexpected(Error::kAlreadyExists); } @@ -569,30 +754,16 @@ EntryInfoOrError Backend::CreateEntryInternal(const CacheEntryKey& key, // `GetSizeOfAllEntries()`. const int64_t bytes_usage = key.string().size(); { - constexpr char kSqlInsertIntoResources[] = - // clang-format off - "INSERT INTO resources(" - "token_high," // 0 - "token_low," // 1 - "last_used," // 2 - "body_end," // 3 - "bytes_usage," // 4 - "doomed," // 5 - "cache_key) " // 6 - "VALUES(?,?,?,?,?,?,?)"; - // clang-format on - - // Intentionally DCHECK() for performance - DCHECK(db_.IsSQLValid(kSqlInsertIntoResources)); - sql::Statement statement( - db_.GetCachedStatement(SQL_FROM_HERE, kSqlInsertIntoResources)); + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, + GetQuery( + disk_cache_sql_queries::Query::kCreateEntry_InsertIntoResources))); statement.BindInt64(0, TokenHigh(entry_info.token)); statement.BindInt64(1, TokenLow(entry_info.token)); statement.BindTime(2, entry_info.last_used); statement.BindInt64(3, entry_info.body_end); statement.BindInt64(4, bytes_usage); - statement.BindBool(5, false); // doomed - statement.BindString(6, key.string()); + statement.BindString(5, key.string()); if (!statement.Run()) { return base::unexpected(Error::kFailedToExecute); } @@ -601,18 +772,20 @@ EntryInfoOrError Backend::CreateEntryInternal(const CacheEntryKey& key, // Update the store's status and commit the transaction. // The entry count is increased by 1, and the total size by `bytes_usage`. // This call will also handle updating the on-disk meta table. - if (!UpdateStoreStatusAndCommitTransaction( + if (const auto error = UpdateStoreStatusAndCommitTransaction( transaction, /*entry_count_delta=*/1, - /*total_size_delta=*/bytes_usage)) { - return base::unexpected(Error::kFailedToCommitTransaction); + /*total_size_delta=*/bytes_usage, corruption_detected); + error != Error::kOk) { + return base::unexpected(error); } return entry_info; } -Error Backend::DoomEntry(const CacheEntryKey& key, - const base::UnguessableToken& token) { +ErrorAndEvictionRequested Backend::DoomEntry( + const CacheEntryKey& key, + const base::UnguessableToken& token) { TRACE_EVENT_BEGIN1("disk_cache", "SqlBackend.DoomEntry", "data", [&](perfetto::TracedValue trace_context) { auto dict = std::move(trace_context).WriteDictionary(); @@ -623,16 +796,16 @@ Error Backend::DoomEntry(const CacheEntryKey& key, base::ElapsedTimer timer; bool corruption_detected = false; auto result = DoomEntryInternal(key, token, corruption_detected); - RecordTimeAndErrorResultHistogram( - "DoomEntry", timer.Elapsed(), - corruption_detected ? Error::kInvalidData : result); + RecordTimeAndErrorResultHistogram("DoomEntry", timer.Elapsed(), result, + corruption_detected); TRACE_EVENT_END1("disk_cache", "SqlBackend.DoomEntry", "result", [&](perfetto::TracedValue trace_context) { auto dict = std::move(trace_context).WriteDictionary(); PopulateTraceDetails(result, store_status_, dict); dict.Add("corruption_detected", corruption_detected); }); - return result; + MaybeCrashIfCorrupted(corruption_detected); + return ErrorAndEvictionRequested(result, ShouldStartEviction()); } Error Backend::DoomEntryInternal(const CacheEntryKey& key, @@ -649,31 +822,11 @@ Error Backend::DoomEntryInternal(const CacheEntryKey& key, // detect potential metadata corruption from overflows. base::CheckedNumeric total_size_delta = 0; { - constexpr char kSqlMarkDoomedResources[] = - // clang-format off - "UPDATE resources " - "SET " - "doomed=? " // 0 - "WHERE " - "cache_key=? AND " // 1 - "token_high=? AND " // 2 - "token_low=? AND " // 3 - "doomed=? " // 4 - "RETURNING " - "bytes_usage"; // 0 - // clang-format on - - // Intentionally DCHECK() for performance - DCHECK(db_.IsSQLValid(kSqlMarkDoomedResources)); - sql::Statement statement( - db_.GetCachedStatement(SQL_FROM_HERE, kSqlMarkDoomedResources)); - // Set the new value: doomed = true. - statement.BindBool(0, true); - statement.BindString(1, key.string()); - statement.BindInt64(2, TokenHigh(token)); - statement.BindInt64(3, TokenLow(token)); - // Set the current value to match: doomed = false. - statement.BindBool(4, false); + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, GetQuery(Query::kDoomEntry_MarkDoomedResources))); + statement.BindString(0, key.string()); + statement.BindInt64(1, TokenHigh(token)); + statement.BindInt64(2, TokenLow(token)); // Iterate through the rows returned by the RETURNING clause. while (statement.Step()) { // Since we're dooming an entry, its size is subtracted from the total. @@ -684,9 +837,11 @@ Error Backend::DoomEntryInternal(const CacheEntryKey& key, } if (doomed_count > 1) { - // TODO(crbug.com/422065015): Add histograms to track how often this - // unexpected case is reached. A cache_key and token combination should - // uniquely identify a single non-doomed entry. + // The cache_key and token combination should uniquely identify a single + // non-doomed entry. + // TODO(crbug.com/422065015): If this error is observed in UMA, implement + // recovery logic. + corruption_detected = true; } // If no rows were updated, it means the entry was not found (or the token @@ -702,23 +857,18 @@ Error Backend::DoomEntryInternal(const CacheEntryKey& key, // consistent state. if (!total_size_delta.IsValid()) { corruption_detected = true; - return RecalculateStoreStatusAndCommitTransaction(transaction) - ? Error::kOk - : Error::kFailedToCommitTransaction; + return RecalculateStoreStatusAndCommitTransaction(transaction); } - if (!UpdateStoreStatusAndCommitTransaction( - transaction, - /*entry_count_delta=*/-doomed_count, - /*total_size_delta=*/total_size_delta.ValueOrDie())) { - return Error::kFailedToCommitTransaction; - } - - return Error::kOk; + return UpdateStoreStatusAndCommitTransaction( + transaction, + /*entry_count_delta=*/-doomed_count, + /*total_size_delta=*/total_size_delta.ValueOrDie(), corruption_detected); } -Error Backend::DeleteDoomedEntry(const CacheEntryKey& key, - const base::UnguessableToken& token) { +ErrorAndEvictionRequested Backend::DeleteDoomedEntry( + const CacheEntryKey& key, + const base::UnguessableToken& token) { TRACE_EVENT_BEGIN1("disk_cache", "SqlBackend.DeleteDoomedEntry", "data", [&](perfetto::TracedValue trace_context) { auto dict = std::move(trace_context).WriteDictionary(); @@ -727,19 +877,22 @@ Error Backend::DeleteDoomedEntry(const CacheEntryKey& key, PopulateTraceDetails(store_status_, dict); }); base::ElapsedTimer timer; - auto result = DeleteDoomedEntryInternal(key, token); + bool corruption_detected = false; + auto result = DeleteDoomedEntryInternal(key, token, corruption_detected); RecordTimeAndErrorResultHistogram("DeleteDoomedEntry", timer.Elapsed(), - result); + result, corruption_detected); TRACE_EVENT_END1("disk_cache", "SqlBackend.DeleteDoomedEntry", "result", [&](perfetto::TracedValue trace_context) { auto dict = std::move(trace_context).WriteDictionary(); PopulateTraceDetails(result, store_status_, dict); }); - return result; + MaybeCrashIfCorrupted(corruption_detected); + return ErrorAndEvictionRequested(result, ShouldStartEviction()); } Error Backend::DeleteDoomedEntryInternal(const CacheEntryKey& key, - const base::UnguessableToken& token) { + const base::UnguessableToken& token, + bool& corruption_detected) { CheckDatabaseInitStatus(); sql::Transaction transaction(&db_); if (!transaction.Begin()) { @@ -748,25 +901,12 @@ Error Backend::DeleteDoomedEntryInternal(const CacheEntryKey& key, int64_t deleted_count = 0; { - constexpr char kSqlDeleteFromResources[] = - // clang-format off - "DELETE FROM resources " - "WHERE " - "cache_key=? AND " // 0 - "token_high=? AND " // 1 - "token_low=? AND " // 2 - "doomed=?"; // 3 - // clang-format on - - // Intentionally DCHECK() for performance - DCHECK(db_.IsSQLValid(kSqlDeleteFromResources)); - sql::Statement statement( - db_.GetCachedStatement(SQL_FROM_HERE, kSqlDeleteFromResources)); + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, + GetQuery(Query::kDeleteDoomedEntry_DeleteFromResources))); statement.BindString(0, key.string()); statement.BindInt64(1, TokenHigh(token)); statement.BindInt64(2, TokenLow(token)); - // Target rows where doomed = true. - statement.BindBool(3, true); if (!statement.Run()) { return Error::kFailedToExecute; } @@ -774,9 +914,11 @@ Error Backend::DeleteDoomedEntryInternal(const CacheEntryKey& key, } if (deleted_count > 1) { - // TODO(crbug.com/422065015): Add histograms to track how often this - // unexpected case is reached. A cache_key and token combination should - // uniquely identify a single doomed entry. + // The cache_key and token combination should uniquely identify a single + // non-doomed entry. + // TODO(crbug.com/422065015): If this error is observed in UMA, implement + // recovery logic. + corruption_detected = true; } // If we didn't find any doomed entry matching the key and token, report it. @@ -785,12 +927,93 @@ Error Backend::DeleteDoomedEntryInternal(const CacheEntryKey& key, : Error::kFailedToCommitTransaction; } - // TODO(crbug.com/422065015): delete body data from the `blobs` table. + // Delete the associated blobs from the `blobs` table. + if (Error error = DeleteBlobsByToken(token); error != Error::kOk) { + return error; + } - return transaction.Commit() ? Error::kOk : Error::kFailedToExecute; + return transaction.Commit() ? Error::kOk : Error::kFailedToCommitTransaction; } -Error Backend::DeleteLiveEntry(const CacheEntryKey& key) { +Error Backend::DeleteDoomedEntries( + base::flat_set excluded_tokens) { + TRACE_EVENT_BEGIN0("disk_cache", "SqlBackend.DeleteDoomedEntries"); + base::ElapsedTimer timer; + bool corruption_detected = false; + size_t deleted_count = 0; + auto result = DeleteDoomedEntriesInternal(excluded_tokens, deleted_count, + corruption_detected); + RecordTimeAndErrorResultHistogram("DeleteDoomedEntries", timer.Elapsed(), + result, corruption_detected); + base::UmaHistogramCounts100("Net.SqlDiskCache.DeleteDoomedEntriesCount", + deleted_count); + TRACE_EVENT_END1("disk_cache", "SqlBackend.DeleteDoomedEntries", "result", + [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + PopulateTraceDetails(result, store_status_, dict); + dict.Add("deleted_count", deleted_count); + }); + MaybeCrashIfCorrupted(corruption_detected); + return result; +} + +Error Backend::DeleteDoomedEntriesInternal( + const base::flat_set& excluded_tokens, + size_t& deleted_count, + bool& corruption_detected) { + CheckDatabaseInitStatus(); + sql::Transaction transaction(&db_); + if (!transaction.Begin()) { + return Error::kFailedToStartTransaction; + } + + std::vector res_ids_to_delete; + std::vector tokens_for_blob_deletion; + + // 1. Select all doomed entries. + { + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, + GetQuery(Query::kDeleteDoomedEntries_SelectDoomedResources))); + // 2. Collect entries to be deleted, skipping excluded ones. + while (statement.Step()) { + auto maybe_token = ToUnguessableToken(statement.ColumnInt64(1), + statement.ColumnInt64(2)); + if (!maybe_token) { + corruption_detected = true; + continue; + } + if (excluded_tokens.contains(*maybe_token)) { + continue; + } + res_ids_to_delete.push_back(statement.ColumnInt64(0)); + tokens_for_blob_deletion.push_back(*maybe_token); + } + } + + deleted_count = res_ids_to_delete.size(); + if (deleted_count == 0) { + // Nothing to delete, abort the transaction and return kOk; + return Error::kOk; + } + + // 3. Delete from `resources` table by `res_id`. + if (auto error = DeleteResourcesByResIds(res_ids_to_delete); + error != Error::kOk) { + return error; + } + + // 4. Delete corresponding blobs by token. + if (auto error = DeleteBlobsByTokens(tokens_for_blob_deletion); + error != Error::kOk) { + return error; + } + + // 5. Commit the transaction. + return transaction.Commit() ? Error::kOk : Error::kFailedToCommitTransaction; +} + +ErrorAndEvictionRequested Backend::DeleteLiveEntry(const CacheEntryKey& key) { TRACE_EVENT_BEGIN1("disk_cache", "SqlBackend.DeleteLiveEntry", "data", [&](perfetto::TracedValue trace_context) { auto dict = std::move(trace_context).WriteDictionary(); @@ -800,16 +1023,16 @@ Error Backend::DeleteLiveEntry(const CacheEntryKey& key) { base::ElapsedTimer timer; bool corruption_detected = false; auto result = DeleteLiveEntryInternal(key, corruption_detected); - RecordTimeAndErrorResultHistogram( - "DeleteLiveEntry", timer.Elapsed(), - corruption_detected ? Error::kInvalidData : result); + RecordTimeAndErrorResultHistogram("DeleteLiveEntry", timer.Elapsed(), result, + corruption_detected); TRACE_EVENT_END1("disk_cache", "SqlBackend.DeleteLiveEntry", "result", [&](perfetto::TracedValue trace_context) { auto dict = std::move(trace_context).WriteDictionary(); PopulateTraceDetails(result, store_status_, dict); dict.Add("corruption_detected", corruption_detected); }); - return result; + MaybeCrashIfCorrupted(corruption_detected); + return ErrorAndEvictionRequested(result, ShouldStartEviction()); } Error Backend::DeleteLiveEntryInternal(const CacheEntryKey& key, @@ -827,24 +1050,9 @@ Error Backend::DeleteLiveEntryInternal(const CacheEntryKey& key, base::CheckedNumeric total_size_delta = 0; int64_t deleted_count = 0; { - constexpr char kSqlDeleteFromResources[] = - // clang-format off - "DELETE FROM resources " - "WHERE " - "cache_key=? AND " // 0 - "doomed=? " // 1 - "RETURNING " - "token_high," // 0 - "token_low," // 1 - "bytes_usage"; // 2 - // clang-format on - // Intentionally DCHECK() for performance - DCHECK(db_.IsSQLValid(kSqlDeleteFromResources)); - sql::Statement statement( - db_.GetCachedStatement(SQL_FROM_HERE, kSqlDeleteFromResources)); + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, GetQuery(Query::kDeleteLiveEntry_DeleteFromResources))); statement.BindString(0, key.string()); - // Target rows where doomed = false. - statement.BindBool(1, false); while (statement.Step()) { ++deleted_count; auto maybe_token = ToUnguessableToken(statement.ColumnInt64(0), @@ -866,48 +1074,48 @@ Error Backend::DeleteLiveEntryInternal(const CacheEntryKey& key, : Error::kFailedToCommitTransaction; } - // TODO(crbug.com/422065015): delete body data from the `blobs` table. + // Delete the blobs associated with the deleted entries. + if (Error delete_result = DeleteBlobsByTokens(tokens_to_be_deleted); + delete_result != Error::kOk) { + return delete_result; + } // If we detected corruption, or if the size update calculation overflowed, // our metadata is suspect. We recover by recalculating everything from // scratch. if (corruption_detected || !total_size_delta.IsValid()) { corruption_detected = true; - return RecalculateStoreStatusAndCommitTransaction(transaction) - ? Error::kOk - : Error::kFailedToCommitTransaction; + return RecalculateStoreStatusAndCommitTransaction(transaction); } - if (!UpdateStoreStatusAndCommitTransaction( - transaction, - /*entry_count_delta=*/ - -static_cast(tokens_to_be_deleted.size()), - /*total_size_delta=*/total_size_delta.ValueOrDie())) { - return Error::kFailedToCommitTransaction; - } - - return Error::kOk; + return UpdateStoreStatusAndCommitTransaction( + transaction, + /*entry_count_delta=*/ + -static_cast(tokens_to_be_deleted.size()), + /*total_size_delta=*/total_size_delta.ValueOrDie(), corruption_detected); } -Error Backend::DeleteAllEntries() { +ErrorAndEvictionRequested Backend::DeleteAllEntries() { TRACE_EVENT_BEGIN1("disk_cache", "SqlBackend.DeleteAllEntries", "data", [&](perfetto::TracedValue trace_context) { auto dict = std::move(trace_context).WriteDictionary(); PopulateTraceDetails(store_status_, dict); }); base::ElapsedTimer timer; - Error result = DeleteAllEntriesInternal(); - RecordTimeAndErrorResultHistogram("DeleteAllEntries", timer.Elapsed(), - result); + bool corruption_detected = false; + Error result = DeleteAllEntriesInternal(corruption_detected); + RecordTimeAndErrorResultHistogram("DeleteAllEntries", timer.Elapsed(), result, + corruption_detected); TRACE_EVENT_END1("disk_cache", "SqlBackend.DeleteAllEntries", "result", [&](perfetto::TracedValue trace_context) { auto dict = std::move(trace_context).WriteDictionary(); PopulateTraceDetails(result, store_status_, dict); }); - return result; + MaybeCrashIfCorrupted(corruption_detected); + return ErrorAndEvictionRequested(result, ShouldStartEviction()); } -Error Backend::DeleteAllEntriesInternal() { +Error Backend::DeleteAllEntriesInternal(bool& corruption_detected) { CheckDatabaseInitStatus(); sql::Transaction transaction(&db_); if (!transaction.Begin()) { @@ -916,11 +1124,8 @@ Error Backend::DeleteAllEntriesInternal() { // Clear the main resources table. { - constexpr char kSqlDeleteFromResources[] = "DELETE FROM resources"; - // Intentionally DCHECK() for performance - DCHECK(db_.IsSQLValid(kSqlDeleteFromResources)); - sql::Statement statement( - db_.GetCachedStatement(SQL_FROM_HERE, kSqlDeleteFromResources)); + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, GetQuery(Query::kDeleteAllEntries_DeleteFromResources))); if (!statement.Run()) { return Error::kFailedToExecute; } @@ -928,11 +1133,8 @@ Error Backend::DeleteAllEntriesInternal() { // Also clear the blobs table. { - constexpr char kSqlDeleteFromBlobs[] = "DELETE FROM blobs"; - // Intentionally DCHECK() for performance - DCHECK(db_.IsSQLValid(kSqlDeleteFromBlobs)); - sql::Statement statement( - db_.GetCachedStatement(SQL_FROM_HERE, kSqlDeleteFromBlobs)); + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, GetQuery(Query::kDeleteAllEntries_DeleteFromBlobs))); if (!statement.Run()) { return Error::kFailedToExecute; } @@ -941,19 +1143,1021 @@ Error Backend::DeleteAllEntriesInternal() { // Update the store's status and commit the transaction. // The entry count and the total size will be zero. // This call will also handle updating the on-disk meta table. - if (!UpdateStoreStatusAndCommitTransaction( - transaction, - /*entry_count_delta=*/-store_status_.entry_count, - /*total_size_delta=*/-store_status_.total_size)) { + return UpdateStoreStatusAndCommitTransaction( + transaction, + /*entry_count_delta=*/-store_status_.entry_count, + /*total_size_delta=*/-store_status_.total_size, corruption_detected); +} + +ErrorAndEvictionRequested Backend::DeleteLiveEntriesBetween( + base::Time initial_time, + base::Time end_time, + base::flat_set excluded_keys) { + TRACE_EVENT_BEGIN1("disk_cache", "SqlBackend.DeleteLiveEntriesBetween", + "data", [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + dict.Add("initial_time", initial_time); + dict.Add("end_time", end_time); + dict.Add("excluded_keys_size", excluded_keys.size()); + PopulateTraceDetails(store_status_, dict); + }); + base::ElapsedTimer timer; + // Flag to indicate if we encounter signs of database corruption. In + // DeleteLiveEntriesBetween, database corruption is ignored. + bool corruption_detected = false; + Error result = DeleteLiveEntriesBetweenInternal( + initial_time, end_time, excluded_keys, corruption_detected); + RecordTimeAndErrorResultHistogram("DeleteLiveEntriesBetween", timer.Elapsed(), + result, corruption_detected); + TRACE_EVENT_END1("disk_cache", "SqlBackend.DeleteLiveEntriesBetween", + "result", [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + PopulateTraceDetails(result, store_status_, dict); + }); + MaybeCrashIfCorrupted(corruption_detected); + return ErrorAndEvictionRequested(result, ShouldStartEviction()); +} + +Error Backend::DeleteLiveEntriesBetweenInternal( + base::Time initial_time, + base::Time end_time, + const base::flat_set& excluded_keys, + bool& corruption_detected) { + CheckDatabaseInitStatus(); + sql::Transaction transaction(&db_); + if (!transaction.Begin()) { + return Error::kFailedToStartTransaction; + } + + std::vector res_ids_to_be_deleted; + std::vector tokens_to_be_deleted; + int64_t entry_count_delta = 0; + base::CheckedNumeric total_size_delta = 0; + { + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, + GetQuery(Query::kDeleteLiveEntriesBetween_SelectLiveResources))); + statement.BindTime(0, initial_time); + statement.BindTime(1, end_time); + while (statement.Step()) { + if (excluded_keys.contains(CacheEntryKey(statement.ColumnString(4)))) { + continue; + } + --entry_count_delta; + res_ids_to_be_deleted.push_back(statement.ColumnInt64(0)); + auto maybe_token = ToUnguessableToken(statement.ColumnInt64(1), + statement.ColumnInt64(2)); + if (maybe_token) { + tokens_to_be_deleted.push_back(*maybe_token); + total_size_delta -= statement.ColumnInt64(3); + } else { + corruption_detected = true; + } + } + } + + // Delete the blobs associated with the entries to be deleted. + if (auto error = DeleteBlobsByTokens(tokens_to_be_deleted); + error != Error::kOk) { + return error; + } + + // Delete the selected entries from the `resources` table. + if (auto error = DeleteResourcesByResIds(res_ids_to_be_deleted); + error != Error::kOk) { + return error; + } + + // If we detected corruption, or if the size update calculation overflowed, + // our metadata is suspect. We recover by recalculating everything from + // scratch. + if (corruption_detected || !total_size_delta.IsValid()) { + corruption_detected = true; + return RecalculateStoreStatusAndCommitTransaction(transaction); + } + + // Update the in-memory and on-disk store status (entry count and total size) + // and commit the transaction. + return UpdateStoreStatusAndCommitTransaction(transaction, entry_count_delta, + total_size_delta.ValueOrDie(), + corruption_detected); +} + +Error Backend::UpdateEntryLastUsed(const CacheEntryKey& key, + base::Time last_used) { + TRACE_EVENT_BEGIN1("disk_cache", "SqlBackend.UpdateEntryLastUsed", "data", + [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + dict.Add("key", key.string()); + dict.Add("last_used", last_used); + }); + base::ElapsedTimer timer; + auto result = UpdateEntryLastUsedInternal(key, last_used); + RecordTimeAndErrorResultHistogram("UpdateEntryLastUsed", timer.Elapsed(), + result, /*corruption_detected=*/false); + TRACE_EVENT_END1("disk_cache", "SqlBackend.UpdateEntryLastUsed", "result", + [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + PopulateTraceDetails(result, dict); + }); + return result; +} + +Error Backend::UpdateEntryLastUsedInternal(const CacheEntryKey& key, + base::Time last_used) { + CheckDatabaseInitStatus(); + sql::Transaction transaction(&db_); + if (!transaction.Begin()) { + return Error::kFailedToStartTransaction; + } + int64_t change_count = 0; + { + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, + GetQuery(Query::kUpdateEntryLastUsed_UpdateResourceLastUsed))); + statement.BindTime(0, last_used); + statement.BindString(1, key.string()); + if (!statement.Run()) { + return Error::kFailedToExecute; + } + change_count = db_.GetLastChangeCount(); + } + if (!transaction.Commit()) { return Error::kFailedToCommitTransaction; } + return change_count == 0 ? Error::kNotFound : Error::kOk; +} + +ErrorAndEvictionRequested Backend::UpdateEntryHeaderAndLastUsed( + const CacheEntryKey& key, + const base::UnguessableToken& token, + base::Time last_used, + scoped_refptr buffer, + int64_t header_size_delta) { + TRACE_EVENT_BEGIN1("disk_cache", "SqlBackend.UpdateEntryHeaderAndLastUsed", + "data", [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + dict.Add("key", key.string()); + dict.Add("token", token.ToString()); + dict.Add("last_used", last_used); + dict.Add("header_size_delta", header_size_delta); + PopulateTraceDetails(store_status_, dict); + }); + base::ElapsedTimer timer; + bool corruption_detected = false; + auto result = UpdateEntryHeaderAndLastUsedInternal( + key, token, last_used, std::move(buffer), header_size_delta, + corruption_detected); + RecordTimeAndErrorResultHistogram("UpdateEntryHeaderAndLastUsed", + timer.Elapsed(), result, + corruption_detected); + TRACE_EVENT_END1("disk_cache", "SqlBackend.UpdateEntryHeaderAndLastUsed", + "result", [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + PopulateTraceDetails(result, store_status_, dict); + }); + MaybeCrashIfCorrupted(corruption_detected); + return ErrorAndEvictionRequested(result, ShouldStartEviction()); +} + +Error Backend::UpdateEntryHeaderAndLastUsedInternal( + const CacheEntryKey& key, + const base::UnguessableToken& token, + base::Time last_used, + scoped_refptr buffer, + int64_t header_size_delta, + bool& corruption_detected) { + CHECK(buffer); + CheckDatabaseInitStatus(); + + sql::Transaction transaction(&db_); + if (!transaction.Begin()) { + return Error::kFailedToStartTransaction; + } + { + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, + GetQuery(Query::kUpdateEntryHeaderAndLastUsed_UpdateResource))); + statement.BindTime(0, last_used); + statement.BindInt64(1, header_size_delta); + statement.BindBlob(2, buffer->span()); + statement.BindString(3, key.string()); + statement.BindInt64(4, TokenHigh(token)); + statement.BindInt64(5, TokenLow(token)); + if (statement.Step()) { + const int64_t bytes_usage = statement.ColumnInt64(0); + if (bytes_usage < static_cast(buffer->size()) + + static_cast(key.string().size())) { + // This indicates data corruption in the database. + // TODO(crbug.com/422065015): If this error is observed in UMA, + // implement recovery logic. + corruption_detected = true; + return Error::kInvalidData; + } + } else { + return Error::kNotFound; + } + } + return UpdateStoreStatusAndCommitTransaction( + transaction, + /*entry_count_delta=*/0, + /*total_size_delta=*/header_size_delta, corruption_detected); +} + +ErrorAndEvictionRequested Backend::WriteEntryData( + const CacheEntryKey& key, + const base::UnguessableToken& token, + int64_t old_body_end, + int64_t offset, + scoped_refptr buffer, + int buf_len, + bool truncate) { + TRACE_EVENT_BEGIN1("disk_cache", "SqlBackend.WriteEntryData", "data", + [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + dict.Add("key", key.string()); + dict.Add("token", token.ToString()); + dict.Add("old_body_end", old_body_end); + dict.Add("offset", offset); + dict.Add("buf_len", buf_len); + dict.Add("truncate", truncate); + PopulateTraceDetails(store_status_, dict); + }); + base::ElapsedTimer timer; + bool corruption_detected = false; + auto result = WriteEntryDataInternal(key, token, old_body_end, offset, + std::move(buffer), buf_len, truncate, + corruption_detected); + RecordTimeAndErrorResultHistogram("WriteEntryData", timer.Elapsed(), result, + corruption_detected); + TRACE_EVENT_END1("disk_cache", "SqlBackend.WriteEntryData", "result", + [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + PopulateTraceDetails(result, store_status_, dict); + }); + MaybeCrashIfCorrupted(corruption_detected); + return ErrorAndEvictionRequested(result, ShouldStartEviction()); +} + +Error Backend::WriteEntryDataInternal(const CacheEntryKey& key, + const base::UnguessableToken& token, + int64_t old_body_end, + int64_t offset, + scoped_refptr buffer, + int buf_len, + bool truncate, + bool& corruption_detected) { + CheckDatabaseInitStatus(); + sql::Transaction transaction(&db_); + if (!transaction.Begin()) { + return Error::kFailedToStartTransaction; + } + + int64_t write_end; + if (old_body_end < 0 || offset < 0 || buf_len < 0 || + (!buffer && buf_len > 0) || (buffer && buf_len > buffer->size()) || + !base::CheckAdd(offset, buf_len).AssignIfValid(&write_end)) { + return Error::kInvalidArgument; + } + + const int64_t new_body_end = + truncate ? write_end : std::max(write_end, old_body_end); + // An overflow is not expected here, as both `new_body_end` and `old_body_end` + // are non-negative int64_t value. + const int64_t body_end_delta = new_body_end - old_body_end; + + base::CheckedNumeric checked_total_size_delta = 0; + + // If the write starts before the current end of the body, it might overlap + // with existing data. + if (offset < old_body_end) { + if (Error result = + TrimOverlappingBlobs(token, offset, write_end, truncate, + checked_total_size_delta, corruption_detected); + result != Error::kOk) { + return result; + } + } + + // If the new body size is smaller, existing blobs beyond the new end must be + // truncated. + if (body_end_delta < 0) { + CHECK(truncate); + if (Error result = + TruncateBlobsAfter(token, new_body_end, checked_total_size_delta); + result != Error::kOk) { + return result; + } + } + + // Insert the new data blob if there is data to write. + if (buf_len) { + if (Error result = InsertNewBlob(token, offset, buffer, buf_len, + checked_total_size_delta); + result != Error::kOk) { + return result; + } + } + + if (!checked_total_size_delta.IsValid()) { + // If the total size delta calculation resulted in an overflow, it suggests + // that the size values in the database were corrupt. + corruption_detected = true; + return Error::kInvalidData; + } + int64_t total_size_delta = checked_total_size_delta.ValueOrDie(); + + // Update the entry's metadata in the `resources` table if the body size + // changed or if the total size of blobs changed. + if (body_end_delta || total_size_delta) { + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, GetQuery(Query::kWriteEntryData_UpdateResource))); + statement.BindInt64(0, body_end_delta); + statement.BindInt64(1, total_size_delta); + statement.BindString(2, key.string()); + statement.BindInt64(3, TokenHigh(token)); + statement.BindInt64(4, TokenLow(token)); + if (statement.Step()) { + // Consistency check: The `RETURNING` clause gives us the `body_end` value + // after the update. If this doesn't match our calculated `new_body_end`, + // it means the `body_end` in the database was not the `old_body_end` we + // expected. This indicates data corruption, so we return an error. + const int64_t returned_new_body_end = statement.ColumnInt64(0); + if (returned_new_body_end != new_body_end) { + corruption_detected = true; + return Error::kBodyEndMismatch; + } + // If the entry is doomed, its size is no longer tracked in the cache's + // total size, so we don't update the store status. + const bool doomed = statement.ColumnBool(1); + if (doomed) { + total_size_delta = 0; + } + } else { + // If no rows were updated, it means the entry was not found (or the + // token was wrong). + return Error::kNotFound; + } + } + + // Commit the transaction, which also updates the in-memory and on-disk store + // status. + return UpdateStoreStatusAndCommitTransaction( + transaction, + /*entry_count_delta=*/0, + /*total_size_delta=*/total_size_delta, corruption_detected); +} + +// This function handles writes that overlap with existing data blobs. It finds +// any blobs that intersect with the new write range `[offset, end)`, removes +// them, and recreates any non-overlapping portions as new, smaller blobs. This +// effectively "cuts out" the space for the new data. +Error Backend::TrimOverlappingBlobs( + const base::UnguessableToken& token, + int64_t offset, + int64_t end, + bool truncate, + base::CheckedNumeric& checked_total_size_delta, + bool& corruption_detected) { + TRACE_EVENT1("disk_cache", "SqlBackend.TrimOverlappingBlobs", "data", + [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + dict.Add("token", token.ToString()); + dict.Add("offset", offset); + dict.Add("end", end); + }); + + // First, delete all blobs that are fully contained within the new write + // range. + // If the write has zero length, no blobs can be fully contained within it, so + // this can be skipped. + if (offset != end) { + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, GetQuery(Query::kTrimOverlappingBlobs_DeleteContained))); + statement.BindInt64(0, TokenHigh(token)); + statement.BindInt64(1, TokenLow(token)); + statement.BindInt64(2, offset); + statement.BindInt64(3, end); + while (statement.Step()) { + const int64_t blob_start = statement.ColumnInt64(0); + const int64_t blob_end = statement.ColumnInt64(1); + checked_total_size_delta -= blob_end - blob_start; + } + } + + // Now, handle blobs that partially overlap with the write range. There should + // be at most two such blobs. + // The SQL condition `blob_start < end AND blob_end > offset` checks for + // overlap. Example of [offset, end) vs [blob_start, blob_end): + // [0, 2) vs [2, 6): Not hit. + // [0, 3) vs [2, 6): Hit. + // [5, 9) vs [2, 6): Hit. + // [6, 9) vs [2, 6): Not hit. + std::vector blob_ids_to_be_removed; + std::vector new_blobs; + // A zero-length, non-truncating write is a no-op. For all other writes, we + // must handle partially overlapping blobs. + if (!(offset == end && !truncate)) { + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, + GetQuery(Query::kTrimOverlappingBlobs_SelectOverlapping))); + statement.BindInt64(0, TokenHigh(token)); + statement.BindInt64(1, TokenLow(token)); + statement.BindInt64(2, end); + statement.BindInt64(3, offset); + while (statement.Step()) { + const int64_t blob_id = statement.ColumnInt64(0); + const int64_t blob_start = statement.ColumnInt64(1); + const int64_t blob_end = statement.ColumnInt64(2); + base::span blob = statement.ColumnBlob(3); + // Consistency check: The blob's size should match its start and end + // offsets. + if (!IsBlobSizeValid(blob_start, blob_end, blob)) { + corruption_detected = true; + return Error::kInvalidData; + } + // Mark the overlapping blob for removal. + blob_ids_to_be_removed.push_back(blob_id); + // If the existing blob starts before the new write, create a new blob + // for the leading part that doesn't overlap. + if (blob_start < offset) { + new_blobs.push_back(BufferWithStart{ + base::MakeRefCounted( + blob.first(base::checked_cast(offset - blob_start))), + blob_start}); + } + // If the existing blob ends after the new write and we are not + // truncating, create a new blob for the trailing part that doesn't + // overlap. + if (!truncate && end < blob_end) { + new_blobs.push_back(BufferWithStart{ + base::MakeRefCounted( + blob.last(base::checked_cast(blob_end - end))), + end}); + } + } + } + + // Delete the old blobs. + if (Error error = + DeleteBlobsById(blob_ids_to_be_removed, checked_total_size_delta, + corruption_detected); + error != Error::kOk) { + return error; + } + + // Insert the new, smaller blobs that were preserved from the non-overlapping + // parts. + if (Error error = InsertNewBlobs(token, new_blobs, checked_total_size_delta); + error != Error::kOk) { + return error; + } return Error::kOk; } -bool Backend::UpdateStoreStatusAndCommitTransaction( +Error Backend::TruncateBlobsAfter( + const base::UnguessableToken& token, + int64_t truncate_offset, + base::CheckedNumeric& checked_total_size_delta) { + TRACE_EVENT1("disk_cache", "SqlBackend.TruncateBlobsAfter", "data", + [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + dict.Add("token", token.ToString()); + dict.Add("truncate_offset", truncate_offset); + }); + // Delete all blobs that start at or after the truncation offset. + { + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, GetQuery(Query::kTruncateBlobsAfter_DeleteAfter))); + statement.BindInt64(0, TokenHigh(token)); + statement.BindInt64(1, TokenLow(token)); + statement.BindInt64(2, truncate_offset); + while (statement.Step()) { + const int64_t blob_start = statement.ColumnInt64(0); + const int64_t blob_end = statement.ColumnInt64(1); + checked_total_size_delta -= blob_end - blob_start; + } + if (!statement.Succeeded()) { + return Error::kFailedToExecute; + } + } + return Error::kOk; +} + +// Inserts a vector of new blobs into the database. +Error Backend::InsertNewBlobs( + const base::UnguessableToken& token, + const std::vector& new_blobs, + base::CheckedNumeric& checked_total_size_delta) { + // Iterate through the provided blobs and insert each one. + for (const auto& new_blob : new_blobs) { + if (Error error = + InsertNewBlob(token, new_blob.start, new_blob.buffer, + new_blob.buffer->size(), checked_total_size_delta); + error != Error::kOk) { + return error; + } + } + return Error::kOk; +} + +// Inserts a single new blob into the database. +Error Backend::InsertNewBlob( + const base::UnguessableToken& token, + int64_t start, + const scoped_refptr& buffer, + int buf_len, + base::CheckedNumeric& checked_total_size_delta) { + TRACE_EVENT1("disk_cache", "SqlBackend.InsertNewBlob", "data", + [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + dict.Add("token", token.ToString()); + dict.Add("start", start); + dict.Add("buf_len", buf_len); + }); + const int64_t end = + (base::CheckedNumeric(start) + buf_len).ValueOrDie(); + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, GetQuery(Query::kInsertNewBlob_InsertIntoBlobs))); + statement.BindInt64(0, TokenHigh(token)); + statement.BindInt64(1, TokenLow(token)); + statement.BindInt64(2, start); + statement.BindInt64(3, end); + statement.BindBlob(4, + buffer->span().first(base::checked_cast(buf_len))); + if (!statement.Run()) { + return Error::kFailedToExecute; + } + checked_total_size_delta += buf_len; + return Error::kOk; +} + +// A helper function to delete multiple blobs by their IDs. +Error Backend::DeleteBlobsById( + const std::vector& blob_ids_to_be_removed, + base::CheckedNumeric& checked_total_size_delta, + bool& corruption_detected) { + // Iterate through the provided blob IDs and delete each one. + for (auto blob_id : blob_ids_to_be_removed) { + if (Error error = DeleteBlobById(blob_id, checked_total_size_delta, + corruption_detected); + error != Error::kOk) { + return error; + } + } + return Error::kOk; +} + +// Deletes a single blob from the `blobs` table given its ID. It uses the +// `RETURNING` clause to get the size of the deleted blob to update the total. +Error Backend::DeleteBlobById( + int64_t blob_id, + base::CheckedNumeric& checked_total_size_delta, + bool& corruption_detected) { + TRACE_EVENT1("disk_cache", "SqlBackend.DeleteBlobById", "data", + [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + dict.Add("blob_id", blob_id); + }); + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, GetQuery(Query::kDeleteBlobById_DeleteFromBlobs))); + statement.BindInt64(0, blob_id); + if (!statement.Step()) { + // `Step()` returned false, which means either the query completed with no + // hit, or an error occurred. + if (db_.GetErrorCode() == static_cast(sql::SqliteResultCode::kDone)) { + return Error::kNotFound; + } + // An unexpected database error occurred. + return Error::kFailedToExecute; + } + const int64_t start = statement.ColumnInt64(0); + const int64_t end = statement.ColumnInt64(1); + if (end <= start) { + corruption_detected = true; + return Error::kInvalidData; + } + // Subtract the size of the deleted blob from the total size delta. + checked_total_size_delta -= end - start; + return Error::kOk; +} + +// Deletes all blobs associated with a specific entry token. +Error Backend::DeleteBlobsByToken(const base::UnguessableToken& token) { + TRACE_EVENT1("disk_cache", "SqlBackend.DeleteBlobsByToken", "token", + [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + dict.Add("token", token.ToString()); + }); + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, GetQuery(Query::kDeleteBlobsByToken_DeleteFromBlobs))); + statement.BindInt64(0, TokenHigh(token)); + statement.BindInt64(1, TokenLow(token)); + if (!statement.Run()) { + return Error::kFailedToExecute; + } + return Error::kOk; +} + +Error Backend::DeleteBlobsByTokens( + const std::vector& tokens) { + TRACE_EVENT0("disk_cache", "SqlBackend.DeleteBlobsByTokens"); + for (const auto& token : tokens) { + if (auto error = DeleteBlobsByToken(token); error != Error::kOk) { + return error; + } + } + return Error::kOk; +} + +Error Backend::DeleteResourcesByResIds(const std::vector& res_ids) { + TRACE_EVENT0("disk_cache", "SqlBackend.DeleteResourcesByResIds"); + for (int64_t res_id : res_ids) { + sql::Statement delete_resource_stmt(db_.GetCachedStatement( + SQL_FROM_HERE, + GetQuery(Query::kDeleteResourcesByResIds_DeleteFromResources))); + delete_resource_stmt.BindInt64(0, res_id); + if (!delete_resource_stmt.Run()) { + return Error::kFailedToExecute; + } + } + return Error::kOk; +} + +IntOrError Backend::ReadEntryData(const base::UnguessableToken& token, + int64_t offset, + scoped_refptr buffer, + int buf_len, + int64_t body_end, + bool sparse_reading) { + TRACE_EVENT_BEGIN1("disk_cache", "SqlBackend.ReadEntryData", "data", + [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + dict.Add("token", token.ToString()); + dict.Add("offset", offset); + dict.Add("buf_len", buf_len); + dict.Add("body_end", body_end); + dict.Add("sparse_reading", sparse_reading); + PopulateTraceDetails(store_status_, dict); + }); + base::ElapsedTimer timer; + bool corruption_detected = false; + auto result = + ReadEntryDataInternal(token, offset, std::move(buffer), buf_len, body_end, + sparse_reading, corruption_detected); + RecordTimeAndErrorResultHistogram("ReadEntryData", timer.Elapsed(), + result.error_or(Error::kOk), + corruption_detected); + TRACE_EVENT_END1("disk_cache", "SqlBackend.ReadEntryData", "result", + [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + PopulateTraceDetails(result, store_status_, dict); + }); + MaybeCrashIfCorrupted(corruption_detected); + return result; +} + +IntOrError Backend::ReadEntryDataInternal(const base::UnguessableToken& token, + int64_t offset, + scoped_refptr buffer, + int buf_len, + int64_t body_end, + bool sparse_reading, + bool& corruption_detected) { + CheckDatabaseInitStatus(); + + if (offset < 0 || buf_len < 0 || !buffer || buf_len > buffer->size()) { + return base::unexpected(Error::kInvalidArgument); + } + + // Truncate `buffer_len` to make sure that `offset + buffer_len` does not + // overflow. + int64_t buffer_len = std::min(static_cast(buf_len), + std::numeric_limits::max() - offset); + const int64_t read_end = + (base::CheckedNumeric(offset) + buffer_len).ValueOrDie(); + // Select all blobs that overlap with the read range [offset, read_end), + // ordered by their start offset. + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, GetQuery(Query::kReadEntryData_SelectOverlapping))); + statement.BindInt64(0, TokenHigh(token)); + statement.BindInt64(1, TokenLow(token)); + statement.BindInt64(2, read_end); + statement.BindInt64(3, offset); + + size_t written_bytes = 0; + while (statement.Step()) { + const int64_t blob_start = statement.ColumnInt64(0); + const int64_t blob_end = statement.ColumnInt64(1); + base::span blob = statement.ColumnBlob(2); + if (!IsBlobSizeValid(blob_start, blob_end, blob)) { + corruption_detected = true; + return base::unexpected(Error::kInvalidData); + } + // Determine the part of the blob that falls within the read request. + const int64_t copy_start = std::max(offset, blob_start); + const int64_t copy_end = std::min(read_end, blob_end); + const size_t copy_size = base::checked_cast(copy_end - copy_start); + const size_t pos_in_buffer = + base::checked_cast(copy_start - offset); + // If there's a gap between the last written byte and the start of the + // current blob, handle it based on `sparse_reading`. + if (written_bytes < pos_in_buffer) { + if (sparse_reading) { + // In sparse reading mode, we stop at the first gap. + // This might be before any data got read. + return written_bytes; + } + // In normal mode, fill the gap with zeros. + std::ranges::fill( + buffer->span().subspan(written_bytes, pos_in_buffer - written_bytes), + 0); + } + // Copy the relevant part of the blob into the output buffer. + buffer->span() + .subspan(pos_in_buffer, copy_size) + .copy_from_nonoverlapping(blob.subspan( + base::checked_cast(copy_start - blob_start), copy_size)); + written_bytes = copy_end - offset; + } + + if (sparse_reading) { + return written_bytes; + } + + // After processing all blobs, check if we need to zero-fill the rest of the + // buffer up to the logical end of the entry's body. + const size_t last_pos_in_buffer = + std::min(body_end - offset, static_cast(buffer_len)); + if (written_bytes < last_pos_in_buffer) { + std::ranges::fill(buffer->span().subspan( + written_bytes, last_pos_in_buffer - written_bytes), + 0); + written_bytes = last_pos_in_buffer; + } + + return written_bytes; +} + +RangeResult Backend::GetEntryAvailableRange(const base::UnguessableToken& token, + int64_t offset, + int len) { + TRACE_EVENT_BEGIN1("disk_cache", "SqlBackend.GetEntryAvailableRange", "data", + [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + dict.Add("token", token.ToString()); + dict.Add("offset", offset); + dict.Add("len", len); + }); + base::ElapsedTimer timer; + auto result = GetEntryAvailableRangeInternal(token, offset, len); + RecordTimeAndErrorResultHistogram("GetEntryAvailableRange", timer.Elapsed(), + Error::kOk, /*corruption_detected=*/false); + TRACE_EVENT_END1("disk_cache", "SqlBackend.GetEntryAvailableRange", "result", + [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + PopulateTraceDetails(result, dict); + }); + return result; +} + +RangeResult Backend::GetEntryAvailableRangeInternal( + const base::UnguessableToken& token, + int64_t offset, + int len) { + CheckDatabaseInitStatus(); + // Truncate `len` to make sure that `offset + len` does not overflow. + len = std::min(static_cast(len), + std::numeric_limits::max() - offset); + const int64_t end = offset + len; + std::optional available_start; + int64_t available_end = 0; + + // To finds the available contiguous range of data for a given entry. queries + // the `blobs` table for data chunks that overlap with the requested range + // [offset, end). + { + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, + GetQuery(Query::kGetEntryAvailableRange_SelectOverlapping))); + statement.BindInt64(0, TokenHigh(token)); + statement.BindInt64(1, TokenLow(token)); + statement.BindInt64(2, end); + statement.BindInt64(3, offset); + while (statement.Step()) { + int64_t blob_start = statement.ColumnInt64(0); + int64_t blob_end = statement.ColumnInt64(1); + if (!available_start) { + // This is the first blob we've found in the requested range. Start + // tracking the contiguous available range from here. + available_start = std::max(blob_start, offset); + available_end = std::min(blob_end, end); + } else { + // We have already found a blob, check if this one is contiguous. + if (available_end == blob_start) { + // The next blob is contiguous with the previous one. Extend the + // available range. + available_end = std::min(blob_end, end); + } else { + // There's a gap in the data. Return the contiguous range found so + // far. + return RangeResult(*available_start, + available_end - *available_start); + } + } + } + } + // If we found any data, return the total contiguous range. + if (available_start) { + return RangeResult(*available_start, available_end - *available_start); + } + return RangeResult(offset, 0); +} + +int64_t Backend::CalculateSizeOfEntriesBetween(base::Time initial_time, + base::Time end_time) { + if (initial_time == base::Time::Min() && end_time == base::Time::Max()) { + return GetSizeOfAllEntries(); + } + TRACE_EVENT_BEGIN1("disk_cache", "SqlBackend.CalculateSizeOfEntriesBetween", + "data", [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + dict.Add("initial_time", initial_time); + dict.Add("end_time", end_time); + }); + base::ElapsedTimer timer; + auto result = CalculateSizeOfEntriesBetweenInternal(initial_time, end_time); + RecordTimeAndErrorResultHistogram("CalculateSizeOfEntriesBetween", + timer.Elapsed(), Error::kOk, + /*corruption_detected=*/false); + TRACE_EVENT_END1("disk_cache", "SqlBackend.CalculateSizeOfEntriesBetween", + "result", result); + return result; +} + +int64_t Backend::CalculateSizeOfEntriesBetweenInternal(base::Time initial_time, + base::Time end_time) { + // To calculate the total size of all entries whose `last_used` time falls + // within the range [`initial_time`, `end_time`), sums up the `bytes_usage` + // from the `resources` table and adds a static overhead for each entry. + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, + GetQuery(Query::kCalculateSizeOfEntriesBetween_SelectLiveResources))); + statement.BindTime(0, initial_time); + statement.BindTime(1, end_time); + base::ClampedNumeric total_size = 0; + while (statement.Step()) { + // `bytes_usage` includes the size of the key, header, and body data. + total_size += statement.ColumnInt64(0); + // Add the static overhead for the entry's row in the database. + total_size += kSqlBackendStaticResourceSize; + } + return total_size; +} + +OptionalEntryInfoWithIdAndKey Backend::OpenLatestEntryBeforeResId( + int64_t res_id_cursor) { + TRACE_EVENT_BEGIN1("disk_cache", "SqlBackend.OpenLatestEntryBeforeResId", + "data", [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + dict.Add("res_id_cursor", res_id_cursor); + }); + base::ElapsedTimer timer; + bool corruption_detected = false; + auto result = + OpenLatestEntryBeforeResIdInternal(res_id_cursor, corruption_detected); + RecordTimeAndErrorResultHistogram("OpenLatestEntryBeforeResId", + timer.Elapsed(), Error::kOk, + corruption_detected); + TRACE_EVENT_END1("disk_cache", "SqlBackend.OpenLatestEntryBeforeResId", + "result", [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + PopulateTraceDetails(result, dict); + }); + MaybeCrashIfCorrupted(corruption_detected); + return result; +} + +OptionalEntryInfoWithIdAndKey Backend::OpenLatestEntryBeforeResIdInternal( + int64_t res_id_cursor, + bool& corruption_detected) { + CheckDatabaseInitStatus(); + + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, + GetQuery(Query::kOpenLatestEntryBeforeResId_SelectLiveResources))); + statement.BindInt64(0, res_id_cursor); + while (statement.Step()) { + auto maybe_token = + ToUnguessableToken(statement.ColumnInt64(1), statement.ColumnInt64(2)); + if (!maybe_token) { + // If OpenNextEntry encounters invalid data, it records it in a histogram + // and ignores the data. + corruption_detected = true; + continue; + } + + EntryInfoWithIdAndKey result; + result.res_id = statement.ColumnInt64(0); + result.key = CacheEntryKey(statement.ColumnString(5)); + auto& entry_info = result.info; + entry_info.token = *maybe_token; + entry_info.last_used = statement.ColumnTime(3); + entry_info.body_end = statement.ColumnInt64(4); + base::span blob_span = statement.ColumnBlob(6); + if (blob_span.size() > std::numeric_limits::max()) { + // If OpenNextEntry encounters invalid data, it records it in a histogram + // and ignores the data. + corruption_detected = true; + continue; + } + entry_info.head = base::MakeRefCounted(); + entry_info.head->SetCapacity(blob_span.size()); + entry_info.head->span().copy_from_nonoverlapping(blob_span); + entry_info.opened = true; + return result; + } + return std::nullopt; +} + +ErrorAndEvictionRequested Backend::RunEviction( + base::flat_set excluded_keys) { + TRACE_EVENT0("disk_cache", "SqlBackend.RunEviction"); + base::ElapsedTimer timer; + bool corruption_detected = false; + auto result = + RunEvictionInternal(std::move(excluded_keys), corruption_detected); + RecordTimeAndErrorResultHistogram("RunEviction", timer.Elapsed(), result, + corruption_detected); + MaybeCrashIfCorrupted(corruption_detected); + return ErrorAndEvictionRequested(result, ShouldStartEviction()); +} + +Error Backend::RunEvictionInternal( + const base::flat_set& excluded_keys, + bool& corruption_detected) { + int64_t size_to_be_removed = GetSizeOfAllEntries() - low_watermark_; + sql::Transaction transaction(&db_); + if (!transaction.Begin()) { + return Error::kFailedToExecute; + } + + std::vector tokens_to_be_deleted; + int64_t entry_count_delta = 0; + // Use checked numerics to safely update the total cache size. + base::CheckedNumeric checked_total_size_delta = 0; + base::CheckedNumeric checked_removed_total_size = 0; + { + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, GetQuery(Query::kRunEviction_SelectLiveResources))); + while (size_to_be_removed > checked_removed_total_size.ValueOrDie() && + statement.Step()) { + if (excluded_keys.contains(CacheEntryKey(statement.ColumnString(2)))) { + continue; + } + auto maybe_token = ToUnguessableToken(statement.ColumnInt64(0), + statement.ColumnInt64(1)); + if (!maybe_token) { + corruption_detected = true; + continue; + } + tokens_to_be_deleted.push_back(*maybe_token); + --entry_count_delta; + const int64_t bytes_usage = statement.ColumnInt64(3); + checked_total_size_delta -= bytes_usage; + checked_removed_total_size += bytes_usage; + checked_removed_total_size += kSqlBackendStaticResourceSize; + if (!checked_total_size_delta.IsValid() || + !checked_removed_total_size.IsValid()) { + corruption_detected = true; + return Error::kInvalidData; + } + } + } + + for (const auto& token_to_be_deleted : tokens_to_be_deleted) { + if (Error delete_result = DeleteBlobsByToken(token_to_be_deleted); + delete_result != Error::kOk) { + return delete_result; + } + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, GetQuery(Query::kRunEviction_DeleteFromResources))); + statement.BindInt64(0, TokenHigh(token_to_be_deleted)); + statement.BindInt64(1, TokenLow(token_to_be_deleted)); + if (!statement.Run()) { + return Error::kFailedToExecute; + } + } + return UpdateStoreStatusAndCommitTransaction( + transaction, entry_count_delta, checked_total_size_delta.ValueOrDie(), + corruption_detected); +} + +Error Backend::UpdateStoreStatusAndCommitTransaction( sql::Transaction& transaction, int64_t entry_count_delta, - int64_t total_size_delta) { + int64_t total_size_delta, + bool& corruption_detected) { const auto old_entry_count = store_status_.entry_count; const auto old_total_size = store_status_.total_size; if (entry_count_delta != 0) { @@ -963,6 +2167,7 @@ bool Backend::UpdateStoreStatusAndCommitTransaction( if (!base::CheckAdd(store_status_.entry_count, entry_count_delta) .AssignIfValid(&store_status_.entry_count) || store_status_.entry_count < 0) { + corruption_detected = true; store_status_.entry_count = CalculateResourceEntryCount(); } meta_table_.SetValue(kSqlBackendMetaTableKeyEntryCount, @@ -976,6 +2181,7 @@ bool Backend::UpdateStoreStatusAndCommitTransaction( if (!base::CheckAdd(store_status_.total_size, total_size_delta) .AssignIfValid(&store_status_.total_size) || store_status_.total_size < 0) { + corruption_detected = true; store_status_.total_size = CalculateTotalSize(); } meta_table_.SetValue(kSqlBackendMetaTableKeyTotalSize, @@ -993,12 +2199,12 @@ bool Backend::UpdateStoreStatusAndCommitTransaction( if (!transaction.Commit()) { store_status_.entry_count = old_entry_count; store_status_.total_size = old_total_size; - return false; + return Error::kFailedToCommitTransaction; } - return true; + return Error::kOk; } -bool Backend::RecalculateStoreStatusAndCommitTransaction( +Error Backend::RecalculateStoreStatusAndCommitTransaction( sql::Transaction& transaction) { store_status_.entry_count = CalculateResourceEntryCount(); store_status_.total_size = CalculateTotalSize(); @@ -1006,18 +2212,15 @@ bool Backend::RecalculateStoreStatusAndCommitTransaction( store_status_.entry_count); meta_table_.SetValue(kSqlBackendMetaTableKeyTotalSize, store_status_.total_size); - return transaction.Commit(); + return transaction.Commit() ? Error::kOk : Error::kFailedToCommitTransaction; } // Recalculates the number of non-doomed entries in the `resources` table. int64_t Backend::CalculateResourceEntryCount() { - constexpr char kSqlSelectCountFromResources[] = - "SELECT COUNT(*) FROM resources WHERE doomed=?"; - // Intentionally DCHECK() for performance - DCHECK(db_.IsSQLValid(kSqlSelectCountFromResources)); - sql::Statement statement( - db_.GetCachedStatement(SQL_FROM_HERE, kSqlSelectCountFromResources)); - statement.BindBool(0, false); + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, + GetQuery( + Query::kCalculateResourceEntryCount_SelectCountFromLiveResources))); int64_t result = 0; if (statement.Step()) { result = statement.ColumnInt64(0); @@ -1027,13 +2230,9 @@ int64_t Backend::CalculateResourceEntryCount() { // Recalculates the total size of all non-doomed entries. int64_t Backend::CalculateTotalSize() { - constexpr char kSqlSelectTotalSizeFromResources[] = - "SELECT SUM(bytes_usage) FROM resources WHERE doomed=?"; - // Intentionally DCHECK() for performance - DCHECK(db_.IsSQLValid(kSqlSelectTotalSizeFromResources)); - sql::Statement statement( - db_.GetCachedStatement(SQL_FROM_HERE, kSqlSelectTotalSizeFromResources)); - statement.BindBool(0, false); + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, + GetQuery(Query::kCalculateTotalSize_SelectTotalSizeFromLiveResources))); int64_t result = 0; if (statement.Step()) { result = statement.ColumnInt64(0); @@ -1076,7 +2275,7 @@ class SqlPersistentStoreImpl : public SqlPersistentStore { EntryInfoOrErrorCallback callback) override { backend_.AsyncCall(&Backend::OpenOrCreateEntry) .WithArgs(key) - .Then(WrapCallback(std::move(callback))); + .Then(WrapCallbackWithEvictionRequested(std::move(callback))); } void OpenEntry(const CacheEntryKey& key, OptionalEntryInfoOrErrorCallback callback) override { @@ -1088,32 +2287,132 @@ class SqlPersistentStoreImpl : public SqlPersistentStore { EntryInfoOrErrorCallback callback) override { backend_.AsyncCall(&Backend::CreateEntry) .WithArgs(key) - .Then(WrapCallback(std::move(callback))); + .Then(WrapCallbackWithEvictionRequested(std::move(callback))); } void DoomEntry(const CacheEntryKey& key, const base::UnguessableToken& token, ErrorCallback callback) override { backend_.AsyncCall(&Backend::DoomEntry) .WithArgs(key, token) - .Then(WrapCallback(std::move(callback))); + .Then(WrapCallbackWithEvictionRequested(std::move(callback))); } void DeleteDoomedEntry(const CacheEntryKey& key, const base::UnguessableToken& token, ErrorCallback callback) override { backend_.AsyncCall(&Backend::DeleteDoomedEntry) .WithArgs(key, token) + .Then(WrapCallbackWithEvictionRequested(std::move(callback))); + } + void DeleteDoomedEntries( + base::flat_set excluded_tokens, + ErrorCallback callback) override { + backend_.AsyncCall(&Backend::DeleteDoomedEntries) + .WithArgs(std::move(excluded_tokens)) .Then(WrapCallback(std::move(callback))); } void DeleteLiveEntry(const CacheEntryKey& key, ErrorCallback callback) override { backend_.AsyncCall(&Backend::DeleteLiveEntry) .WithArgs(key) - .Then(WrapCallback(std::move(callback))); + .Then(WrapCallbackWithEvictionRequested(std::move(callback))); } void DeleteAllEntries(ErrorCallback callback) override { backend_.AsyncCall(&Backend::DeleteAllEntries) + .Then(WrapCallbackWithEvictionRequested(std::move(callback))); + } + void DeleteLiveEntriesBetween(base::Time initial_time, + base::Time end_time, + base::flat_set excluded_keys, + ErrorCallback callback) override { + backend_.AsyncCall(&Backend::DeleteLiveEntriesBetween) + .WithArgs(initial_time, end_time, std::move(excluded_keys)) + .Then(WrapCallbackWithEvictionRequested(std::move(callback))); + } + void UpdateEntryLastUsed(const CacheEntryKey& key, + base::Time last_used, + ErrorCallback callback) override { + backend_.AsyncCall(&Backend::UpdateEntryLastUsed) + .WithArgs(key, last_used) .Then(WrapCallback(std::move(callback))); } + void UpdateEntryHeaderAndLastUsed(const CacheEntryKey& key, + const base::UnguessableToken& token, + base::Time last_used, + scoped_refptr buffer, + int64_t header_size_delta, + ErrorCallback callback) override { + backend_.AsyncCall(&Backend::UpdateEntryHeaderAndLastUsed) + .WithArgs(key, token, last_used, std::move(buffer), header_size_delta) + .Then(WrapCallbackWithEvictionRequested(std::move(callback))); + } + + void WriteEntryData(const CacheEntryKey& key, + const base::UnguessableToken& token, + int64_t old_body_end, + int64_t offset, + scoped_refptr buffer, + int buf_len, + bool truncate, + ErrorCallback callback) override { + backend_.AsyncCall(&Backend::WriteEntryData) + .WithArgs(key, token, old_body_end, offset, std::move(buffer), buf_len, + truncate) + .Then(WrapCallbackWithEvictionRequested(std::move(callback))); + } + void ReadEntryData(const base::UnguessableToken& token, + int64_t offset, + scoped_refptr buffer, + int buf_len, + int64_t body_end, + bool sparse_reading, + IntOrErrorCallback callback) override { + backend_.AsyncCall(&Backend::ReadEntryData) + .WithArgs(token, offset, std::move(buffer), buf_len, body_end, + sparse_reading) + .Then(WrapCallback(std::move(callback))); + } + void GetEntryAvailableRange(const base::UnguessableToken& token, + int64_t offset, + int len, + RangeResultCallback callback) override { + backend_.AsyncCall(&Backend::GetEntryAvailableRange) + .WithArgs(token, offset, len) + .Then(WrapCallback(std::move(callback))); + } + void CalculateSizeOfEntriesBetween(base::Time initial_time, + base::Time end_time, + Int64OrErrorCallback callback) override { + backend_.AsyncCall(&Backend::CalculateSizeOfEntriesBetween) + .WithArgs(initial_time, end_time) + .Then(WrapCallback(std::move(callback))); + } + void OpenLatestEntryBeforeResId( + int64_t res_id_cursor, + OptionalEntryInfoWithIdAndKeyCallback callback) override { + backend_.AsyncCall(&Backend::OpenLatestEntryBeforeResId) + .WithArgs(res_id_cursor) + .Then(WrapCallback(std::move(callback))); + } + bool ShouldStartEviction() override { + return !eviction_in_progress_ && eviction_requested_; + } + void StartEviction(base::flat_set excluded_keys, + ErrorCallback callback) override { + CHECK(!eviction_in_progress_); + eviction_in_progress_ = true; + backend_.AsyncCall(&Backend::RunEviction) + .WithArgs(std::move(excluded_keys)) + .Then(base::BindOnce( + [](base::WeakPtr weak_ptr, + ErrorCallback callback, ErrorAndEvictionRequested result) { + if (weak_ptr) { + weak_ptr->eviction_in_progress_ = false; + weak_ptr->eviction_requested_ = result.eviction_requested; + std::move(callback).Run(result.result); + } + }, + weak_factory_.GetWeakPtr(), std::move(callback))); + } int64_t MaxFileSize() const override { return max_file_size_; } int64_t MaxSize() const override { return max_size_; } @@ -1124,6 +2423,10 @@ class SqlPersistentStoreImpl : public SqlPersistentStore { backend_.AsyncCall(&Backend::GetSizeOfAllEntries).Then(std::move(callback)); } + void EnableStrictCorruptionCheckForTesting() override { + backend_.AsyncCall(&Backend::EnableStrictCorruptionCheckForTesting); + } + private: void SetMaxSize(int64_t max_bytes) { max_size_ = max_bytes; @@ -1146,10 +2449,30 @@ class SqlPersistentStoreImpl : public SqlPersistentStore { weak_factory_.GetWeakPtr(), std::move(callback)); } + // Like `WrapCallback`, but also updates the `eviction_requested_` flag. + template + base::OnceCallback)> + WrapCallbackWithEvictionRequested( + base::OnceCallback callback) { + return base::BindOnce( + [](base::WeakPtr weak_ptr, + base::OnceCallback callback, + ResultAndEvictionRequested result) { + if (weak_ptr) { + weak_ptr->eviction_requested_ = result.eviction_requested; + // We should not run the callback when `this` was deleted. + std::move(callback).Run(std::move(result.result)); + } + }, + weak_factory_.GetWeakPtr(), std::move(callback)); + } + base::SequenceBound backend_; int64_t max_size_ = 0; int64_t max_file_size_ = 0; + bool eviction_in_progress_ = false; + bool eviction_requested_ = false; base::WeakPtrFactory weak_factory_{this}; }; @@ -1173,4 +2496,12 @@ SqlPersistentStore::EntryInfo::EntryInfo(EntryInfo&&) = default; SqlPersistentStore::EntryInfo& SqlPersistentStore::EntryInfo::operator=( EntryInfo&&) = default; +SqlPersistentStore::EntryInfoWithIdAndKey::EntryInfoWithIdAndKey() = default; +SqlPersistentStore::EntryInfoWithIdAndKey::~EntryInfoWithIdAndKey() = default; +SqlPersistentStore::EntryInfoWithIdAndKey::EntryInfoWithIdAndKey( + EntryInfoWithIdAndKey&&) = default; +SqlPersistentStore::EntryInfoWithIdAndKey& +SqlPersistentStore::EntryInfoWithIdAndKey::operator=(EntryInfoWithIdAndKey&&) = + default; + } // namespace disk_cache diff --git a/naiveproxy/src/net/disk_cache/sql/sql_persistent_store.h b/naiveproxy/src/net/disk_cache/sql/sql_persistent_store.h index 6928c01bd7..5bba62d0a6 100644 --- a/naiveproxy/src/net/disk_cache/sql/sql_persistent_store.h +++ b/naiveproxy/src/net/disk_cache/sql/sql_persistent_store.h @@ -6,7 +6,9 @@ #define NET_DISK_CACHE_SQL_SQL_PERSISTENT_STORE_H_ #include +#include +#include "base/containers/flat_set.h" #include "base/functional/callback_forward.h" #include "base/memory/scoped_refptr.h" #include "base/time/time.h" @@ -15,6 +17,7 @@ #include "net/base/cache_type.h" #include "net/base/net_export.h" #include "net/disk_cache/buildflags.h" +#include "net/disk_cache/disk_cache.h" #include "net/disk_cache/sql/cache_entry_key.h" // This backend is experimental and only available when the build flag is set. @@ -27,6 +30,7 @@ class SequencedTaskRunner; namespace net { class GrowableIOBuffer; +class IOBuffer; } // namespace net namespace disk_cache { @@ -57,7 +61,9 @@ class NET_EXPORT_PRIVATE SqlPersistentStore { kInvalidData = 11, kAlreadyExists = 12, kNotFound = 13, - kMaxValue = kNotFound + kInvalidArgument = 14, + kBodyEndMismatch = 15, + kMaxValue = kBodyEndMismatch }; // LINT.ThenChange(//tools/metrics/histograms/metadata/net/enums.xml:SqlDiskCacheStoreError) @@ -80,6 +86,19 @@ class NET_EXPORT_PRIVATE SqlPersistentStore { bool opened = false; }; + // Holds information about a specific cache entry, including its `res_id` and + // `key`. This is used when iterating through entries. + struct NET_EXPORT_PRIVATE EntryInfoWithIdAndKey { + EntryInfoWithIdAndKey(); + ~EntryInfoWithIdAndKey(); + EntryInfoWithIdAndKey(EntryInfoWithIdAndKey&&); + EntryInfoWithIdAndKey& operator=(EntryInfoWithIdAndKey&&); + + EntryInfo info; + int64_t res_id; + CacheEntryKey key; + }; + using ErrorCallback = base::OnceCallback; using Int32Callback = base::OnceCallback; using Int64Callback = base::OnceCallback; @@ -89,6 +108,13 @@ class NET_EXPORT_PRIVATE SqlPersistentStore { base::expected, Error>; using OptionalEntryInfoOrErrorCallback = base::OnceCallback; + using OptionalEntryInfoWithIdAndKey = std::optional; + using OptionalEntryInfoWithIdAndKeyCallback = + base::OnceCallback; + using IntOrError = base::expected; + using IntOrErrorCallback = base::OnceCallback; + using Int64OrError = base::expected; + using Int64OrErrorCallback = base::OnceCallback; // Creates a new instance of the persistent store. The returned object must be // initialized by calling `Initialize()`. This function never returns a null @@ -142,6 +168,14 @@ class NET_EXPORT_PRIVATE SqlPersistentStore { const base::UnguessableToken& token, ErrorCallback callback) = 0; + // Physically deletes all entries that have been marked as doomed, except for + // those whose tokens are in `excluded_tokens`. This is typically used for + // background cleanup of doomed entries that are no longer in use. `callback` + // is invoked upon completion. + virtual void DeleteDoomedEntries( + base::flat_set excluded_tokens, + ErrorCallback callback) = 0; + // Deletes a "live" entry, i.e., an entry whose `doomed` flag is not set. // This is for use for entries which are not open; open entries should have // `DoomEntry()` called, and then `DeleteDoomedEntry()` once they're no longer @@ -152,6 +186,119 @@ class NET_EXPORT_PRIVATE SqlPersistentStore { // Deletes all entries from the cache. `callback` is invoked on completion. virtual void DeleteAllEntries(ErrorCallback callback) = 0; + // Deletes all "live" (not doomed) entries whose `last_used` time falls + // within the range [`initial_time`, `end_time`), excluding any entries whose + // keys are present in `excluded_keys`. `callback` is invoked on completion. + virtual void DeleteLiveEntriesBetween( + base::Time initial_time, + base::Time end_time, + base::flat_set excluded_keys, + ErrorCallback callback) = 0; + + // Updates the `last_used` timestamp for the entry with the specified `key`. + // `callback` is invoked with `kOk` on success, or `kNotFound` if the entry + // does not exist or is already doomed. + virtual void UpdateEntryLastUsed(const CacheEntryKey& key, + base::Time last_used, + ErrorCallback callback) = 0; + + // Updates the header data (stream 0) and the `last_used` timestamp for a + // specific cache entry. The `bytes_usage` for the entry is adjusted based + // on `header_size_delta`. `callback` is invoked with `kOk` on success, + // `kNotFound` if the entry (matching `key` and `token`) is not found or is + // doomed, or `kInvalidData` if internal data consistency checks fail. + // `buffer` must not be null. `header_size_delta` is the change in the size + // of the header data. + virtual void UpdateEntryHeaderAndLastUsed(const CacheEntryKey& key, + const base::UnguessableToken& token, + base::Time last_used, + scoped_refptr buffer, + int64_t header_size_delta, + ErrorCallback callback) = 0; + + // Writes data to an entry's body. This can be used to write new data, + // overwrite existing data, or append to the entry. + // `key` and `token` identify the target entry. + // `old_body_end` is the expected current size of the body. It is used to + // determine whether to trim or truncate existing data, and for consistency + // checks. + // `offset` is the position within the entry's body to start writing. + // `buffer` contains the data to be written. This can be null for truncation. + // `buf_len` is the size of `buffer`. + // If `truncate` is true, the entry's body will be truncated to the end of + // this write. Otherwise, the body size will grow if the write extends past + // the current end. + // `callback` is invoked upon completion with an error code. + virtual void WriteEntryData(const CacheEntryKey& key, + const base::UnguessableToken& token, + int64_t old_body_end, + int64_t offset, + scoped_refptr buffer, + int buf_len, + bool truncate, + ErrorCallback callback) = 0; + + // Reads data from an entry's body. + // `token` identifies the entry to read from. + // `offset` is the position within the entry's body to start reading. + // `buffer` is the destination for the read data. + // `buf_len` is the size of `buffer`. + // `body_end` is the logical size of the entry's body. + // If `sparse_reading` is true, the read will stop at the first gap in the + // stored data. If false, gaps will be filled with zeros. + // `callback` is invoked with the number of bytes read on success, or an error + // code on failure. + virtual void ReadEntryData(const base::UnguessableToken& token, + int64_t offset, + scoped_refptr buffer, + int buf_len, + int64_t body_end, + bool sparse_reading, + IntOrErrorCallback callback) = 0; + + // Finds the available contiguous range of data for a given entry. + // `token` identifies the entry. + // `offset` is the starting position of the range to check. + // `len` is the length of the range to check. + // `callback` is invoked with the result. The `RangeResult` will contain the + // starting offset and length of the first contiguous block of data found + // within the requested range `[offset, offset + len)`. If no data is found + // in the requested range, the `available_len` in the result will be 0. + virtual void GetEntryAvailableRange(const base::UnguessableToken& token, + int64_t offset, + int len, + RangeResultCallback callback) = 0; + + // Calculates the total size of all entries whose `last_used` time falls + // within the range [`initial_time`, `end_time`). The size includes the key, + // header, body data, and a static overhead per entry. `callback` is invoked + // with the total size on success, or an error code on failure. + virtual void CalculateSizeOfEntriesBetween(base::Time initial_time, + base::Time end_time, + Int64OrErrorCallback callback) = 0; + + // Opens the latest (highest `res_id`) cache entry that has a `res_id` less + // than `res_id_cursor`. This method is used for iterating through entries + // in reverse `res_id` order. To fetch all entries, start with + // `res_id_cursor` set to `std::numeric_limits::max()`. `callback` + // receives the entry (or `std::nullopt` if no more entries exist). + virtual void OpenLatestEntryBeforeResId( + int64_t res_id_cursor, + OptionalEntryInfoWithIdAndKeyCallback callback) = 0; + + // Checks if cache eviction should be initiated. This is typically called by + // the backend after an operation that increases the cache size. Returns true + // if the cache size has exceeded the high watermark and an eviction is not + // already in progress. + virtual bool ShouldStartEviction() = 0; + + // Starts the eviction process to reduce the cache size. This method removes + // the least recently used entries until the total cache size is below the + // low watermark. Entries with keys in `excluded_keys` (typically active + // entries) will not be evicted. `callback` is invoked upon completion. + virtual void StartEviction(base::flat_set excluded_keys, + ErrorCallback callback) = 0; + // The maximum size of an individual cache entry's data stream. virtual int64_t MaxFileSize() const = 0; @@ -164,6 +311,9 @@ class NET_EXPORT_PRIVATE SqlPersistentStore { // Asynchronously retrieves the total size of all entries. virtual void GetSizeOfAllEntries(Int64Callback callback) const = 0; + // Enables a strict corruption checking mode for testing purposes. + virtual void EnableStrictCorruptionCheckForTesting() = 0; + protected: SqlPersistentStore() = default; }; diff --git a/naiveproxy/src/net/disk_cache/sql/sql_persistent_store_queries.h b/naiveproxy/src/net/disk_cache/sql/sql_persistent_store_queries.h new file mode 100644 index 0000000000..e7c7275c29 --- /dev/null +++ b/naiveproxy/src/net/disk_cache/sql/sql_persistent_store_queries.h @@ -0,0 +1,517 @@ +// Copyright 2025 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_DISK_CACHE_SQL_SQL_PERSISTENT_STORE_QUERIES_H_ +#define NET_DISK_CACHE_SQL_SQL_PERSISTENT_STORE_QUERIES_H_ + +#include "base/notreached.h" +#include "base/strings/cstring_view.h" + +namespace disk_cache_sql_queries { +namespace internal { + +// The query strings are defined in this namespace to hide them from the public +// API. Callers should use `GetQuery()` instead. +// +// The query strings are defined as `inline constexpr` variables in this header +// file. This allows for compile-time optimization. + +// The `resources` table stores the main metadata for each cache entry. +inline constexpr const char kInitSchema_CreateTableResources[] = + // clang-format off + "CREATE TABLE IF NOT EXISTS resources(" + // Unique ID for the resource + "res_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," + // High part of an unguessable token + "token_high INTEGER NOT NULL," + // Low part of an unguessable token + "token_low INTEGER NOT NULL," + // Timestamp for LRU + "last_used INTEGER NOT NULL," + // End offset of the body + "body_end INTEGER NOT NULL," + // Total bytes consumed by the entry + "bytes_usage INTEGER NOT NULL," + // Flag for entries pending deletion + "doomed INTEGER NOT NULL," + // The cache key created by HttpCache::GenerateCacheKeyForRequest() + "cache_key TEXT NOT NULL," + // Serialized response headers + "head BLOB)"; +// clang-format on + +// The `blobs` table stores the data chunks of the cached body. +inline constexpr const char kInitSchema_CreateTableBlobs[] = + // clang-format off + "CREATE TABLE IF NOT EXISTS blobs(" + // Unique ID for the blob + "blob_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," + // Foreign key to resources.token_high + "token_high INTEGER NOT NULL," + // Foreign key to resources.token_low + "token_low INTEGER NOT NULL," + // Start offset of this blob chunk + "start INTEGER NOT NULL," + // End offset of this blob chunk + "end INTEGER NOT NULL," + // The actual data chunk + "blob BLOB NOT NULL)"; +// clang-format on + +// A unique index on the entry's token. This is used to quickly look up or +// update a resource entry using its unique token, which is essential for +// operations like `DoomEntry`, `UpdateEntryHeaderAndLastUsed`, and +// `WriteEntryData`. The `UNIQUE` constraint ensures data integrity by +// preventing duplicate tokens. +inline constexpr const char kIndex_ResourcesToken[] = + "CREATE UNIQUE INDEX IF NOT EXISTS index_resources_token ON " + "resources(token_high, token_low)"; + +// An index on `(cache_key, doomed)` to speed up lookups for live entries. This +// is frequently used in operations like `OpenEntry` to quickly find a +// non-doomed entry for a given cache key. +inline constexpr const char kIndex_ResourcesCacheKeyDoomed[] = + "CREATE INDEX IF NOT EXISTS index_resources_cache_key_doomed ON " + "resources(cache_key, doomed)"; + +// An index on `(doomed, last_used)` to optimize eviction logic. Eviction +// typically targets the least recently used (`last_used`) live (`doomed=false`) +// entries. This index significantly speeds up queries that select entries for +// eviction. +inline constexpr const char kIndex_ResourcesDoomedLastUsed[] = + "CREATE INDEX IF NOT EXISTS index_resources_doomed_last_used ON " + "resources(doomed, last_used)"; + +// An index on `(doomed, res_id)` to optimize iterating through entries while +// filtering for live (`doomed=false`) entries. `res_id` is a monotonically +// increasing primary key, making this index ideal for ordered traversals like +// in `OpenLatestEntryBeforeResId`. +inline constexpr const char kIndex_ResourcesDoomedResId[] = + "CREATE INDEX IF NOT EXISTS index_resources_doomed_res_id ON " + "resources(doomed, res_id)"; + +// A unique index on `(token_high, token_low, start)` in the `blobs` table. This +// is critical for quickly finding the correct data blobs for a given entry when +// reading or writing data at a specific offset. The `UNIQUE` constraint +// ensures that there are no overlapping blobs starting at the same offset for +// the same entry, which is important for data integrity. +inline constexpr const char kIndex_BlobsTokenStart[] = + "CREATE UNIQUE INDEX IF NOT EXISTS index_blobs_token_start ON " + "blobs(token_high, token_low, start)"; + +inline constexpr const char kOpenEntry_SelectLiveResources[] = + // clang-format off + "SELECT " + "token_high," // 0 + "token_low," // 1 + "last_used," // 2 + "body_end," // 3 + "head " // 4 + "FROM resources " + "WHERE " + "cache_key=? AND " // 0 + "doomed=0 " + "ORDER BY res_id DESC"; +// clang-format on + +inline constexpr const char kCreateEntry_InsertIntoResources[] = + // clang-format off + "INSERT INTO resources(" + "token_high," // 0 + "token_low," // 1 + "last_used," // 2 + "body_end," // 3 + "bytes_usage," // 4 + "doomed," + "cache_key) " // 5 + "VALUES(?,?,?,?,?,0,?)"; +// clang-format on + +inline constexpr const char kDoomEntry_MarkDoomedResources[] = + // clang-format off + "UPDATE resources " + "SET " + "doomed=1 " + "WHERE " + "cache_key=? AND " // 0 + "token_high=? AND " // 1 + "token_low=? AND " // 2 + "doomed=0 " + "RETURNING " + "bytes_usage"; // 0 +// clang-format on + +inline constexpr const char kDeleteDoomedEntry_DeleteFromResources[] = + // clang-format off + "DELETE FROM resources " + "WHERE " + "cache_key=? AND " // 0 + "token_high=? AND " // 1 + "token_low=? AND " // 2 + "doomed=1"; +// clang-format on + +inline constexpr const char kDeleteDoomedEntries_SelectDoomedResources[] = + // clang-format off + "SELECT " + "res_id," // 0 + "token_high," // 1 + "token_low " // 2 + "FROM resources " + "WHERE doomed=1"; +// clang-format on + +inline constexpr const char kDeleteLiveEntry_DeleteFromResources[] = + // clang-format off + "DELETE FROM resources " + "WHERE " + "cache_key=? AND " // 0 + "doomed=0 " + "RETURNING " + "token_high," // 0 + "token_low," // 1 + "bytes_usage"; // 2 +// clang-format on + +inline constexpr const char kDeleteAllEntries_DeleteFromResources[] = + "DELETE FROM resources"; + +inline constexpr const char kDeleteAllEntries_DeleteFromBlobs[] = + "DELETE FROM blobs"; + +inline constexpr const char kDeleteLiveEntriesBetween_SelectLiveResources[] = + // clang-format off + "SELECT " + "res_id," // 0 + "token_high," // 1 + "token_low," // 2 + "bytes_usage," // 3 + "cache_key " // 4 + "FROM resources " + "WHERE " + "last_used>=? AND " // 0 + "last_used=? AND " // 2 + "end<=? " // 3 + "RETURNING " + "start," // 0 + "end"; // 1 +// clang-format on + +inline constexpr const char kTrimOverlappingBlobs_SelectOverlapping[] = + // clang-format off + "SELECT " + "blob_id," // 0 + "start," // 1 + "end," // 2 + "blob " // 3 + "FROM blobs " + "WHERE " + "token_high=? AND " // 0 + "token_low=? AND " // 1 + "start?"; // 3 +// clang-format on + +inline constexpr const char kTruncateBlobsAfter_DeleteAfter[] = + // clang-format off + "DELETE FROM blobs " + "WHERE " + "token_high=? AND " // 0 + "token_low=? AND " // 1 + "start>=? " // 2 + "RETURNING " + "start," // 0 + "end"; // 1 +// clang-format on + +inline constexpr const char kInsertNewBlob_InsertIntoBlobs[] = + // clang-format off + "INSERT INTO blobs(" + "token_high," // 0 + "token_low," // 1 + "start," // 2 + "end," // 3 + "blob) " // 4 + "VALUES(?,?,?,?,?)"; +// clang-format on + +inline constexpr const char kDeleteBlobById_DeleteFromBlobs[] = + // clang-format off + "DELETE FROM blobs " + "WHERE " + "blob_id=? " // 0 + "RETURNING " + "start," // 0 + "end"; // 1 +// clang-format on + +inline constexpr const char kDeleteBlobsByToken_DeleteFromBlobs[] = + // clang-format off + "DELETE FROM blobs " + "WHERE " + "token_high=? AND " // 0 + "token_low=?"; // 1 +// clang-format on + +inline constexpr const char kReadEntryData_SelectOverlapping[] = + // clang-format off + "SELECT " + "start," // 0 + "end," // 1 + "blob " // 2 + "FROM blobs " + "WHERE " + "token_high=? AND " // 0 + "token_low=? AND " // 1 + "start? " // 3 + "ORDER BY start"; +// clang-format on + +inline constexpr const char kGetEntryAvailableRange_SelectOverlapping[] = + // clang-format off + "SELECT " + "start," // 0 + "end " // 1 + "FROM blobs " + "WHERE " + "token_high=? AND " // 0 + "token_low=? AND " // 1 + "start? " // 3 + "ORDER BY start"; +// clang-format on + +inline constexpr const char + kCalculateSizeOfEntriesBetween_SelectLiveResources[] = + // clang-format off + "SELECT " + "bytes_usage " // 0 + "FROM resources " + "WHERE " + "last_used>=? AND " // 0 + "last_used #include +#include "base/containers/span.h" #include "base/memory/raw_ptr.h" #include "build/build_config.h" @@ -63,10 +64,16 @@ bool ComparePolicy(const AddressSorterPosix::PolicyEntry& p1, } // Creates sorted PolicyTable from |table| with |size| entries. +// TODO(crbug.com/431824301): Remove unneeded parameter once validated to be +// redundant in M143. AddressSorterPosix::PolicyTable LoadPolicy( - const AddressSorterPosix::PolicyEntry* table, - size_t size) { - AddressSorterPosix::PolicyTable result(table, table + size); + base::span table, + size_t spanification_suspected_redundant_size) { + CHECK(spanification_suspected_redundant_size == table.size(), + base::NotFatalUntil::M143); + AddressSorterPosix::PolicyTable result( + table.data(), + table.subspan(spanification_suspected_redundant_size).data()); std::sort(result.begin(), result.end(), ComparePolicy); return result; } diff --git a/naiveproxy/src/net/dns/context_host_resolver.h b/naiveproxy/src/net/dns/context_host_resolver.h index 4d42a715fe..91a1dfe938 100644 --- a/naiveproxy/src/net/dns/context_host_resolver.h +++ b/naiveproxy/src/net/dns/context_host_resolver.h @@ -7,7 +7,6 @@ #include #include -#include #include #include "base/memory/raw_ptr.h" diff --git a/naiveproxy/src/net/dns/dns_config_service_linux.cc b/naiveproxy/src/net/dns/dns_config_service_linux.cc index 7aaf9fa5b0..8c0bf26c27 100644 --- a/naiveproxy/src/net/dns/dns_config_service_linux.cc +++ b/naiveproxy/src/net/dns/dns_config_service_linux.cc @@ -217,7 +217,8 @@ void RecordIncompatibleNsswitchReason( } bool IsNsswitchConfigCompatible( - const std::vector& nsswitch_hosts) { + const std::vector& nsswitch_hosts, + ResolvReader& resolv_reader) { bool files_found = false; for (const NsswitchReader::ServiceSpecification& specification : nsswitch_hosts) { @@ -253,6 +254,20 @@ bool IsNsswitchConfigCompatible( } break; + case NsswitchReader::Service::kResolve: + // If /etc/resolv.conf points to systemd-resolved then treat nss-resolve + // the same as nss-dns. If it's not then consider the nsswitch + // configuration incompatible. + if (!resolv_reader.IsLikelySystemdResolved()) { + RecordIncompatibleNsswitchReason( + IncompatibleNsswitchReason::kIncompatibleService, + specification.service); + return false; + } + // systemd-resolved also supports looking up records from /etc/hosts. + files_found = true; + [[fallthrough]]; + case NsswitchReader::Service::kDns: if (!files_found) { RecordIncompatibleNsswitchReason( @@ -280,7 +295,6 @@ bool IsNsswitchConfigCompatible( case NsswitchReader::Service::kMdns: case NsswitchReader::Service::kMdns4: case NsswitchReader::Service::kMdns6: - case NsswitchReader::Service::kResolve: case NsswitchReader::Service::kNis: RecordIncompatibleNsswitchReason( IncompatibleNsswitchReason::kIncompatibleService, @@ -468,7 +482,7 @@ class DnsConfigServiceLinux::ConfigReader : public SerialWorker { std::vector nsswitch_hosts = nsswitch_reader_->ReadAndParseHosts(); dns_config_->unhandled_options = - !IsNsswitchConfigCompatible(nsswitch_hosts); + !IsNsswitchConfigCompatible(nsswitch_hosts, *resolv_reader_); base::UmaHistogramBoolean("Net.DNS.DnsConfig.Nsswitch.Compatible", !dns_config_->unhandled_options); } diff --git a/naiveproxy/src/net/dns/dns_config_watcher_mac.cc b/naiveproxy/src/net/dns/dns_config_watcher_mac.cc index e318ebb645..3ad56087db 100644 --- a/naiveproxy/src/net/dns/dns_config_watcher_mac.cc +++ b/naiveproxy/src/net/dns/dns_config_watcher_mac.cc @@ -12,8 +12,8 @@ #include #include "base/compiler_specific.h" -#include "base/lazy_instance.h" #include "base/memory/raw_ptr.h" +#include "base/no_destructor.h" #include "third_party/apple_apsl/dnsinfo.h" namespace { @@ -57,8 +57,8 @@ class DnsInfoApi { }; const DnsInfoApi& GetDnsInfoApi() { - static base::LazyInstance::Leaky api = LAZY_INSTANCE_INITIALIZER; - return api.Get(); + static base::NoDestructor api; + return *api; } struct DnsConfigTDeleter { diff --git a/naiveproxy/src/net/dns/dns_reloader.cc b/naiveproxy/src/net/dns/dns_reloader.cc index e7a8877858..8ef378af21 100644 --- a/naiveproxy/src/net/dns/dns_reloader.cc +++ b/naiveproxy/src/net/dns/dns_reloader.cc @@ -40,7 +40,7 @@ #if defined(USE_RES_NINIT) -#include "base/lazy_instance.h" +#include "base/no_destructor.h" #include "base/notreached.h" #include "base/synchronization/lock.h" #include "base/task/current_thread.h" @@ -126,25 +126,26 @@ class DnsReloader : public NetworkChangeNotifier::DNSObserver { base::Lock lock_; // Protects resolver_generation_. int resolver_generation_ = 0; - friend struct base::LazyInstanceTraitsBase; + friend class base::NoDestructor; // We use thread local storage to identify which ReloadState to interact with. base::ThreadLocalOwnedPointer tls_reload_state_; }; -base::LazyInstance::Leaky - g_dns_reloader = LAZY_INSTANCE_INITIALIZER; +DnsReloader* GetDnsReloader() { + static base::NoDestructor dns_reloader; + return dns_reloader.get(); +} } // namespace void EnsureDnsReloaderInit() { - g_dns_reloader.Pointer(); + GetDnsReloader(); } void DnsReloaderMaybeReload() { // This routine can be called by any of the DNS worker threads. - DnsReloader* dns_reloader = g_dns_reloader.Pointer(); - dns_reloader->MaybeReload(); + GetDnsReloader()->MaybeReload(); } } // namespace net diff --git a/naiveproxy/src/net/dns/dns_test_util.cc b/naiveproxy/src/net/dns/dns_test_util.cc index d53ee86330..673512bf17 100644 --- a/naiveproxy/src/net/dns/dns_test_util.cc +++ b/naiveproxy/src/net/dns/dns_test_util.cc @@ -2,16 +2,12 @@ // 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 "net/dns/dns_test_util.h" #include #include +#include #include #include #include @@ -19,6 +15,7 @@ #include #include "base/check.h" +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/functional/bind.h" #include "base/location.h" @@ -50,7 +47,7 @@ namespace net { namespace { -const uint8_t kMalformedResponseHeader[] = { +constexpr auto kMalformedResponseHeader = std::to_array({ // Header 0x00, 0x14, // Arbitrary ID 0x81, 0x80, // Standard query response, RA, no error @@ -58,7 +55,7 @@ const uint8_t kMalformedResponseHeader[] = { 0x00, 0x01, // 1 RR (answers) 0x00, 0x00, // 0 authority RRs 0x00, 0x00, // 0 additional RRs -}; +}); // Create a response containing a valid question (as would normally be validated // in DnsTransaction) but completely missing a header-declared answer. @@ -71,11 +68,11 @@ DnsResponse CreateMalformedResponse(std::string hostname, uint16_t type) { // Build response to simulate the barebones validation DnsResponse applies to // responses received from the network. auto buffer = base::MakeRefCounted( - sizeof(kMalformedResponseHeader) + query.question().size()); - memcpy(buffer->data(), kMalformedResponseHeader, - sizeof(kMalformedResponseHeader)); - memcpy(buffer->data() + sizeof(kMalformedResponseHeader), - query.question().data(), query.question().size()); + kMalformedResponseHeader.size() + query.question().size()); + auto out_span = buffer->span(); + out_span.take_first(kMalformedResponseHeader.size()) + .copy_from(kMalformedResponseHeader); + out_span.copy_from(base::as_byte_span(query.question())); DnsResponse response(buffer, buffer->size()); CHECK(response.InitParseWithoutQuery(buffer->size())); @@ -134,10 +131,8 @@ DnsResourceRecord BuildTestCnameRecord(std::string name, dns_names_util::DottedNameToNetwork(canonical_name); CHECK(rdata.has_value()); - return BuildTestDnsRecord( - std::move(name), dns_protocol::kTypeCNAME, - base::span(rdata.value().data(), rdata.value().size()), - ttl); + return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeCNAME, + rdata.value(), ttl); } DnsResourceRecord BuildTestAddressRecord(std::string name, @@ -166,9 +161,8 @@ DnsResourceRecord BuildTestTextRecord(std::string name, rdata.insert(rdata.end(), text_string.begin(), text_string.end()); } - return BuildTestDnsRecord( - std::move(name), dns_protocol::kTypeTXT, - base::span(rdata.data(), rdata.size()), ttl); + return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeTXT, rdata, + ttl); } DnsResourceRecord BuildTestHttpsAliasRecord(std::string name, @@ -184,9 +178,8 @@ DnsResourceRecord BuildTestHttpsAliasRecord(std::string name, rdata.insert(rdata.end(), alias_domain.value().begin(), alias_domain.value().end()); - return BuildTestDnsRecord( - std::move(name), dns_protocol::kTypeHttps, - base::span(rdata.data(), rdata.size()), ttl); + return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeHttps, rdata, + ttl); } std::pair BuildTestHttpsServiceAlpnParam( @@ -288,9 +281,8 @@ DnsResourceRecord BuildTestHttpsServiceRecord( rdata.insert(rdata.end(), param.second.begin(), param.second.end()); } - return BuildTestDnsRecord( - std::move(name), dns_protocol::kTypeHttps, - base::span(rdata.data(), rdata.size()), ttl); + return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeHttps, rdata, + ttl); } DnsResponse BuildTestDnsResponse( @@ -345,8 +337,7 @@ DnsResponse BuildTestDnsAddressResponseWithCname(std::string name, std::vector answers = { BuildTestDnsRecord(std::move(answer_name), dns_protocol::kTypeCNAME, - base::span(cname_rdata.value().data(), - cname_rdata.value().size())), + cname_rdata.value()), BuildTestAddressRecord(std::move(cannonname), ip)}; return BuildTestDnsResponse( @@ -381,9 +372,8 @@ DnsResponse BuildTestDnsPointerResponse(std::string name, dns_names_util::DottedNameToNetwork(pointer_name); CHECK(rdata.has_value()); - answers.push_back(BuildTestDnsRecord( - answer_name, dns_protocol::kTypePTR, - base::span(rdata.value().data(), rdata.value().size()))); + answers.push_back( + BuildTestDnsRecord(answer_name, dns_protocol::kTypePTR, rdata.value())); } return BuildTestDnsResponse(std::move(name), dns_protocol::kTypePTR, answers); @@ -418,9 +408,8 @@ DnsResponse BuildTestDnsServiceResponse( CHECK(dns_name.has_value()); rdata.insert(rdata.end(), dns_name.value().begin(), dns_name.value().end()); - answers.push_back(BuildTestDnsRecord( - answer_name, dns_protocol::kTypeSRV, - base::span(rdata.data(), rdata.size()), base::Hours(5))); + answers.push_back(BuildTestDnsRecord(answer_name, dns_protocol::kTypeSRV, + rdata, base::Hours(5))); } return BuildTestDnsResponse(std::move(name), dns_protocol::kTypeSRV, answers); @@ -588,8 +577,9 @@ class MockDnsTransactionFactory::MockTransaction final : public DnsTransaction { // completes. auto buffer_copy = base::MakeRefCounted( result->response->io_buffer_size()); - memcpy(buffer_copy->data(), result->response->io_buffer()->data(), - result->response->io_buffer_size()); + buffer_copy->span().copy_from_nonoverlapping( + result->response->io_buffer()->first( + result->response->io_buffer_size())); result_.response = DnsResponse(std::move(buffer_copy), result->response->io_buffer_size()); CHECK(result_.response->InitParseWithoutQuery( diff --git a/naiveproxy/src/net/dns/host_cache.cc b/naiveproxy/src/net/dns/host_cache.cc index b2ef120926..e9043595ab 100644 --- a/naiveproxy/src/net/dns/host_cache.cc +++ b/naiveproxy/src/net/dns/host_cache.cc @@ -28,13 +28,13 @@ #include "base/numerics/safe_conversions.h" #include "base/strings/string_number_conversions.h" #include "base/time/default_tick_clock.h" +#include "base/trace_event/trace_event.h" #include "base/types/optional_util.h" #include "base/value_iterators.h" #include "net/base/address_family.h" #include "net/base/ip_endpoint.h" #include "net/base/network_anonymization_key.h" #include "net/base/trace_constants.h" -#include "net/base/tracing.h" #include "net/base/url_util.h" #include "net/dns/host_resolver.h" #include "net/dns/host_resolver_internal_result.h" @@ -387,8 +387,6 @@ HostCache::Entry::Entry( // Even if otherwise empty, having the metadata result object signifies // receiving a compatible HTTPS record. - https_record_compatibility_ = std::vector{true}; - if (data_results.empty() && endpoint_metadatas_.empty()) { error_ = ERR_NAME_NOT_RESOLVED; } @@ -467,8 +465,6 @@ HostCache::Entry HostCache::Entry::MergeEntries(Entry front, Entry back) { MergeContainers(front.aliases_, back.aliases_); MergeLists(front.text_records_, back.text_records()); MergeLists(front.hostnames_, back.hostnames()); - MergeLists(front.https_record_compatibility_, - back.https_record_compatibility_); MergeContainers(front.canonical_names_, back.canonical_names_); // Only expected to merge entries from same source. @@ -579,7 +575,6 @@ HostCache::Entry::Entry(const HostCache::Entry& entry, aliases_(entry.aliases()), text_records_(entry.text_records()), hostnames_(entry.hostnames()), - https_record_compatibility_(entry.https_record_compatibility_), source_(entry.source()), pinning_(entry.pinning()), canonical_names_(entry.canonical_names()), @@ -595,7 +590,6 @@ HostCache::Entry::Entry( std::set aliases, std::vector&& text_records, std::vector&& hostnames, - std::vector&& https_record_compatibility, Source source, base::TimeTicks expires, int network_changes) @@ -605,15 +599,10 @@ HostCache::Entry::Entry( aliases_(std::move(aliases)), text_records_(std::move(text_records)), hostnames_(std::move(hostnames)), - https_record_compatibility_(std::move(https_record_compatibility)), source_(source), expires_(expires), network_changes_(network_changes) {} -void HostCache::Entry::PrepareForCacheInsertion() { - https_record_compatibility_.clear(); -} - bool HostCache::Entry::IsStale(base::TimeTicks now, int network_changes) const { EntryStaleness stale; stale.expired_by = now - expires_; @@ -888,7 +877,6 @@ void HostCache::Set(const Key& key, Entry entry_for_cache(entry, now, ttl, network_changes_); entry_for_cache.set_pinning(entry.pinning().value_or(has_active_pin)); - entry_for_cache.PrepareForCacheInsertion(); AddEntry(key, std::move(entry_for_cache)); if (delegate_ && result_changed) @@ -1209,9 +1197,6 @@ bool HostCache::RestoreFromListValue(const base::Value::List& old_cache) { } } - // We do not intend to serialize experimental results with the host cache. - std::vector experimental_results; - Key key(std::move(host), dns_query_type.value(), flags, static_cast(host_resolver_source), network_anonymization_key); @@ -1224,8 +1209,8 @@ bool HostCache::RestoreFromListValue(const base::Value::List& old_cache) { Entry new_entry(error, std::move(ip_endpoints), std::move(endpoint_metadatas), std::move(aliases), std::move(text_records), std::move(hostname_records), - std::move(experimental_results), Entry::SOURCE_UNKNOWN, - expiration_time, network_changes_ - 1); + Entry::SOURCE_UNKNOWN, expiration_time, + network_changes_ - 1); new_entry.set_pinning(maybe_pinned.value_or(false)); new_entry.set_canonical_names(std::move(canonical_names)); AddEntry(key, std::move(new_entry)); diff --git a/naiveproxy/src/net/dns/host_cache.h b/naiveproxy/src/net/dns/host_cache.h index 737ec34eaf..1ef6a0c74b 100644 --- a/naiveproxy/src/net/dns/host_cache.h +++ b/naiveproxy/src/net/dns/host_cache.h @@ -26,7 +26,6 @@ #include "base/numerics/clamped_math.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" -#include "base/types/optional_util.h" #include "base/values.h" #include "net/base/address_family.h" #include "net/base/connection_endpoint_metadata.h" @@ -178,12 +177,11 @@ class NET_EXPORT HostCache { bool ContentsEqual(const Entry& other) const { return std::tie(error_, ip_endpoints_, endpoint_metadatas_, aliases_, - text_records_, hostnames_, https_record_compatibility_, - canonical_names_) == - std::tie( - other.error_, other.ip_endpoints_, other.endpoint_metadatas_, - other.aliases_, other.text_records_, other.hostnames_, - other.https_record_compatibility_, other.canonical_names_); + text_records_, hostnames_, canonical_names_) == + std::tie(other.error_, other.ip_endpoints_, + other.endpoint_metadatas_, other.aliases_, + other.text_records_, other.hostnames_, + other.canonical_names_); } int error() const { return error_; } @@ -215,13 +213,6 @@ class NET_EXPORT HostCache { void set_hostnames(std::vector hostnames) { hostnames_ = std::move(hostnames); } - const std::vector& https_record_compatibility() const { - return https_record_compatibility_; - } - void set_https_record_compatibility( - std::vector https_record_compatibility) { - https_record_compatibility_ = std::move(https_record_compatibility); - } std::optional pinning() const { return pinning_; } void set_pinning(std::optional pinning) { pinning_ = pinning; } @@ -289,13 +280,10 @@ class NET_EXPORT HostCache { std::set aliases, std::vector&& text_results, std::vector&& hostnames, - std::vector&& https_record_compatibility, Source source, base::TimeTicks expires, int network_changes); - void PrepareForCacheInsertion(); - void SetResult( std::multimap endpoint_metadatas) { @@ -307,9 +295,6 @@ class NET_EXPORT HostCache { void SetResult(std::vector hostnames) { hostnames_ = std::move(hostnames); } - void SetResult(std::vector https_record_compatibility) { - https_record_compatibility_ = std::move(https_record_compatibility); - } int total_hits() const { return total_hits_; } int stale_hits() const { return stale_hits_; } @@ -331,16 +316,6 @@ class NET_EXPORT HostCache { std::vector text_records_; std::vector hostnames_; - // Bool of whether each HTTPS record received is compatible - // (draft-ietf-dnsop-svcb-https-08#section-8), considering alias records to - // always be compatible. - // - // This field may be reused for experimental query types to record - // successfully received records of that experimental type. - // - // For either usage, cleared before inserting in cache. - std::vector https_record_compatibility_; - // Where results were obtained (e.g. DNS lookup, hosts file, etc). Source source_ = SOURCE_UNKNOWN; // If true, this entry cannot be evicted from the cache until after the next diff --git a/naiveproxy/src/net/dns/host_resolver.cc b/naiveproxy/src/net/dns/host_resolver.cc index fea5a6cda6..a2576a1375 100644 --- a/naiveproxy/src/net/dns/host_resolver.cc +++ b/naiveproxy/src/net/dns/host_resolver.cc @@ -75,22 +75,25 @@ class FailingRequestImpl : public HostResolver::ResolveHostRequest, int Start(CompletionOnceCallback callback) override { return error_; } int Start() override { return error_; } - AddressList* GetAddressResults() const override { return nullptr; } - - std::vector* GetEndpointResults() const override { - return nullptr; + const AddressList& GetAddressResults() const override { + static const base::NoDestructor kEmptyResult; + return *kEmptyResult; } - const std::vector* GetTextResults() const override { - return nullptr; + base::span GetEndpointResults() + const override { + return {}; } - const std::vector* GetHostnameResults() const override { - return nullptr; + base::span GetTextResults() const override { return {}; } + + base::span GetHostnameResults() const override { + return {}; } - const std::set* GetDnsAliasResults() const override { - return nullptr; + const std::set& GetDnsAliasResults() const override { + static const base::NoDestructor> kEmptyResult; + return *kEmptyResult; } ResolveErrorInfo GetResolveErrorInfo() const override { @@ -122,10 +125,7 @@ class FailingServiceEndpointRequestImpl int Start(Delegate* delegate) override { return error_; } - const std::vector& GetEndpointResults() override { - static const base::NoDestructor> kEmptyResult; - return *kEmptyResult.get(); - } + base::span GetEndpointResults() override { return {}; } const std::set& GetDnsAliasResults() override { static const base::NoDestructor> kEmptyResult; @@ -150,10 +150,6 @@ class FailingServiceEndpointRequestImpl const int error_; }; -bool EndpointResultIsNonProtocol(const HostResolverEndpointResult& result) { - return result.metadata.supported_protocol_alpns.empty(); -} - void GetTimeDeltaFromDictString(const base::Value::Dict& args, std::string_view key, base::TimeDelta* out) { @@ -308,11 +304,6 @@ HostResolver::ManagerOptions::ManagerOptions(ManagerOptions&& other) = default; HostResolver::ManagerOptions::~ManagerOptions() = default; -const std::vector* -HostResolver::ResolveHostRequest::GetExperimentalResultsForTesting() const { - NOTREACHED(); -} - std::unique_ptr HostResolver::Factory::CreateResolver( HostResolverManager* manager, std::string_view host_mapping_rules, @@ -585,12 +576,14 @@ AddressList HostResolver::EndpointResultToAddressList( const std::set& aliases) { AddressList list; - auto non_protocol_endpoint = - std::ranges::find_if(endpoints, &EndpointResultIsNonProtocol); - if (non_protocol_endpoint == endpoints.end()) + auto authority_endpoint = std::ranges::find_if_not( + endpoints, + [](const auto& endpoint) { return endpoint.metadata.IsAlternative(); }); + if (authority_endpoint == endpoints.end()) { return list; + } - list.endpoints() = non_protocol_endpoint->ip_endpoints; + list.endpoints() = authority_endpoint->ip_endpoints; std::vector aliases_vector(aliases.begin(), aliases.end()); list.SetDnsAliases(std::move(aliases_vector)); diff --git a/naiveproxy/src/net/dns/host_resolver.h b/naiveproxy/src/net/dns/host_resolver.h index 5296295206..39aae1d3dc 100644 --- a/naiveproxy/src/net/dns/host_resolver.h +++ b/naiveproxy/src/net/dns/host_resolver.h @@ -124,35 +124,34 @@ class NET_EXPORT HostResolver { // Address record (A or AAAA) results of the request. Should only be called // after Start() signals completion, either by invoking the callback or by - // returning a result other than |ERR_IO_PENDING|. May return nullptr or - // empty for non-address requests. + // returning a result other than |ERR_IO_PENDING|. May empty for non-address + // requests. // // TODO(crbug.com/40203587): Remove and replace all usage with // GetEndpointResults(). - virtual const AddressList* GetAddressResults() const = 0; + virtual const AddressList& GetAddressResults() const = 0; // Endpoint results for `A`, `AAAA`, `UNSPECIFIED`, or `HTTPS` requests. // Should only be called after Start() signals completion, either by // invoking the callback or by returning a result other than - // `ERR_IO_PENDING`. May return nullptr or empty for non-address/HTTPS - // requests. - virtual const std::vector* GetEndpointResults() + // `ERR_IO_PENDING`. May return empty for non-address/HTTPS requests. + virtual base::span GetEndpointResults() const = 0; // Text record (TXT) results of the request. Should only be called after // Start() signals completion, either by invoking the callback or by - // returning a result other than |ERR_IO_PENDING|. May return nullptr or - // empty for non-TXT requests. - virtual const std::vector* GetTextResults() const = 0; + // returning a result other than |ERR_IO_PENDING|. May return empty for + // non-TXT requests. + virtual base::span GetTextResults() const = 0; // Hostname record (SRV or PTR) results of the request. For SRV results, // hostnames are ordered according to their priorities and weights. See RFC - // 2782. May return nullptr or empty for non-SRV/PTR requests. + // 2782. May return empty for non-SRV/PTR requests. // // Should only be called after Start() signals completion, either by // invoking the callback or by returning a result other than // |ERR_IO_PENDING|. - virtual const std::vector* GetHostnameResults() const = 0; + virtual base::span GetHostnameResults() const = 0; // Any DNS record aliases, such as CNAME aliases, found as a result of an // address query. Includes all known aliases, e.g. from A, AAAA, or HTTPS, @@ -161,7 +160,7 @@ class NET_EXPORT HostResolver { // invoking the callback or by returning a result other than // `ERR_IO_PENDING`. Returns a list of aliases that has been fixed up and // canonicalized (as URL hostnames), and thus may differ from the results - // stored directly in the AddressList. May return nullptr or empty for + // stored directly in the AddressList. May return empty for // non-address/HTTPS requests. // // If `ResolveHostParameters::include_canonical_name` was true, alias @@ -169,14 +168,7 @@ class NET_EXPORT HostResolver { // system resolver without URL hostname canonicalization (or an empty set or // `nullptr` in the unusual case that the system resolver did not give a // canonical name). - virtual const std::set* GetDnsAliasResults() const = 0; - - // Result of an experimental query. Meaning depends on the specific query - // type, but each boolean value generally refers to a valid or invalid - // record of the experimental type. May return nullptr or empty for requests - // without experimental result behavior. - NET_EXPORT virtual const std::vector* - GetExperimentalResultsForTesting() const; + virtual const std::set& GetDnsAliasResults() const = 0; // Error info for the request. // @@ -234,7 +226,7 @@ class NET_EXPORT HostResolver { // delegate's OnServiceEndpointsUpdated(). Results are finalized when // Start() finished synchronously (returning other than ERR_IO_PENDING), or // delegate's OnServiceEndpointRequestFinished() is called. - virtual const std::vector& GetEndpointResults() = 0; + virtual base::span GetEndpointResults() = 0; // Any DNS record aliases, such as CNAME aliases, found as a result of // addresses and HTTPS queries. These can be changed over time while @@ -629,8 +621,7 @@ class NET_EXPORT HostResolver { // Helper for squashing error code to a small set of DNS error codes. static int SquashErrorCode(int error); - // Builds an AddressList from the first non-protocol endpoint found in - // `endpoints`. + // Builds an AddressList from the first authority endpoint in `endpoints`. // // TODO(crbug.com/40203587): Delete once `AddressList` usage is fully replaced // in `HostResolver` and results. @@ -638,25 +629,25 @@ class NET_EXPORT HostResolver { base::span endpoints, const std::set& aliases); - // Returns whether there is at least one protocol endpoint in `endpoints`, and - // all such endpoints have ECH parameters. This can be used to implement the - // guidance in section 3 of RFC9460. + // Returns whether there is at least one alternative endpoint in `endpoints`, + // and all such endpoints have ECH parameters. This can be used to implement + // the guidance in section 5.1 of draft-ietf-tls-svcb-ech-08. template - static bool AllProtocolEndpointsHaveEch(base::span endpoints) + static bool AllAlternativeEndpointsHaveEch(base::span endpoints) requires HasConnectionEndpointMetadata { - bool has_svcb = false; + bool has_alternative = false; for (const auto& endpoint : endpoints) { - if (!endpoint.metadata.supported_protocol_alpns.empty()) { - has_svcb = true; + if (endpoint.metadata.IsAlternative()) { + has_alternative = true; if (endpoint.metadata.ech_config_list.empty()) { return false; // There is a non-ECH SVCB/HTTPS route. } } } - // Either there were no SVCB/HTTPS records (should be SVCB-optional), or + // Either there were no alternative endpoints (should be SVCB-optional), or // there were and all supported ECH (should be SVCB-reliant). - return has_svcb; + return has_alternative; } // Returns true if NAT64 can be used in place of an IPv4 address during host diff --git a/naiveproxy/src/net/dns/host_resolver_dns_task.cc b/naiveproxy/src/net/dns/host_resolver_dns_task.cc index bec87c2963..7a32ae4337 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 #include +#include "base/feature_list.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/time/tick_clock.h" @@ -26,6 +27,11 @@ namespace net { +// When enabled, query HTTPS RR first. +BASE_FEATURE(kPrioritizeHttpsResourceRecord, + "PrioritizeHttpsResourceRecord", + base::FEATURE_DISABLED_BY_DEFAULT); + namespace { DnsResponse CreateFakeEmptyResponse(std::string_view hostname, @@ -404,25 +410,38 @@ void HostResolverDnsTask::PushTransactionsNeeded(DnsQueryTypeSet query_types) { TransactionErrorBehavior::kFatalOrEmpty); } - // Give AAAA/A queries a head start by pushing them to the queue first. - constexpr DnsQueryType kHighPriorityQueries[] = {DnsQueryType::AAAA, - DnsQueryType::A}; - for (DnsQueryType high_priority_query : kHighPriorityQueries) { - if (query_types.Has(high_priority_query)) { - query_types.Remove(high_priority_query); - transactions_needed_.emplace_back(high_priority_query); - } - } - for (DnsQueryType remaining_query : query_types) { - if (remaining_query == DnsQueryType::HTTPS) { + auto add_transaction = [&](DnsQueryType query) { + if (query == DnsQueryType::HTTPS) { // Ignore errors for these types. In most cases treating them normally // would only result in fallback to resolution without querying the // type. Instead, synthesize empty results. transactions_needed_.emplace_back( - remaining_query, TransactionErrorBehavior::kSynthesizeEmpty); + query, TransactionErrorBehavior::kSynthesizeEmpty); } else { - transactions_needed_.emplace_back(remaining_query); + transactions_needed_.emplace_back(query); } + }; + + if (query_types.Has(DnsQueryType::HTTPS) && + (base::FeatureList::IsEnabled(kPrioritizeHttpsResourceRecord) || + base::FeatureList::IsEnabled(features::kHappyEyeballsV3))) { + query_types.Remove(DnsQueryType::HTTPS); + add_transaction(DnsQueryType::HTTPS); + } + + // Give AAAA/A queries a head start by pushing them to the queue first. + constexpr DnsQueryType kHighPriorityQueries[] = {DnsQueryType::AAAA, + DnsQueryType::A}; + for (DnsQueryType high_priority_query : kHighPriorityQueries) { + if (!query_types.Has(high_priority_query)) { + continue; + } + query_types.Remove(high_priority_query); + add_transaction(high_priority_query); + } + + for (DnsQueryType remaining_query : query_types) { + add_transaction(remaining_query); } } diff --git a/naiveproxy/src/net/dns/host_resolver_manager.cc b/naiveproxy/src/net/dns/host_resolver_manager.cc index f1450c1e65..e23ea3fe98 100644 --- a/naiveproxy/src/net/dns/host_resolver_manager.cc +++ b/naiveproxy/src/net/dns/host_resolver_manager.cc @@ -59,6 +59,7 @@ #include "base/threading/scoped_blocking_call.h" #include "base/time/default_tick_clock.h" #include "base/time/time.h" +#include "base/trace_event/trace_event.h" #include "base/types/optional_util.h" #include "base/values.h" #include "build/build_config.h" @@ -76,7 +77,6 @@ #include "net/base/prioritized_dispatcher.h" #include "net/base/request_priority.h" #include "net/base/trace_constants.h" -#include "net/base/tracing.h" #include "net/base/url_util.h" #include "net/dns/dns_alias_utility.h" #include "net/dns/dns_client.h" diff --git a/naiveproxy/src/net/dns/host_resolver_manager_request_impl.cc b/naiveproxy/src/net/dns/host_resolver_manager_request_impl.cc index 87518f48c3..ff3fe17763 100644 --- a/naiveproxy/src/net/dns/host_resolver_manager_request_impl.cc +++ b/naiveproxy/src/net/dns/host_resolver_manager_request_impl.cc @@ -97,54 +97,46 @@ int HostResolverManager::RequestImpl::Start(CompletionOnceCallback callback) { return rv; } -const AddressList* HostResolverManager::RequestImpl::GetAddressResults() const { +const AddressList& HostResolverManager::RequestImpl::GetAddressResults() const { DCHECK(complete_); - return base::OptionalToPtr(legacy_address_results_); + return legacy_address_results_; } -const std::vector* +base::span HostResolverManager::RequestImpl::GetEndpointResults() const { DCHECK(complete_); - return base::OptionalToPtr(endpoint_results_); + return endpoint_results_; } -const std::vector* -HostResolverManager::RequestImpl::GetTextResults() const { +base::span HostResolverManager::RequestImpl::GetTextResults() + const { DCHECK(complete_); - return results_ ? &results_.value().text_records() : nullptr; + return results_ ? results_->text_records() : base::span(); } -const std::vector* +base::span HostResolverManager::RequestImpl::GetHostnameResults() const { DCHECK(complete_); - return results_ ? &results_.value().hostnames() : nullptr; + return results_ ? results_->hostnames() : base::span(); } -const std::set* +const std::set& HostResolverManager::RequestImpl::GetDnsAliasResults() const { DCHECK(complete_); // If `include_canonical_name` param was true, should only ever have at most // a single alias, representing the expected "canonical name". #if DCHECK_IS_ON() - if (parameters().include_canonical_name && fixed_up_dns_alias_results_) { - DCHECK_LE(fixed_up_dns_alias_results_->size(), 1u); - if (GetAddressResults()) { - std::set address_list_aliases_set( - GetAddressResults()->dns_aliases().begin(), - GetAddressResults()->dns_aliases().end()); - DCHECK(address_list_aliases_set == fixed_up_dns_alias_results_.value()); - } + if (parameters().include_canonical_name) { + DCHECK_LE(fixed_up_dns_alias_results_.size(), 1u); + std::set address_list_aliases_set( + GetAddressResults().dns_aliases().begin(), + GetAddressResults().dns_aliases().end()); + DCHECK(address_list_aliases_set == fixed_up_dns_alias_results_); } #endif // DCHECK_IS_ON() - return base::OptionalToPtr(fixed_up_dns_alias_results_); -} - -const std::vector* -HostResolverManager::RequestImpl::GetExperimentalResultsForTesting() const { - DCHECK(complete_); - return results_ ? &results_.value().https_record_compatibility() : nullptr; + return fixed_up_dns_alias_results_; } net::ResolveErrorInfo HostResolverManager::RequestImpl::GetResolveErrorInfo() @@ -369,26 +361,24 @@ int HostResolverManager::RequestImpl::DoFinishRequest(int rv) { void HostResolverManager::RequestImpl::FixUpEndpointAndAliasResults() { DCHECK(results_.has_value()); - DCHECK(!legacy_address_results_.has_value()); - DCHECK(!endpoint_results_.has_value()); - DCHECK(!fixed_up_dns_alias_results_.has_value()); + DCHECK(legacy_address_results_.empty()); + DCHECK(endpoint_results_.empty()); + DCHECK(fixed_up_dns_alias_results_.empty()); - endpoint_results_ = results_.value().GetEndpoints(); - if (endpoint_results_.has_value()) { - fixed_up_dns_alias_results_ = results_.value().aliases(); + endpoint_results_ = results_->GetEndpoints(); + fixed_up_dns_alias_results_ = results_->aliases(); - // Skip fixups for `include_canonical_name` requests. Just use the - // canonical name exactly as it was received from the system resolver. - if (parameters().include_canonical_name) { - DCHECK_LE(fixed_up_dns_alias_results_.value().size(), 1u); - } else { - fixed_up_dns_alias_results_ = dns_alias_utility::FixUpDnsAliases( - fixed_up_dns_alias_results_.value()); - } - - legacy_address_results_ = HostResolver::EndpointResultToAddressList( - endpoint_results_.value(), fixed_up_dns_alias_results_.value()); + // Skip fixups for `include_canonical_name` requests. Just use the + // canonical name exactly as it was received from the system resolver. + if (parameters().include_canonical_name) { + DCHECK_LE(fixed_up_dns_alias_results_.size(), 1u); + } else { + fixed_up_dns_alias_results_ = + dns_alias_utility::FixUpDnsAliases(fixed_up_dns_alias_results_); } + + legacy_address_results_ = HostResolver::EndpointResultToAddressList( + endpoint_results_, fixed_up_dns_alias_results_); } void HostResolverManager::RequestImpl::LogStartRequest() { diff --git a/naiveproxy/src/net/dns/host_resolver_manager_request_impl.h b/naiveproxy/src/net/dns/host_resolver_manager_request_impl.h index 58640d3872..abe9f210c8 100644 --- a/naiveproxy/src/net/dns/host_resolver_manager_request_impl.h +++ b/naiveproxy/src/net/dns/host_resolver_manager_request_impl.h @@ -63,13 +63,12 @@ class HostResolverManager::RequestImpl // HostResolver::ResolveHostRequest implementations: int Start(CompletionOnceCallback callback) override; - const AddressList* GetAddressResults() const override; - const std::vector* GetEndpointResults() + const AddressList& GetAddressResults() const override; + base::span GetEndpointResults() const override; - const std::vector* GetTextResults() const override; - const std::vector* GetHostnameResults() const override; - const std::set* GetDnsAliasResults() const override; - const std::vector* GetExperimentalResultsForTesting() const override; + base::span GetTextResults() const override; + base::span GetHostnameResults() const override; + const std::set& GetDnsAliasResults() const override; net::ResolveErrorInfo GetResolveErrorInfo() const override; const std::optional& GetStaleInfo() const override; void ChangeRequestPriority(RequestPriority priority) override; @@ -174,9 +173,9 @@ class HostResolverManager::RequestImpl bool only_ipv6_reachable_ = false; std::optional results_; std::optional stale_info_; - std::optional legacy_address_results_; - std::optional> endpoint_results_; - std::optional> fixed_up_dns_alias_results_; + AddressList legacy_address_results_; + std::vector endpoint_results_; + std::set fixed_up_dns_alias_results_; ResolveErrorInfo error_info_; const raw_ptr tick_clock_; diff --git a/naiveproxy/src/net/dns/host_resolver_manager_service_endpoint_request_impl.cc b/naiveproxy/src/net/dns/host_resolver_manager_service_endpoint_request_impl.cc index 57dee19203..2183c9b013 100644 --- a/naiveproxy/src/net/dns/host_resolver_manager_service_endpoint_request_impl.cc +++ b/naiveproxy/src/net/dns/host_resolver_manager_service_endpoint_request_impl.cc @@ -109,7 +109,7 @@ bool HostResolverManager::ServiceEndpointRequestImpl::IsStaleWhileRefresing() stale_info_.has_value() && stale_info_.value().is_stale(); } -const std::vector& +base::span HostResolverManager::ServiceEndpointRequestImpl::GetEndpointResults() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -130,8 +130,7 @@ HostResolverManager::ServiceEndpointRequestImpl::GetEndpointResults() { return job_.value()->dns_task_results_manager()->GetCurrentEndpoints(); } - static const base::NoDestructor> kEmptyEndpoints; - return *kEmptyEndpoints.get(); + return {}; } const std::set& diff --git a/naiveproxy/src/net/dns/host_resolver_manager_service_endpoint_request_impl.h b/naiveproxy/src/net/dns/host_resolver_manager_service_endpoint_request_impl.h index c0eaea5d52..3512dcf3e4 100644 --- a/naiveproxy/src/net/dns/host_resolver_manager_service_endpoint_request_impl.h +++ b/naiveproxy/src/net/dns/host_resolver_manager_service_endpoint_request_impl.h @@ -50,7 +50,7 @@ class HostResolverManager::ServiceEndpointRequestImpl // HostResolver::ServiceEndpointRequest implementations: int Start(Delegate* delegate) override; - const std::vector& GetEndpointResults() override; + base::span GetEndpointResults() override; const std::set& GetDnsAliasResults() override; bool EndpointsCryptoReady() override; ResolveErrorInfo GetResolveErrorInfo() override; diff --git a/naiveproxy/src/net/dns/host_resolver_nat64_task.cc b/naiveproxy/src/net/dns/host_resolver_nat64_task.cc index ea0e1d5ed3..d0acf79a45 100644 --- a/naiveproxy/src/net/dns/host_resolver_nat64_task.cc +++ b/naiveproxy/src/net/dns/host_resolver_nat64_task.cc @@ -106,7 +106,7 @@ int HostResolverNat64Task::DoResolve() { int HostResolverNat64Task::DoResolveComplete(int result) { // If not under DNS64 and resolving ipv4only.arpa fails, return the original // IPv4 address. - if (result != OK || request_ipv4onlyarpa_->GetEndpointResults()->empty()) { + if (result != OK || request_ipv4onlyarpa_->GetEndpointResults().empty()) { IPAddress ipv4_address; bool is_ip = ipv4_address.AssignFromIPLiteral(hostname_); DCHECK(is_ip); @@ -130,7 +130,7 @@ int HostResolverNat64Task::DoSynthesizeToIpv6() { std::vector converted_addresses; - for (const auto& endpoints : *request_ipv4onlyarpa_->GetEndpointResults()) { + for (const auto& endpoints : request_ipv4onlyarpa_->GetEndpointResults()) { for (const auto& ip_endpoint : endpoints.ip_endpoints) { ipv4onlyarpa_AAAA_address = ip_endpoint.address(); diff --git a/naiveproxy/src/net/dns/host_resolver_system_task.cc b/naiveproxy/src/net/dns/host_resolver_system_task.cc index 7e0322db28..85776a47c2 100644 --- a/naiveproxy/src/net/dns/host_resolver_system_task.cc +++ b/naiveproxy/src/net/dns/host_resolver_system_task.cc @@ -25,6 +25,7 @@ #include "base/task/thread_pool.h" #include "base/threading/scoped_blocking_call.h" #include "base/time/time.h" +#include "base/trace_event/trace_event.h" #include "base/types/pass_key.h" #include "dns_reloader.h" #include "net/base/address_family.h" @@ -36,7 +37,6 @@ #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" diff --git a/naiveproxy/src/net/dns/httpssvc_metrics.h b/naiveproxy/src/net/dns/httpssvc_metrics.h index b6ab55f50c..33a9c3c56a 100644 --- a/naiveproxy/src/net/dns/httpssvc_metrics.h +++ b/naiveproxy/src/net/dns/httpssvc_metrics.h @@ -19,7 +19,7 @@ namespace net { // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. (See HttpssvcDnsRcode in // tools/metrics/histograms/enums.xml.) -enum HttpssvcDnsRcode { +enum class HttpssvcDnsRcode { kTimedOut = 0, kUnrecognizedRcode, kMissingDnsResponse, diff --git a/naiveproxy/src/net/dns/mock_host_resolver.cc b/naiveproxy/src/net/dns/mock_host_resolver.cc index f544d2ba77..847102d0f0 100644 --- a/naiveproxy/src/net/dns/mock_host_resolver.cc +++ b/naiveproxy/src/net/dns/mock_host_resolver.cc @@ -23,7 +23,6 @@ #include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "base/no_destructor.h" #include "base/notimplemented.h" #include "base/notreached.h" #include "base/strings/pattern.h" @@ -187,11 +186,11 @@ class MockHostResolverBase::RequestBase { std::set aliases, std::optional staleness) { DCHECK(!complete_); - DCHECK(!endpoint_results_); + DCHECK(endpoint_results_.empty()); DCHECK(!parameters_.is_speculative); endpoint_results_ = std::move(endpoint_results); - for (auto& result : *endpoint_results_) { + for (auto& result : endpoint_results_) { result.ip_endpoints = FixupEndPoints(result.ip_endpoints); } @@ -199,8 +198,8 @@ class MockHostResolverBase::RequestBase { // `HostResolver` implementations are expected to provide an `AddressList` // result whenever `HostResolverEndpointResult` is also available. - address_results_ = EndpointResultToAddressList( - *endpoint_results_, *fixed_up_dns_alias_results_); + address_results_ = EndpointResultToAddressList(endpoint_results_, + fixed_up_dns_alias_results_); staleness_ = std::move(staleness); @@ -251,9 +250,7 @@ class MockHostResolverBase::RequestBase { // Similar get GetAddressResults() and GetResolveErrorInfo(), but only exposed // through the HostResolver::ResolveHostRequest interface, and don't have the // DCHECKs that `complete_` is true. - const std::optional& address_results() const { - return address_results_; - } + const AddressList& address_results() const { return address_results_; } ResolveErrorInfo resolve_error_info() const { return resolve_error_info_; } protected: @@ -293,9 +290,9 @@ class MockHostResolverBase::RequestBase { RequestPriority priority_; int host_resolver_flags_; - std::optional address_results_; - std::optional> endpoint_results_; - std::optional> fixed_up_dns_alias_results_; + AddressList address_results_; + std::vector endpoint_results_; + std::set fixed_up_dns_alias_results_; std::optional staleness_; ResolveErrorInfo resolve_error_info_; @@ -349,32 +346,30 @@ class MockHostResolverBase::RequestImpl return rv; } - const AddressList* GetAddressResults() const override { + const AddressList& GetAddressResults() const override { DCHECK(complete_); - return base::OptionalToPtr(address_results_); + return address_results_; } - const std::vector* GetEndpointResults() + base::span GetEndpointResults() const override { DCHECK(complete_); - return base::OptionalToPtr(endpoint_results_); + return endpoint_results_; } - const std::vector* GetTextResults() const override { + base::span GetTextResults() const override { DCHECK(complete_); - static const base::NoDestructor> empty_result; - return empty_result.get(); + return {}; } - const std::vector* GetHostnameResults() const override { + base::span GetHostnameResults() const override { DCHECK(complete_); - static const base::NoDestructor> empty_result; - return empty_result.get(); + return {}; } - const std::set* GetDnsAliasResults() const override { + const std::set& GetDnsAliasResults() const override { DCHECK(complete_); - return base::OptionalToPtr(fixed_up_dns_alias_results_); + return fixed_up_dns_alias_results_; } net::ResolveErrorInfo GetResolveErrorInfo() const override { @@ -437,16 +432,12 @@ class MockHostResolverBase::ServiceEndpointRequestImpl return rv; } - const std::vector& GetEndpointResults() override { + base::span GetEndpointResults() override { return service_endpoint_results_; } const std::set& GetDnsAliasResults() override { - if (fixed_up_dns_alias_results_.has_value()) { - return *fixed_up_dns_alias_results_; - } - static const base::NoDestructor> kEmptyDnsAliases; - return *kEmptyDnsAliases.get(); + return fixed_up_dns_alias_results_; } bool EndpointsCryptoReady() override { return true; } @@ -467,12 +458,8 @@ class MockHostResolverBase::ServiceEndpointRequestImpl private: void SetEndpointResultsInternal() override { - if (!endpoint_results_.has_value()) { - return; - } - std::vector service_endpoints; - for (const auto& endpoint : *endpoint_results_) { + for (const auto& endpoint : endpoint_results_) { std::vector ipv4_endpoints; std::vector ipv6_endpoints; for (const auto& ip_endpoint : endpoint.ip_endpoints) { @@ -1586,34 +1573,30 @@ class HangingHostResolver::RequestImpl return ERR_IO_PENDING; } - const AddressList* GetAddressResults() const override { - base::ImmediateCrash(); - } + const AddressList& GetAddressResults() const override { NOTREACHED(); } - const std::vector* GetEndpointResults() + base::span GetEndpointResults() const override { - base::ImmediateCrash(); + NOTREACHED(); } - const std::vector* GetTextResults() const override { - base::ImmediateCrash(); + base::span GetTextResults() const override { + NOTREACHED(); } - const std::vector* GetHostnameResults() const override { - base::ImmediateCrash(); + base::span GetHostnameResults() const override { + NOTREACHED(); } - const std::set* GetDnsAliasResults() const override { - base::ImmediateCrash(); + const std::set& GetDnsAliasResults() const override { + NOTREACHED(); } - net::ResolveErrorInfo GetResolveErrorInfo() const override { - base::ImmediateCrash(); - } + net::ResolveErrorInfo GetResolveErrorInfo() const override { NOTREACHED(); } const std::optional& GetStaleInfo() const override { - base::ImmediateCrash(); + NOTREACHED(); } void ChangeRequestPriority(RequestPriority priority) override {} diff --git a/naiveproxy/src/net/dns/mock_mdns_socket_factory.cc b/naiveproxy/src/net/dns/mock_mdns_socket_factory.cc index 90cd128c0a..a9cb108cbb 100644 --- a/naiveproxy/src/net/dns/mock_mdns_socket_factory.cc +++ b/naiveproxy/src/net/dns/mock_mdns_socket_factory.cc @@ -2,16 +2,12 @@ // 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/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "net/dns/mock_mdns_socket_factory.h" #include #include +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/location.h" @@ -56,7 +52,7 @@ int MockMDnsDatagramServerSocket::HandleRecvNow( CompletionOnceCallback callback) { int size_returned = std::min(response_packet_.size(), static_cast(size)); - memcpy(buffer->data(), response_packet_.data(), size_returned); + UNSAFE_TODO(memcpy(buffer->data(), response_packet_.data(), size_returned)); return size_returned; } @@ -104,7 +100,7 @@ void MockMDnsSocketFactory::SimulateReceive(const uint8_t* packet, int size) { DCHECK(recv_buffer_.get()); DCHECK(!recv_callback_.is_null()); - memcpy(recv_buffer_->data(), packet, size); + UNSAFE_TODO(memcpy(recv_buffer_->data(), packet, size)); std::move(recv_callback_).Run(size); } diff --git a/naiveproxy/src/net/dns/public/host_resolver_source.h b/naiveproxy/src/net/dns/public/host_resolver_source.h index 61161f3b45..c6e908e8ac 100644 --- a/naiveproxy/src/net/dns/public/host_resolver_source.h +++ b/naiveproxy/src/net/dns/public/host_resolver_source.h @@ -48,7 +48,7 @@ base::Value ToValue(HostResolverSource source); std::optional HostResolverSourceFromValue( const base::Value& value); -const HostResolverSource kHostResolverSources[] = { +inline const HostResolverSource kHostResolverSources[] = { HostResolverSource::ANY, HostResolverSource::SYSTEM, HostResolverSource::DNS, HostResolverSource::MULTICAST_DNS, HostResolverSource::LOCAL_ONLY}; diff --git a/naiveproxy/src/net/dns/public/resolv_reader.cc b/naiveproxy/src/net/dns/public/resolv_reader.cc index e393c4ca02..42875701da 100644 --- a/naiveproxy/src/net/dns/public/resolv_reader.cc +++ b/naiveproxy/src/net/dns/public/resolv_reader.cc @@ -33,6 +33,30 @@ std::unique_ptr ResolvReader::GetResState() { return res; } +bool ResolvReader::IsLikelySystemdResolved() { +#if BUILDFLAG(IS_LINUX) + // Look for a single 127.0.0.53:53 nameserver endpoint. The only known + // significant usage of such a configuration is the systemd-resolved local + // resolver, so it is then a fairly safe assumption that any DNS queries to + // the nameserver will be handled by systemd-resolved. + // + // This code path is only reachable if the system has nss-resolve configured + // in nsswitch.conf, which is another indicator that systemd-resolved is + // likely to be in use. + std::unique_ptr res = GetResState(); + if (res) { + std::optional> nameservers = + GetNameservers(res->state()); + if (nameservers) { + return nameservers->size() == 1 && + nameservers->front() == IPEndPoint(IPAddress(127, 0, 0, 53), 53); + } + } +#endif + + return false; +} + std::optional> GetNameservers( const struct __res_state& res) { std::vector nameservers; diff --git a/naiveproxy/src/net/dns/public/resolv_reader.h b/naiveproxy/src/net/dns/public/resolv_reader.h index ec64e265b5..42f87280bf 100644 --- a/naiveproxy/src/net/dns/public/resolv_reader.h +++ b/naiveproxy/src/net/dns/public/resolv_reader.h @@ -25,6 +25,10 @@ class NET_EXPORT ResolvReader { // Null on failure. virtual std::unique_ptr GetResState(); + + // Returns whether or not resolv.conf contains configuration that will forward + // all DNS calls to a local resolver likely using systemd-resolved. + virtual bool IsLikelySystemdResolved(); }; // Returns configured DNS servers or nullopt on failure. diff --git a/naiveproxy/src/net/dns/record_rdata.cc b/naiveproxy/src/net/dns/record_rdata.cc index 8b0e8a3297..037ca9e40f 100644 --- a/naiveproxy/src/net/dns/record_rdata.cc +++ b/naiveproxy/src/net/dns/record_rdata.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 "net/dns/record_rdata.h" #include @@ -14,6 +9,7 @@ #include #include +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/containers/span_reader.h" #include "base/logging.h" @@ -294,8 +290,8 @@ std::unique_ptr NsecRecordRdata::Create( uint8_t length; // Bitmap length in bytes. Between 1 and 32. }; - const BitmapHeader* header = - reinterpret_cast(data.data() + next_domain_length); + const BitmapHeader* header = reinterpret_cast( + UNSAFE_TODO(data.data() + next_domain_length)); // The block number must be zero in mDns-specific NSEC records. The bitmap // length must be between 1 and 32. diff --git a/naiveproxy/src/net/dns/stale_host_resolver.cc b/naiveproxy/src/net/dns/stale_host_resolver.cc index 2cf80d7395..18ac206e6b 100644 --- a/naiveproxy/src/net/dns/stale_host_resolver.cc +++ b/naiveproxy/src/net/dns/stale_host_resolver.cc @@ -47,11 +47,12 @@ class StaleHostResolver::RequestImpl : public HostResolver::ResolveHostRequest { // HostResolver::ResolveHostRequest implementation: int Start(CompletionOnceCallback result_callback) override; - const AddressList* GetAddressResults() const override; - const HostResolverEndpointResults* GetEndpointResults() const override; - const std::vector* GetTextResults() const override; - const std::vector* GetHostnameResults() const override; - const std::set* GetDnsAliasResults() const override; + const AddressList& GetAddressResults() const override; + base::span GetEndpointResults() + const override; + base::span GetTextResults() const override; + base::span GetHostnameResults() const override; + const std::set& GetDnsAliasResults() const override; ResolveErrorInfo GetResolveErrorInfo() const override; const std::optional& GetStaleInfo() const override; void ChangeRequestPriority(RequestPriority priority) override; @@ -177,7 +178,7 @@ int StaleHostResolver::RequestImpl::Start( return network_rv; } -const AddressList* StaleHostResolver::RequestImpl::GetAddressResults() const { +const AddressList& StaleHostResolver::RequestImpl::GetAddressResults() const { if (network_request_) { return network_request_->GetAddressResults(); } @@ -186,7 +187,7 @@ const AddressList* StaleHostResolver::RequestImpl::GetAddressResults() const { return cache_request_->GetAddressResults(); } -const HostResolverEndpointResults* +base::span StaleHostResolver::RequestImpl::GetEndpointResults() const { if (network_request_) { return network_request_->GetEndpointResults(); @@ -196,7 +197,7 @@ StaleHostResolver::RequestImpl::GetEndpointResults() const { return cache_request_->GetEndpointResults(); } -const std::vector* StaleHostResolver::RequestImpl::GetTextResults() +base::span StaleHostResolver::RequestImpl::GetTextResults() const { if (network_request_) { return network_request_->GetTextResults(); @@ -206,7 +207,7 @@ const std::vector* StaleHostResolver::RequestImpl::GetTextResults() return cache_request_->GetTextResults(); } -const std::vector* +base::span StaleHostResolver::RequestImpl::GetHostnameResults() const { if (network_request_) { return network_request_->GetHostnameResults(); @@ -216,7 +217,7 @@ StaleHostResolver::RequestImpl::GetHostnameResults() const { return cache_request_->GetHostnameResults(); } -const std::set* +const std::set& StaleHostResolver::RequestImpl::GetDnsAliasResults() const { if (network_request_) { return network_request_->GetDnsAliasResults(); diff --git a/naiveproxy/src/net/extras/preload_data/decoder.cc b/naiveproxy/src/net/extras/preload_data/decoder.cc index 996c3f1e0e..fc415ca72a 100644 --- a/naiveproxy/src/net/extras/preload_data/decoder.cc +++ b/naiveproxy/src/net/extras/preload_data/decoder.cc @@ -2,13 +2,10 @@ // 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 "net/extras/preload_data/decoder.h" + #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/notreached.h" namespace net::extras { @@ -23,7 +20,7 @@ bool PreloadDecoder::BitReader::Next(bool* out) { if (current_byte_index_ >= num_bytes_) { return false; } - current_byte_ = bytes_[current_byte_index_++]; + current_byte_ = UNSAFE_TODO(bytes_[current_byte_index_++]); num_bits_used_ = 0; } @@ -140,7 +137,7 @@ bool PreloadDecoder::BitReader::Seek(size_t offset) { return false; } current_byte_index_ = offset / 8; - current_byte_ = bytes_[current_byte_index_++]; + current_byte_ = UNSAFE_TODO(bytes_[current_byte_index_++]); num_bits_used_ = offset % 8; return true; } @@ -151,7 +148,7 @@ PreloadDecoder::HuffmanDecoder::HuffmanDecoder(const uint8_t* tree, bool PreloadDecoder::HuffmanDecoder::Decode(PreloadDecoder::BitReader* reader, char* out) const { - const uint8_t* current = &tree_[tree_bytes_ - 2]; + const uint8_t* current = UNSAFE_TODO(&tree_[tree_bytes_ - 2]); for (;;) { bool bit; @@ -159,7 +156,7 @@ bool PreloadDecoder::HuffmanDecoder::Decode(PreloadDecoder::BitReader* reader, return false; } - uint8_t b = current[bit]; + uint8_t b = UNSAFE_TODO(current[bit]); if (b & 0x80) { *out = static_cast(b & 0x7f); return true; @@ -171,7 +168,7 @@ bool PreloadDecoder::HuffmanDecoder::Decode(PreloadDecoder::BitReader* reader, return false; } - current = &tree_[offset]; + current = UNSAFE_TODO(&tree_[offset]); } } @@ -184,6 +181,16 @@ PreloadDecoder::PreloadDecoder(const uint8_t* huffman_tree, bit_reader_(trie, trie_bits), trie_root_position_(trie_root_position) {} +PreloadDecoder::PreloadDecoder(base::span huffman_tree, + base::span trie, + size_t trie_bits, + size_t trie_root_position) + : huffman_decoder_(huffman_tree.data(), huffman_tree.size()), + bit_reader_(trie.data(), trie_bits), + trie_root_position_(trie_root_position) { + CHECK_LE((trie_bits + 7) / 8, trie.size()); +} + PreloadDecoder::~PreloadDecoder() = default; bool PreloadDecoder::Decode(const std::string& search, bool* out_found) { diff --git a/naiveproxy/src/net/extras/preload_data/decoder.h b/naiveproxy/src/net/extras/preload_data/decoder.h index 934fee37f9..bdfddf5046 100644 --- a/naiveproxy/src/net/extras/preload_data/decoder.h +++ b/naiveproxy/src/net/extras/preload_data/decoder.h @@ -9,6 +9,7 @@ #include +#include "base/containers/span.h" #include "base/memory/raw_ptr.h" namespace net::extras { @@ -115,6 +116,11 @@ class PreloadDecoder { size_t trie_bits, size_t trie_root_position); + PreloadDecoder(base::span huffman_tree, + base::span trie, + size_t trie_bits, + size_t trie_root_position); + PreloadDecoder(const PreloadDecoder&) = delete; PreloadDecoder& operator=(const PreloadDecoder&) = delete; diff --git a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_cookie_store.cc b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_cookie_store.cc index 55f44d52ef..05bfa24c32 100644 --- a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_cookie_store.cc +++ b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_cookie_store.cc @@ -960,13 +960,32 @@ bool SQLitePersistentCookieStore::Backend::LoadCookiesForDomains( } delete_statement.Assign(db()->GetCachedStatement( SQL_FROM_HERE, "DELETE FROM cookies WHERE host_key = ?")); - if (!smt.is_valid() || !delete_statement.is_valid()) { + + sql::Statement delete_insecure_prefixed_statement; + delete_insecure_prefixed_statement.Assign(db()->GetCachedStatement( + SQL_FROM_HERE, + "DELETE FROM cookies WHERE " + "(LOWER(name) LIKE '__host-http-%' OR LOWER(name) LIKE '__http-%') " + "AND (is_httponly = 0 OR is_secure = 0)")); + + if (!smt.is_valid() || !delete_statement.is_valid() || + !delete_insecure_prefixed_statement.is_valid()) { delete_statement.Clear(); + delete_insecure_prefixed_statement.Clear(); smt.Clear(); // Disconnect smt_ref from db_. Reset(); return false; } + // Delete cookies with __host-http- or __http- prefixes that are not httponly + // These cookies are potentially insecure and should be removed. + // Do this BEFORE loading cookies to ensure deleted cookies don't get loaded. + if (!delete_insecure_prefixed_statement.Run()) { + // Log the failure but don't treat it as fatal since this is a cleanup + // operation + RecordCookieLoadProblem(CookieLoadProblem::KRecoveryFailed); + } + std::vector> cookies; std::unordered_set top_frame_site_keys_to_delete; auto it = domains.begin(); @@ -1037,16 +1056,11 @@ bool SQLitePersistentCookieStore::Backend::MakeCookiesFromSQLStatement( UMA_HISTOGRAM_BOOLEAN("Cookie.EncryptedAndPlaintextValues", encrypted_and_plaintext_values); - // Ensure feature is fully activated for all users who load cookies, before - // checking the validity of the row. - if (base::FeatureList::IsEnabled( - features::kEncryptedAndPlaintextValuesAreInvalid)) { - if (encrypted_and_plaintext_values) { - RecordCookieLoadProblem( - CookieLoadProblem::kValuesExistInBothEncryptedAndPlaintext); - ok = false; - continue; - } + if (encrypted_and_plaintext_values) { + RecordCookieLoadProblem( + CookieLoadProblem::kValuesExistInBothEncryptedAndPlaintext); + ok = false; + continue; } if (!encrypted_value.empty()) { diff --git a/naiveproxy/src/net/features.gni b/naiveproxy/src/net/features.gni index 4b3f35f06a..654a167283 100644 --- a/naiveproxy/src/net/features.gni +++ b/naiveproxy/src/net/features.gni @@ -2,8 +2,10 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chrome_build.gni") import("//build/config/cronet/config.gni") import("//build/config/features.gni") +import("//extensions/buildflags/buildflags.gni") declare_args() { # Disables support for file URLs. File URL support requires use of icu. @@ -27,8 +29,9 @@ declare_args() { # TODO: https://crbug.com/40282397 - Consider dropping once Cronet default enables zstd. disable_zstd_filter = false - # Multicast DNS. - enable_mdns = is_win || is_linux || is_chromeos || is_fuchsia || is_apple + # Multicast DNS. Enabled on desktop Android for the chrome.mdns extension API. + enable_mdns = is_win || is_linux || is_chromeos || is_fuchsia || is_apple || + enable_desktop_android_extensions # Reporting not used on iOS. enable_reporting = !is_ios diff --git a/naiveproxy/src/net/filter/filter_source_stream.cc b/naiveproxy/src/net/filter/filter_source_stream.cc index 5fbbea0f88..076141503b 100644 --- a/naiveproxy/src/net/filter/filter_source_stream.cc +++ b/naiveproxy/src/net/filter/filter_source_stream.cc @@ -15,10 +15,10 @@ #include "base/notreached.h" #include "base/numerics/safe_conversions.h" #include "base/strings/string_util.h" +#include "base/trace_event/trace_event.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/base/trace_constants.h" -#include "net/base/tracing.h" #include "net/filter/brotli_source_stream.h" #include "net/filter/filter_source_stream.h" #include "net/filter/gzip_source_stream.h" diff --git a/naiveproxy/src/net/first_party_sets/first_party_sets_cache_filter.cc b/naiveproxy/src/net/first_party_sets/first_party_sets_cache_filter.cc index 30fef2b8a7..7d5c239aaa 100644 --- a/naiveproxy/src/net/first_party_sets/first_party_sets_cache_filter.cc +++ b/naiveproxy/src/net/first_party_sets/first_party_sets_cache_filter.cc @@ -4,6 +4,8 @@ #include "net/first_party_sets/first_party_sets_cache_filter.h" +#include "base/containers/map_util.h" + namespace net { FirstPartySetsCacheFilter::MatchInfo::MatchInfo() = default; @@ -43,8 +45,9 @@ FirstPartySetsCacheFilter::MatchInfo FirstPartySetsCacheFilter::GetMatchInfo( FirstPartySetsCacheFilter::MatchInfo res; if (browser_run_id_ > 0) { res.browser_run_id = browser_run_id_; - if (const auto it = filter_.find(site); it != filter_.end()) - res.clear_at_run_id = it->second; + if (const int64_t* run_id = base::FindOrNull(filter_, site); run_id) { + res.clear_at_run_id = *run_id; + } } return res; } diff --git a/naiveproxy/src/net/first_party_sets/first_party_sets_context_config.cc b/naiveproxy/src/net/first_party_sets/first_party_sets_context_config.cc index e2f9adbef3..6d69aa720e 100644 --- a/naiveproxy/src/net/first_party_sets/first_party_sets_context_config.cc +++ b/naiveproxy/src/net/first_party_sets/first_party_sets_context_config.cc @@ -5,6 +5,7 @@ #include "net/first_party_sets/first_party_sets_context_config.h" #include "base/containers/map_util.h" +#include "base/types/optional_util.h" #include "net/first_party_sets/first_party_set_entry_override.h" namespace net { @@ -65,10 +66,7 @@ bool FirstPartySetsContextConfig::operator==( std::optional FirstPartySetsContextConfig::FindOverride(const SchemefulSite& site) const { - if (const auto it = customizations_.find(site); it != customizations_.end()) { - return it->second; - } - return std::nullopt; + return base::OptionalFromPtr(base::FindOrNull(customizations_, site)); } bool FirstPartySetsContextConfig::Contains(const SchemefulSite& site) const { 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 index 917c6eaa7a..8d9df42293 100644 --- a/naiveproxy/src/net/first_party_sets/first_party_sets_validator.cc +++ b/naiveproxy/src/net/first_party_sets/first_party_sets_validator.cc @@ -50,8 +50,8 @@ bool FirstPartySetsValidator::IsSiteValid(const SchemefulSite& site) const { bool FirstPartySetsValidator::IsSitePrimaryValid( const SchemefulSite& primary) const { - const auto it = primary_states_.find(primary); - return it != primary_states_.end() && it->second.IsValid(); + const PrimarySiteState* state = base::FindOrNull(primary_states_, primary); + return state && state->IsValid(); } bool FirstPartySetsValidator::PrimarySiteState::IsValid() const { 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 c0fa9a90dc..d7869e0803 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 @@ -18,6 +18,7 @@ #include "base/containers/map_util.h" #include "base/functional/function_ref.h" #include "base/types/optional_ref.h" +#include "base/types/optional_util.h" #include "net/base/schemeful_site.h" #include "net/first_party_sets/addition_overlaps_union_find.h" #include "net/first_party_sets/first_party_set_entry.h" @@ -132,15 +133,7 @@ std::optional GlobalFirstPartySets::FindEntry( } // Finally, look up in `entries_`, applying an alias if applicable. - const auto canonical_it = aliases_.find(site); - const SchemefulSite& canonical_site = - canonical_it == aliases_.end() ? site : canonical_it->second; - if (const auto entry_it = entries_.find(canonical_site); - entry_it != entries_.end()) { - return entry_it->second; - } - - return std::nullopt; + return base::OptionalFromPtr(base::FindOrNull(entries_, ResolveAlias(site))); } base::flat_map @@ -212,10 +205,6 @@ GlobalFirstPartySets::FindPrimariesAffectedByReplacements( 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); @@ -223,15 +212,14 @@ GlobalFirstPartySets::FindPrimariesAffectedByReplacements( // 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)]( + [this, canonical_to_aliases = std::move(canonical_to_aliases)]( const SchemefulSite& site, const base::FunctionRef f) { - const SchemefulSite canonical = canonicalize(site); + const SchemefulSite& canonical = ResolveAlias(site); f(canonical); - if (const auto it = canonical_to_aliases.find(canonical); - it != canonical_to_aliases.end()) { - for (const auto& alias : it->second) { + if (const std::set* aliases = + base::FindOrNull(canonical_to_aliases, canonical)) { + for (const auto& alias : *aliases) { f(alias); } } @@ -316,25 +304,25 @@ FirstPartySetsContextConfig GlobalFirstPartySets::ComputeConfig( /*config=*/std::nullopt, [&](const SchemefulSite& member, const FirstPartySetEntry& set_entry) { // Reparent all sites in any intersecting addition sets. - if (const auto entry = - addition_intersected_primaries.find(set_entry.primary()); - entry != addition_intersected_primaries.end() && - !replacements.contains(member)) { + if (const FirstPartySetEntry* entry = base::FindOrNull( + addition_intersected_primaries, set_entry.primary()); + entry && !replacements.contains(member)) { site_to_override.emplace_back( - member, FirstPartySetEntry(entry->second.primary(), - member == entry->second.primary() + member, FirstPartySetEntry(entry->primary(), + member == entry->primary() ? SiteType::kPrimary : SiteType::kAssociated)); } if (member == set_entry.primary()) return true; // Remove non-singletons from the potential list. - if (const auto entry = potential_singletons.find(set_entry.primary()); - entry != potential_singletons.end() && - !entry->second.contains(member)) { + if (const auto singletons_it = + potential_singletons.find(set_entry.primary()); + singletons_it != potential_singletons.end() && + !singletons_it->second.contains(member)) { // This primary lost members, but it still has at least one // (`member`), so it's not a singleton. - potential_singletons.erase(entry); + potential_singletons.erase(singletons_it); } // Remove members from sets whose primary left. if (replaced_existing_primaries.contains(set_entry.primary()) && @@ -448,10 +436,11 @@ bool GlobalFirstPartySets::ForEachPublicSetEntry( return false; } for (const auto& [alias, canonical] : aliases_) { - auto it = entries_.find(canonical); - CHECK(it != entries_.end()); - if (!f(alias, it->second)) + const FirstPartySetEntry* entry = base::FindOrNull(entries_, canonical); + CHECK(entry); + if (!f(alias, *entry)) { return false; + } } return true; } @@ -532,6 +521,12 @@ bool GlobalFirstPartySets::IsValid( return validator.IsValid(); } +const SchemefulSite& GlobalFirstPartySets::ResolveAlias( + const SchemefulSite& site) const { + const SchemefulSite* canonical = base::FindOrNull(aliases_, site); + return canonical ? *canonical : site; +} + std::ostream& operator<<(std::ostream& os, const GlobalFirstPartySets& sets) { os << "{entries = {"; for (const auto& [site, entry] : sets.entries_) { @@ -543,7 +538,7 @@ std::ostream& operator<<(std::ostream& os, const GlobalFirstPartySets& sets) { } os << "}, manual_config = {"; sets.ForEachManualConfigEntry( - [&](const net::SchemefulSite& site, + [&](const SchemefulSite& site, const FirstPartySetEntryOverride& override) { os << "{" << site.Serialize() << ": " << override << "},"; return true; 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 0e527d627f..caaa6b724b 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 @@ -198,6 +198,12 @@ class NET_EXPORT GlobalFirstPartySets { bool IsValid(base::optional_ref config = std::nullopt) const; + // Resolves an alias site into the canonical representative site, if possible. + // The returned reference's lifetime is the *minimum* of the lifetimes of + // `site` and `this`. + const SchemefulSite& ResolveAlias(const SchemefulSite& site) const + LIFETIME_BOUND; + // The version associated with the component_updater-provided public sets. // This may be invalid if the "First-Party Sets" component has not been // installed yet, or has been corrupted. Entries and aliases from invalid diff --git a/naiveproxy/src/net/first_party_sets/local_set_declaration.cc b/naiveproxy/src/net/first_party_sets/local_set_declaration.cc index e1b646df8a..9f1f1f663b 100644 --- a/naiveproxy/src/net/first_party_sets/local_set_declaration.cc +++ b/naiveproxy/src/net/first_party_sets/local_set_declaration.cc @@ -8,6 +8,7 @@ #include #include "base/containers/contains.h" +#include "base/containers/map_util.h" #include "base/logging.h" #include "net/base/schemeful_site.h" #include "net/first_party_sets/first_party_set_entry.h" @@ -107,7 +108,9 @@ SetsMutation LocalSetDeclaration::ComputeMutation() const { base::flat_map entries = entries_; for (const auto& [alias, canonical] : aliases_) { - entries.emplace(alias, entries.find(canonical)->second); + // Note: it's safe to dereference the pointer below due to the checks in + // `CheckPreconditions`. + entries.emplace(alias, *base::FindOrNull(entries, canonical)); } // A local set declaration is treated as a "replacement" set. return SetsMutation(/*replacement_sets=*/{std::move(entries)}, diff --git a/naiveproxy/src/net/http/alternative_service.h b/naiveproxy/src/net/http/alternative_service.h index 661d43918c..ea83f82c08 100644 --- a/naiveproxy/src/net/http/alternative_service.h +++ b/naiveproxy/src/net/http/alternative_service.h @@ -124,9 +124,7 @@ class NET_EXPORT_PRIVATE AlternativeServiceInfo { void set_port(uint16_t port) { alternative_service_.port = port; } - void set_expiration(const base::Time& expiration) { - expiration_ = expiration; - } + void set_expiration(base::Time expiration) { expiration_ = expiration; } // Sets the advertised versions for QUIC alternative services to a sorted copy // of `advertised_versions`. diff --git a/naiveproxy/src/net/http/bidirectional_stream.cc b/naiveproxy/src/net/http/bidirectional_stream.cc index 0a99fd3b74..c4cf85d4d1 100644 --- a/naiveproxy/src/net/http/bidirectional_stream.cc +++ b/naiveproxy/src/net/http/bidirectional_stream.cc @@ -211,7 +211,7 @@ void BidirectionalStream::StartRequest() { stream_request_ = session_->http_stream_factory()->RequestBidirectionalStreamImpl( http_request_info, request_info_->priority, /*allowed_bad_certs=*/{}, - this, /* enable_ip_based_pooling = */ true, + this, /* enable_ip_based_pooling_for_h2 = */ true, /* enable_alternative_services = */ true, net_log_); // Check that this call does not fail. DCHECK(stream_request_); diff --git a/naiveproxy/src/net/http/http_auth_handler_negotiate.cc b/naiveproxy/src/net/http/http_auth_handler_negotiate.cc index 86d8d7949c..54e01280a1 100644 --- a/naiveproxy/src/net/http/http_auth_handler_negotiate.cc +++ b/naiveproxy/src/net/http/http_auth_handler_negotiate.cc @@ -365,10 +365,9 @@ int HttpAuthHandlerNegotiate::DoResolveCanonicalNameComplete(int rv) { // Expect at most a single DNS alias representing the canonical name // because the `HostResolver` request was made with // `include_canonical_name`. - DCHECK(resolve_host_request_->GetDnsAliasResults()); - DCHECK_LE(resolve_host_request_->GetDnsAliasResults()->size(), 1u); - if (!resolve_host_request_->GetDnsAliasResults()->empty()) { - server = *resolve_host_request_->GetDnsAliasResults()->begin(); + DCHECK_LE(resolve_host_request_->GetDnsAliasResults().size(), 1u); + if (!resolve_host_request_->GetDnsAliasResults().empty()) { + server = *resolve_host_request_->GetDnsAliasResults().begin(); DCHECK(!server.empty()); } } else { diff --git a/naiveproxy/src/net/http/http_cache.cc b/naiveproxy/src/net/http/http_cache.cc index 85d077bafd..ffef1f51c8 100644 --- a/naiveproxy/src/net/http/http_cache.cc +++ b/naiveproxy/src/net/http/http_cache.cc @@ -537,6 +537,25 @@ void HttpCache::OnExternalCacheHit( } } + OnExternalCacheHitForRequest(request_info); + + if (no_vary_search_cache_ && + features::kHttpCacheNoVarySearchApplyToExternalHits.Get()) { + auto result = no_vary_search_cache_->Lookup(request_info); + if (result) { + // Do this in addition to, rather than instead of, the URL passed to the + // function. If both exist in the cache, then we may need to fall back to + // the supplied URL in some cases so it is useful to keep it fresh. The + // version of the URL from the NoVarySearchCache is touched second so that + // it is slightly fresher and so less likely to be evicted. + request_info.url = result->original_url; + OnExternalCacheHitForRequest(request_info); + } + } +} + +void HttpCache::OnExternalCacheHitForRequest( + const HttpRequestInfo& request_info) { std::optional key = GenerateCacheKeyForRequest(&request_info); if (!key) { return; diff --git a/naiveproxy/src/net/http/http_cache.h b/naiveproxy/src/net/http/http_cache.h index 6ca9c1a636..a60ac8aa02 100644 --- a/naiveproxy/src/net/http/http_cache.h +++ b/naiveproxy/src/net/http/http_cache.h @@ -539,6 +539,10 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory { bool is_shared_resource, std::optional initiator); + // Generates a cache key for `request_info` and informs the backend it should + // consider it used if it exists. + void OnExternalCacheHitForRequest(const HttpRequestInfo& request_info); + // Creates a WorkItem and sets it as the |pending_op|'s writer, or adds it to // the queue if a writer already exists. Error CreateAndSetWorkItem(scoped_refptr* entry, diff --git a/naiveproxy/src/net/http/http_cache_transaction.cc b/naiveproxy/src/net/http/http_cache_transaction.cc index 8632177697..369ec46120 100644 --- a/naiveproxy/src/net/http/http_cache_transaction.cc +++ b/naiveproxy/src/net/http/http_cache_transaction.cc @@ -39,6 +39,7 @@ #include "base/time/clock.h" #include "base/time/time.h" #include "base/trace_event/common/trace_event_common.h" +#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_id_helper.h" #include "base/values.h" #include "net/base/auth.h" @@ -46,8 +47,8 @@ #include "net/base/load_flags.h" #include "net/base/load_timing_info.h" #include "net/base/net_errors.h" +#include "net/base/task/task_runner.h" #include "net/base/trace_constants.h" -#include "net/base/tracing.h" #include "net/base/transport_info.h" #include "net/base/upload_data_stream.h" #include "net/cert/cert_status_flags.h" @@ -109,6 +110,14 @@ bool MethodUsesNoVarySearch(const std::string& method) { return method == "GET" || method == "HEAD"; } +const scoped_refptr& TaskRunner( + net::RequestPriority priority) { + if (features::kNetTaskSchedulerHttpCacheTransaction.Get()) { + return net::GetTaskRunner(priority); + } + return base::SingleThreadTaskRunner::GetCurrentDefault(); +} + } // namespace #define CACHE_STATUS_HISTOGRAMS(type) \ @@ -303,7 +312,7 @@ int HttpCache::Transaction::Read(IOBuffer* buf, // user wishes to read the network response (the error page). If there is a // previous response in the cache then we should leave it intact. if (auth_response_.headers.get() && mode_ != NONE) { - UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER); + UpdateCacheEntryStatusToOther(OtherStatusReason::kReadingAuthResponse); DCHECK(mode_ & WRITE); bool stopped = StopCachingImpl(mode_ == READ_WRITE); DCHECK(stopped); @@ -1043,6 +1052,7 @@ int HttpCache::Transaction::DoGetBackendComplete(int result) { } else if (effective_load_flags_ & LOAD_BYPASS_CACHE) { mode_ = WRITE; } else { + CHECK(!done_headers_create_new_entry_); mode_ = READ_WRITE; } @@ -1121,6 +1131,20 @@ int HttpCache::Transaction::DoInitEntry() { if ((mode_ & READ_META) && read_no_vary_search_cache_ && IsNoVarySearchApplicable()) { no_vary_search_use_result_ = LookupRequestInNoVarySearchCache(); + if (no_vary_search_use_result_ == NoVarySearchUseResult::kUsed && + first_nvs_cache_lookup_end_time_.is_null()) { + first_nvs_cache_lookup_end_time_ = base::TimeTicks::Now(); + } + } else if (!first_nvs_cache_lookup_end_time_.is_null() && + no_vary_search_use_result_ != NoVarySearchUseResult::kUsed) { + // A NoVarySearchCache lookup succeeded earlier for this transaction, but + // then for some reason the result was unusable. Record the time lost as a + // result. See the histogram "HttpCache.NoVarySearch.UseResult" for + // information about what went wrong. + base::UmaHistogramTimes( + "HttpCache.NoVarySearch.NotUsableLostTime2", + base::TimeTicks::Now() - first_nvs_cache_lookup_end_time_); + first_nvs_cache_lookup_end_time_ = base::TimeTicks(); } TransitionToState(STATE_OPEN_OR_CREATE_ENTRY); @@ -1187,6 +1211,8 @@ int HttpCache::Transaction::DoOpenOrCreateEntry() { // READ_WRITE). // READ, UPDATE, certain READ_WRITEs, and some methods shouldn't create, so // try only opening. + CHECK_NE(mode_, NONE); + CHECK_NE(mode_, WRITE); if (mode_ != READ_WRITE || ShouldOpenOnlyMethods()) { if (entry_not_suitable) { // The entry isn't suitable and we can't create a new one. @@ -1413,7 +1439,7 @@ int HttpCache::Transaction::DoAddToEntry() { // first transaction of that new entry and thus it will not have cache lock // delays, thus returning early from here. if (done_headers_create_new_entry_) { - DCHECK_EQ(mode_, WRITE); + CHECK_EQ(mode_, WRITE); TransitionToState(STATE_DONE_HEADERS_ADD_TO_ENTRY_COMPLETE); return rv; } @@ -1441,7 +1467,7 @@ void HttpCache::Transaction::AddCacheLockTimeoutHandler(ActiveEntry* entry) { if ((bypass_lock_for_test_ && next_state_ == STATE_ADD_TO_ENTRY_COMPLETE) || (bypass_lock_after_headers_for_test_ && next_state_ == STATE_FINISH_HEADERS_COMPLETE)) { - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + TaskRunner(priority_)->PostTask( FROM_HERE, base::BindOnce(&HttpCache::Transaction::OnCacheLockTimeout, weak_factory_.GetWeakPtr(), entry_lock_waiting_since_)); @@ -1468,7 +1494,7 @@ void HttpCache::Transaction::AddCacheLockTimeoutHandler(ActiveEntry* entry) { // the cache if at all possible. See http://crbug.com/408765 timeout_milliseconds = 25; } - base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask( + TaskRunner(priority_)->PostDelayedTask( FROM_HERE, base::BindOnce(&HttpCache::Transaction::OnCacheLockTimeout, weak_factory_.GetWeakPtr(), entry_lock_waiting_since_), @@ -1907,7 +1933,7 @@ int HttpCache::Transaction::DoSendRequestComplete(int result) { response_.resolve_error_info = response->resolve_error_info; // Do not record requests that have network errors or restarts. - UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER); + UpdateCacheEntryStatusToOther(OtherStatusReason::kNetworkError); if (IsCertificateError(result)) { // If we get a certificate error, then there is a certificate in ssl_info, // so GetResponseInfo() should never return NULL here. @@ -1975,7 +2001,7 @@ int HttpCache::Transaction::DoSuccessfulSendRequest() { // happening if the user cancels the authentication before we receive // the new response. net_log_.AddEvent(NetLogEventType::HTTP_CACHE_RE_SEND_PARTIAL_REQUEST); - UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER); + UpdateCacheEntryStatusToOther(OtherStatusReason::kResponseValidation); SetResponse(HttpResponseInfo()); ResetNetworkTransaction(); new_response_ = nullptr; @@ -1986,7 +2012,7 @@ int HttpCache::Transaction::DoSuccessfulSendRequest() { if (handling_206_ && mode_ == READ_WRITE && !truncated_ && !is_sparse_) { // We have stored the full entry, but it changed and the server is // sending a range. We have to delete the old entry. - UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER); + UpdateCacheEntryStatusToOther(OtherStatusReason::kDeleteFullEntry); DoneWithEntry(false); } @@ -2512,7 +2538,7 @@ int HttpCache::Transaction::DoCacheReadDataComplete(int result) { if (partial_) { // Partial requests are confusing to report in histograms because they may // have multiple underlying requests. - UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER); + UpdateCacheEntryStatusToOther(OtherStatusReason::kPartialRequest); return DoPartialCacheReadCompleted(result); } @@ -2596,7 +2622,7 @@ void HttpCache::Transaction::SetRequest(const NetLogWithSource& net_log) { } if (range_found && !(effective_load_flags_ & LOAD_DISABLE_CACHE)) { - UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER); + UpdateCacheEntryStatusToOther(OtherStatusReason::kRangeHeaderFound); partial_ = std::make_unique(); if (method_ == "GET" && partial_->Init(request_->extra_headers)) { // We will be modifying the actual range requested to the server, so @@ -2730,7 +2756,7 @@ int HttpCache::Transaction::BeginCacheValidation() { if (truncated_) { // Truncated entries can cause partial gets, so we shouldn't record this // load in histograms. - UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER); + UpdateCacheEntryStatusToOther(OtherStatusReason::kTruncatedEntry); skip_validation = !partial_->initial_validation(); } @@ -2803,7 +2829,7 @@ int HttpCache::Transaction::BeginPartialCacheValidation() { } // Partial requests should not be recorded in histograms. - UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER); + UpdateCacheEntryStatusToOther(OtherStatusReason::kPartialValidation); if (method_ == "HEAD") { return BeginCacheValidation(); } @@ -2851,7 +2877,7 @@ int HttpCache::Transaction::BeginExternallyConditionalizedRequest() { !external_validation_->Match(*response_.headers)) { // The externally conditionalized request is not a validation request // for our existing cache entry. Proceed with caching disabled. - UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER); + UpdateCacheEntryStatusToOther(OtherStatusReason::kPreConditionalized); DoneWithEntry(true); } @@ -3052,11 +3078,12 @@ bool HttpCache::Transaction::ConditionalizeRequest() { return true; } -bool HttpCache::Transaction::MaybeRejectBasedOnEntryInMemoryData( +HttpCache::Transaction::HttpCacheEntryRejectionStatus +HttpCache::Transaction::GetHttpCacheEntryRejectionStatus( uint8_t in_memory_info) { // Not going to be clever with those... if (partial_) { - return false; + return HttpCacheEntryRejectionStatus::kNoRejectionPartial; } // Avoiding open based on in-memory hints requires us to be permitted to @@ -3065,19 +3092,33 @@ bool HttpCache::Transaction::MaybeRejectBasedOnEntryInMemoryData( // first place, so we shouldn't see it here. DCHECK_NE(mode_, WRITE); if (mode_ != READ_WRITE) { - return false; + return HttpCacheEntryRejectionStatus::kNoRejectionNonReadWriteMode; } // If we are loading ignoring cache validity (aka back button), obviously // can't reject things based on it. Also if LOAD_ONLY_FROM_CACHE there is no // hope of network offering anything better. - if (effective_load_flags_ & LOAD_SKIP_CACHE_VALIDATION || - effective_load_flags_ & LOAD_ONLY_FROM_CACHE) { - return false; + if (effective_load_flags_ & LOAD_SKIP_CACHE_VALIDATION) { + return HttpCacheEntryRejectionStatus::kNoRejectionSkipCacheValidation; + } + + if (effective_load_flags_ & LOAD_ONLY_FROM_CACHE) { + return HttpCacheEntryRejectionStatus::kNoRejectionLoadOnlyFromCache; } return (in_memory_info & HINT_UNUSABLE_PER_CACHING_HEADERS) == - HINT_UNUSABLE_PER_CACHING_HEADERS; + HINT_UNUSABLE_PER_CACHING_HEADERS + ? HttpCacheEntryRejectionStatus::kRejection + : HttpCacheEntryRejectionStatus::kNoRejectionUsable; +} + +bool HttpCache::Transaction::MaybeRejectBasedOnEntryInMemoryData( + uint8_t in_memory_info) { + HttpCacheEntryRejectionStatus status = + GetHttpCacheEntryRejectionStatus(in_memory_info); + base::UmaHistogramEnumeration("HttpCache.EntryRejectionStatus", status); + + return status == HttpCacheEntryRejectionStatus::kRejection; } bool HttpCache::Transaction::ComputeUnusablePerCachingHeaders() { @@ -3218,7 +3259,7 @@ bool HttpCache::Transaction::ValidatePartialResponse() { if (failure) { // We cannot truncate this entry, it has to be deleted. - UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER); + UpdateCacheEntryStatusToOther(OtherStatusReason::kValidatePartial); mode_ = NONE; if (is_sparse_ || truncated_) { // There was something cached to start with, either sparsed data (206), or @@ -3246,7 +3287,7 @@ void HttpCache::Transaction::IgnoreRangeRequest() { // returned the headers), but we'll just pretend that this request is not // using the cache and see what happens. Most likely this is the first // response from the server (it's not changing its mind midway, right?). - UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER); + UpdateCacheEntryStatusToOther(OtherStatusReason::kIgnoreRangeRequest); DoneWithEntry(mode_ != WRITE); partial_.reset(nullptr); } @@ -3273,7 +3314,7 @@ int HttpCache::Transaction::DoConnectedCallbackComplete(int result) { if (result == ERR_CACHED_IP_ADDRESS_SPACE_BLOCKED_BY_PRIVATE_NETWORK_ACCESS_POLICY) { DoomInconsistentEntry(); - UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER); + UpdateCacheEntryStatusToOther(OtherStatusReason::kBlockedByIpSpace); TransitionToState(reading_ ? STATE_SEND_REQUEST : STATE_HEADERS_PHASE_CANNOT_PROCEED); return OK; @@ -3716,6 +3757,15 @@ void HttpCache::Transaction::UpdateCacheEntryStatus( SyncCacheEntryStatusToResponse(); } +void HttpCache::Transaction::UpdateCacheEntryStatusToOther( + OtherStatusReason reason) { + if (cache_entry_status_ == CacheEntryStatus::ENTRY_OTHER) { + return; + } + other_status_reason_ = reason; + UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER); +} + void HttpCache::Transaction::SyncCacheEntryStatusToResponse() { if (cache_entry_status_ == CacheEntryStatus::ENTRY_UNDEFINED) { return; @@ -3754,15 +3804,16 @@ void HttpCache::Transaction::RecordHistograms() { HttpResponseHeaders* response_headers = GetResponseInfo()->headers.get(); const bool is_no_store = response_headers && response_headers->HasHeaderValue( "cache-control", "no-store"); + bool is_html = false; if (response_headers && response_headers->GetMimeType(&mime_type)) { // Record the cache pattern by resource type. The type is inferred by // response header mime type, which could be incorrect, so this is just an // estimate. - if (mime_type == "text/html" && - (effective_load_flags_ & LOAD_MAIN_FRAME_DEPRECATED)) { + is_html = (mime_type == "text/html"); + if (is_html && (effective_load_flags_ & LOAD_MAIN_FRAME_DEPRECATED)) { CACHE_STATUS_HISTOGRAMS(".MainFrameHTML"); IS_NO_STORE_HISTOGRAMS(".MainFrameHTML", is_no_store); - } else if (mime_type == "text/html") { + } else if (is_html) { CACHE_STATUS_HISTOGRAMS(".NonMainFrameHTML"); } else if (mime_type == "text/css") { if (is_third_party) { @@ -3799,6 +3850,15 @@ void HttpCache::Transaction::RecordHistograms() { IS_NO_STORE_HISTOGRAMS("", is_no_store); if (cache_entry_status_ == CacheEntryStatus::ENTRY_OTHER) { + CHECK_NE(other_status_reason_, OtherStatusReason::kNoReason); + UMA_HISTOGRAM_ENUMERATION("HttpCache.Pattern.NotCoveredReason", + other_status_reason_); + if (is_html && (effective_load_flags_ & LOAD_MAIN_FRAME_DEPRECATED)) { + base::UmaHistogramEnumeration( + "HttpCache.Pattern.NotCoveredReason.MainFrameHTML", + other_status_reason_); + } + return; } diff --git a/naiveproxy/src/net/http/http_cache_transaction.h b/naiveproxy/src/net/http/http_cache_transaction.h index d0fb2c028a..d552394d66 100644 --- a/naiveproxy/src/net/http/http_cache_transaction.h +++ b/naiveproxy/src/net/http/http_cache_transaction.h @@ -22,6 +22,7 @@ #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" +#include "base/trace_event/trace_event.h" #include "net/base/completion_once_callback.h" #include "net/base/completion_repeating_callback.h" #include "net/base/io_buffer.h" @@ -30,7 +31,6 @@ #include "net/base/net_error_details.h" #include "net/base/net_errors.h" #include "net/base/request_priority.h" -#include "net/base/tracing.h" #include "net/http/http_cache.h" #include "net/http/http_cache_util.h" #include "net/http/http_request_headers.h" @@ -311,6 +311,53 @@ class NET_EXPORT_PRIVATE HttpCache::Transaction : public HttpTransaction { }; // LINT.ThenChange(//tools/metrics/histograms/metadata/net/enums.xml:NoVarySearchUseResult) + // Reason why we ended up with status ENTRY_OTHER. + // + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. + // + // LINT.IfChange(OtherStatusReason) + enum class OtherStatusReason : uint8_t { + kNoReason = 0, // Status was not set to ENTRY_OTHER. + kReadingAuthResponse = 1, // Stopped caching to read auth response body. + kNetworkError = 2, // A network error happened. + kResponseValidation = 3, // Response validation failed. + kDeleteFullEntry = 4, // Need to delete a full entry. + kPartialRequest = 5, // Partial requests are hard to log. + kRangeHeaderFound = 6, // Request had Range header. + kTruncatedEntry = 7, // Cache entry was truncated. + kPartialValidation = 8, // Validating a partial entry. + kPreConditionalized = 9, // Externally conditionalized request. + kValidatePartial = 10, // Validating partial response failed. + kIgnoreRangeRequest = 11, // Very miscellaneous range failure. + kBlockedByIpSpace = 12, // Blocked by Private Network Access. + kMaxValue = kBlockedByIpSpace, + }; + // LINT.ThenChange(//tools/metrics/histograms/metadata/net/enums.xml:HttpCacheNotCoveredReason) + + // The status of the entry that we are considering to doom. + // + // LINT.IfChange(HttpCacheEntryRejectionStatus) + enum class HttpCacheEntryRejectionStatus { + // The cache entry was rejected. + kRejection = 0, + // The cache entry was not rejected because it is usable. + kNoRejectionUsable = 1, + // The cache entry was not rejected because the request is for a partial + // cache entry. + kNoRejectionPartial = 2, + // The cache entry was not rejected because the transaction is not in + // read-write mode. + kNoRejectionNonReadWriteMode = 3, + // The cache entry was not rejected because cache validation was skipped. + kNoRejectionSkipCacheValidation = 4, + // The cache entry was not rejected because the request was loaded only from + // cache. + kNoRejectionLoadOnlyFromCache = 5, + kMaxValue = kNoRejectionLoadOnlyFromCache, + }; + // LINT.ThenChange(//tools/metrics/histograms/metadata/net/enums.xml:HttpCacheEntryRejectionStatus) + // Runs the state transition loop. Resets and calls |callback_| on exit, // unless the return value is ERR_IO_PENDING. int DoLoop(int result); @@ -433,6 +480,9 @@ class NET_EXPORT_PRIVATE HttpCache::Transaction : public HttpTransaction { // entry and not attempt to create. bool ShouldOpenOnlyMethods() const; + HttpCacheEntryRejectionStatus GetHttpCacheEntryRejectionStatus( + uint8_t in_memory_info); + // Returns true if the resource info MemoryEntryDataHints bit flags in // |in_memory_info| and the current request & load flags suggest that // the cache entry in question is not actually usable for HTTP @@ -546,6 +596,8 @@ class NET_EXPORT_PRIVATE HttpCache::Transaction : public HttpTransaction { void UpdateCacheEntryStatus( HttpResponseInfo::CacheEntryStatus new_cache_entry_status); + void UpdateCacheEntryStatusToOther(OtherStatusReason reason); + // Sets the response.cache_entry_status to the current cache_entry_status_. void SyncCacheEntryStatusToResponse(); @@ -733,6 +785,7 @@ class NET_EXPORT_PRIVATE HttpCache::Transaction : public HttpTransaction { base::TimeTicks last_disk_cache_access_start_time_; base::TimeDelta total_disk_cache_read_time_; base::TimeDelta total_disk_cache_write_time_; + base::TimeTicks first_nvs_cache_lookup_end_time_; bool recorded_histograms_ = false; bool has_opened_or_created_entry_ = false; bool record_entry_open_or_creation_time_ = false; @@ -759,6 +812,10 @@ class NET_EXPORT_PRIVATE HttpCache::Transaction : public HttpTransaction { NoVarySearchUseResult no_vary_search_use_result_ = NoVarySearchUseResult::kNotApplied; + // The first reason why `cache_entry_status_` ended up set to ENTRY_OTHER. + // Logged to UMA on destruction when `cache_entry_status_` is ENTRY_OTHER. + OtherStatusReason other_status_reason_ = OtherStatusReason::kNoReason; + // If an entry in the NoVarySearchCache was found to be unhelpful, this // handle can be used to erase it. Only set if an entry was found in the // NoVerySearchCache and hasn't been erased already. This is also used as a diff --git a/naiveproxy/src/net/http/http_connection_info.cc b/naiveproxy/src/net/http/http_connection_info.cc index 1e294415ce..d22ebfeb13 100644 --- a/naiveproxy/src/net/http/http_connection_info.cc +++ b/naiveproxy/src/net/http/http_connection_info.cc @@ -102,6 +102,11 @@ std::string_view HttpConnectionInfoToString( } } +// Returns a more coarse-grained description of the protocol used to fetch the +// response. +// +// This is used for histograms, so the returned value must not change. +// LINT.IfChange(HttpConnectionInfoCoarseToString) std::string_view HttpConnectionInfoCoarseToString( HttpConnectionInfoCoarse connection_info_coarse) { switch (connection_info_coarse) { @@ -115,6 +120,7 @@ std::string_view HttpConnectionInfoCoarseToString( return "Other"; } } +// LINT.ThenChange(//tools/metrics/histograms/metadata/page/histograms.xml:ConnectionProtocolType) // Returns a more coarse-grained description of the protocol used to fetch the // response. diff --git a/naiveproxy/src/net/http/http_network_session.h b/naiveproxy/src/net/http/http_network_session.h index 43aa7bcb44..9bc11bfb0f 100644 --- a/naiveproxy/src/net/http/http_network_session.h +++ b/naiveproxy/src/net/http/http_network_session.h @@ -13,7 +13,6 @@ #include #include #include -#include #include #include "base/containers/flat_set.h" @@ -40,10 +39,6 @@ #include "net/ssl/ssl_client_session_cache.h" #include "net/third_party/quiche/src/quiche/http2/core/spdy_protocol.h" -namespace base { -class Value; -} - namespace net { class CertVerifier; diff --git a/naiveproxy/src/net/http/http_network_transaction.cc b/naiveproxy/src/net/http/http_network_transaction.cc index 89dc681a30..4593bdcc35 100644 --- a/naiveproxy/src/net/http/http_network_transaction.cc +++ b/naiveproxy/src/net/http/http_network_transaction.cc @@ -1097,7 +1097,7 @@ int HttpNetworkTransaction::DoCreateStream() { // IP based pooling is only disabled on a retry after 421 Misdirected Request // is received. Alternative Services are also disabled in this case (though // they can also be disabled when retrying after a QUIC error). - if (!enable_ip_based_pooling_) { + if (!enable_ip_based_pooling_for_h2_) { DCHECK(!enable_alternative_services_); } @@ -1111,11 +1111,13 @@ int HttpNetworkTransaction::DoCreateStream() { session_->http_stream_factory()->RequestWebSocketHandshakeStream( *request_, priority_, /*allowed_bad_certs=*/observed_bad_certs_, this, websocket_handshake_stream_base_create_helper_, - enable_ip_based_pooling_, enable_alternative_services_, net_log_); + enable_ip_based_pooling_for_h2_, enable_alternative_services_, + net_log_); } else { stream_request_ = session_->http_stream_factory()->RequestStream( *request_, priority_, /*allowed_bad_certs=*/observed_bad_certs_, this, - enable_ip_based_pooling_, enable_alternative_services_, net_log_); + enable_ip_based_pooling_for_h2_, enable_alternative_services_, + net_log_); } DCHECK(stream_request_.get()); return ERR_IO_PENDING; @@ -1686,14 +1688,14 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) { request_->upload_data_stream && request_->upload_data_stream->has_null_source(); if (response_.headers->response_code() == 421 && - (enable_ip_based_pooling_ || enable_alternative_services_) && + (enable_ip_based_pooling_for_h2_ || enable_alternative_services_) && !has_body_with_null_source) { #if BUILDFLAG(ENABLE_REPORTING) GenerateNetworkErrorLoggingReport(OK); #endif // BUILDFLAG(ENABLE_REPORTING) // Retry the request with both IP based pooling and Alternative Services // disabled. - enable_ip_based_pooling_ = false; + enable_ip_based_pooling_for_h2_ = false; enable_alternative_services_ = false; net_log_.AddEvent( NetLogEventType::HTTP_TRANSACTION_RESTART_MISDIRECTED_REQUEST); diff --git a/naiveproxy/src/net/http/http_network_transaction.h b/naiveproxy/src/net/http/http_network_transaction.h index f5759840f3..c40a6838c3 100644 --- a/naiveproxy/src/net/http/http_network_transaction.h +++ b/naiveproxy/src/net/http/http_network_transaction.h @@ -464,7 +464,11 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction // Enable pooling to a SpdySession with matching IP and certificate // even if the SpdySessionKey is different. - bool enable_ip_based_pooling_ = true; + // While QUIC also has a notion of IP based pooling / connection aliasing, + // this field does not affect QUIC. `enable_alternative_services_` is always + // set to false when this field is, which disables QUIC. If that ever changes, + // this field should probably be wired up to QUIC sessions as well. + bool enable_ip_based_pooling_for_h2_ = true; // Enable using alternative services for the request. bool enable_alternative_services_ = true; diff --git a/naiveproxy/src/net/http/http_proxy_connect_job.cc b/naiveproxy/src/net/http/http_proxy_connect_job.cc index 3fa80500d7..b6c887d6cf 100644 --- a/naiveproxy/src/net/http/http_proxy_connect_job.cc +++ b/naiveproxy/src/net/http/http_proxy_connect_job.cc @@ -29,6 +29,7 @@ #include "net/base/net_errors.h" #include "net/base/proxy_chain.h" #include "net/base/session_usage.h" +#include "net/base/task/task_runner.h" #include "net/dns/public/secure_dns_policy.h" #include "net/log/net_log_source_type.h" #include "net/log/net_log_with_source.h" @@ -137,6 +138,14 @@ GURL MakeProxyUrl(const HttpProxySocketParams& params) { params.proxy_server().host_port_pair().ToString()); } +const scoped_refptr& TaskRunner( + net::RequestPriority priority) { + if (features::kNetTaskSchedulerHttpProxyConnectJob.Get()) { + return net::GetTaskRunner(priority); + } + return base::SingleThreadTaskRunner::GetCurrentDefault(); +} + } // namespace HttpProxySocketParams::HttpProxySocketParams( @@ -406,9 +415,9 @@ void HttpProxyConnectJob::RestartWithAuthCredentials() { // Always do this asynchronously, to avoid re-entrancy. next_state_ = STATE_RESTART_WITH_AUTH; - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::BindOnce(&HttpProxyConnectJob::OnIOComplete, - weak_ptr_factory_.GetWeakPtr(), OK)); + TaskRunner(priority()) + ->PostTask(FROM_HERE, base::BindOnce(&HttpProxyConnectJob::OnIOComplete, + weak_ptr_factory_.GetWeakPtr(), OK)); } int HttpProxyConnectJob::DoLoop(int result) { @@ -512,7 +521,7 @@ int HttpProxyConnectJob::DoTransportConnect() { // Skip making a new connection if we have an existing HTTP/2 session. if (params_->tunnel() && common_connect_job_params()->spdy_session_pool->FindAvailableSession( - CreateSpdySessionKey(), /*enable_ip_based_pooling=*/false, + CreateSpdySessionKey(), /*enable_ip_based_pooling_for_h2=*/false, /*is_websocket=*/false, net_log())) { next_state_ = STATE_SPDY_PROXY_CREATE_STREAM; return OK; @@ -639,8 +648,9 @@ int HttpProxyConnectJob::DoHttpProxyConnect() { int HttpProxyConnectJob::DoHttpProxyConnectComplete(int result) { // Always inform caller of auth requests asynchronously. if (result == ERR_PROXY_AUTH_REQUESTED) { - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::BindOnce(&HttpProxyConnectJob::OnAuthChallenge, + TaskRunner(priority()) + ->PostTask(FROM_HERE, + base::BindOnce(&HttpProxyConnectJob::OnAuthChallenge, weak_ptr_factory_.GetWeakPtr())); return ERR_IO_PENDING; } @@ -676,7 +686,7 @@ int HttpProxyConnectJob::DoSpdyProxyCreateStream() { SpdySessionKey key = CreateSpdySessionKey(); base::WeakPtr spdy_session = common_connect_job_params()->spdy_session_pool->FindAvailableSession( - key, /* enable_ip_based_pooling = */ false, + key, /* enable_ip_based_pooling_for_h2 = */ false, /* is_websocket = */ false, net_log()); // It's possible that a session to the proxy has recently been created if (spdy_session) { diff --git a/naiveproxy/src/net/http/http_response_headers.cc b/naiveproxy/src/net/http/http_response_headers.cc index da4b7ebd32..1354e5dd7e 100644 --- a/naiveproxy/src/net/http/http_response_headers.cc +++ b/naiveproxy/src/net/http/http_response_headers.cc @@ -27,10 +27,10 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/time/time.h" +#include "base/trace_event/trace_event.h" #include "base/values.h" #include "net/base/features.h" #include "net/base/parse_number.h" -#include "net/base/tracing.h" #include "net/http/http_byte_range.h" #include "net/http/http_log_util.h" #include "net/http/http_status_code.h" @@ -1150,9 +1150,9 @@ bool HttpResponseHeaders::IsRedirectResponseCode(int response_code) { // freshness_lifetime + stale_while_revalidate > current_age // ValidationType HttpResponseHeaders::RequiresValidation( - const Time& request_time, - const Time& response_time, - const Time& current_time) const { + Time request_time, + Time response_time, + Time current_time) const { FreshnessLifetimes lifetimes = GetFreshnessLifetimes(response_time); if (lifetimes.freshness.is_zero() && lifetimes.staleness.is_zero()) return VALIDATION_SYNCHRONOUS; @@ -1224,7 +1224,7 @@ HttpResponseHeaders::ParseCacheControlDirectivesForFreshness() const { // the |staleness| time, unless it overridden by another directive. // HttpResponseHeaders::FreshnessLifetimes -HttpResponseHeaders::GetFreshnessLifetimes(const Time& response_time) const { +HttpResponseHeaders::GetFreshnessLifetimes(Time response_time) const { FreshnessLifetimes lifetimes; // Check for headers that force a response to never be fresh. For backwards // compat, we treat "Pragma: no-cache" as a synonym for "Cache-Control: @@ -1365,10 +1365,9 @@ HttpResponseHeaders::GetFreshnessLifetimes(const Time& response_time) const { // resident_time = now - response_time; // current_age = corrected_initial_age + resident_time; // -base::TimeDelta HttpResponseHeaders::GetCurrentAge( - const Time& request_time, - const Time& response_time, - const Time& current_time) const { +base::TimeDelta HttpResponseHeaders::GetCurrentAge(Time request_time, + Time response_time, + Time current_time) const { // If there is no Date header, then assume that the server response was // generated at the time when we received the response. Time date_value = GetDateValue().value_or(response_time); diff --git a/naiveproxy/src/net/http/http_response_headers.h b/naiveproxy/src/net/http/http_response_headers.h index d79d998a04..0f59d653ed 100644 --- a/naiveproxy/src/net/http/http_response_headers.h +++ b/naiveproxy/src/net/http/http_response_headers.h @@ -349,9 +349,9 @@ class NET_EXPORT HttpResponseHeaders // a parameter to support unit testing. The request_time parameter indicates // the time at which the request was made that resulted in this response, // which was received at response_time. - ValidationType RequiresValidation(const base::Time& request_time, - const base::Time& response_time, - const base::Time& current_time) const; + ValidationType RequiresValidation(base::Time request_time, + base::Time response_time, + base::Time current_time) const; // Calculates the amount of time the server claims the response is fresh from // the time the response was generated. See section 13.2.4 of RFC 2616. See @@ -359,14 +359,13 @@ class NET_EXPORT HttpResponseHeaders // the definition of FreshnessLifetimes above for the meaning of the return // value. See RFC 5861 section 3 for the definition of // stale-while-revalidate. - FreshnessLifetimes GetFreshnessLifetimes( - const base::Time& response_time) const; + FreshnessLifetimes GetFreshnessLifetimes(base::Time response_time) const; // Returns the age of the response. See section 13.2.3 of RFC 2616. // See RequiresValidation for a description of this method's parameters. - base::TimeDelta GetCurrentAge(const base::Time& request_time, - const base::Time& response_time, - const base::Time& current_time) const; + base::TimeDelta GetCurrentAge(base::Time request_time, + base::Time response_time, + base::Time current_time) const; // The following methods extract values from the response headers. If a value // is not present, or is invalid, then std::nullopt is returned. Otherwise, diff --git a/naiveproxy/src/net/http/http_response_info.cc b/naiveproxy/src/net/http/http_response_info.cc index 0409b9e341..bee263e2a1 100644 --- a/naiveproxy/src/net/http/http_response_info.cc +++ b/naiveproxy/src/net/http/http_response_info.cc @@ -369,9 +369,12 @@ bool HttpResponseInfo::InitFromPickle(const base::Pickle& pickle, (extra_flags & RESPONSE_EXTRA_INFO_DID_USE_SHARED_DICTIONARY) != 0; if (extra_flags & RESPONSE_EXTRA_INFO_HAS_PROXY_CHAIN) { - if (!proxy_chain.InitFromPickle(&iter)) { + std::optional unpickled_proxy_chain = + ProxyChain::InitFromPickle(iter); + if (!unpickled_proxy_chain) { return false; } + proxy_chain = std::move(*unpickled_proxy_chain); } return true; diff --git a/naiveproxy/src/net/http/http_stream_factory.cc b/naiveproxy/src/net/http/http_stream_factory.cc index 17b2e358b5..b506ce5289 100644 --- a/naiveproxy/src/net/http/http_stream_factory.cc +++ b/naiveproxy/src/net/http/http_stream_factory.cc @@ -169,14 +169,14 @@ std::unique_ptr HttpStreamFactory::RequestStream( RequestPriority priority, const std::vector& allowed_bad_certs, HttpStreamRequest::Delegate* delegate, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool enable_alternative_services, const NetLogWithSource& net_log) { - return RequestStreamInternal(request_info, priority, allowed_bad_certs, - delegate, nullptr, - HttpStreamRequest::HTTP_STREAM, - /*is_websocket=*/false, enable_ip_based_pooling, - enable_alternative_services, net_log); + return RequestStreamInternal( + request_info, priority, allowed_bad_certs, delegate, nullptr, + HttpStreamRequest::HTTP_STREAM, + /*is_websocket=*/false, enable_ip_based_pooling_for_h2, + enable_alternative_services, net_log); } std::unique_ptr @@ -186,15 +186,15 @@ HttpStreamFactory::RequestWebSocketHandshakeStream( const std::vector& allowed_bad_certs, HttpStreamRequest::Delegate* delegate, WebSocketHandshakeStreamBase::CreateHelper* create_helper, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool enable_alternative_services, const NetLogWithSource& net_log) { DCHECK(create_helper); - return RequestStreamInternal(request_info, priority, allowed_bad_certs, - delegate, create_helper, - HttpStreamRequest::HTTP_STREAM, - /*is_websocket=*/true, enable_ip_based_pooling, - enable_alternative_services, net_log); + return RequestStreamInternal( + request_info, priority, allowed_bad_certs, delegate, create_helper, + HttpStreamRequest::HTTP_STREAM, + /*is_websocket=*/true, enable_ip_based_pooling_for_h2, + enable_alternative_services, net_log); } std::unique_ptr @@ -203,16 +203,16 @@ HttpStreamFactory::RequestBidirectionalStreamImpl( RequestPriority priority, const std::vector& allowed_bad_certs, HttpStreamRequest::Delegate* delegate, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool enable_alternative_services, const NetLogWithSource& net_log) { DCHECK(request_info.url.SchemeIs(url::kHttpsScheme)); - return RequestStreamInternal(request_info, priority, allowed_bad_certs, - delegate, nullptr, - HttpStreamRequest::BIDIRECTIONAL_STREAM, - /*is_websocket=*/false, enable_ip_based_pooling, - enable_alternative_services, net_log); + return RequestStreamInternal( + request_info, priority, allowed_bad_certs, delegate, nullptr, + HttpStreamRequest::BIDIRECTIONAL_STREAM, + /*is_websocket=*/false, enable_ip_based_pooling_for_h2, + enable_alternative_services, net_log); } std::unique_ptr HttpStreamFactory::RequestStreamInternal( @@ -224,7 +224,7 @@ std::unique_ptr HttpStreamFactory::RequestStreamInternal( websocket_handshake_stream_create_helper, HttpStreamRequest::StreamType stream_type, bool is_websocket, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool enable_alternative_services, const NetLogWithSource& net_log) { // This is only needed in the non-preconnect path, as preconnects do not @@ -233,7 +233,7 @@ std::unique_ptr HttpStreamFactory::RequestStreamInternal( auto job_controller = std::make_unique( this, delegate, session_, job_factory_.get(), request_info, - /* is_preconnect = */ false, is_websocket, enable_ip_based_pooling, + /* is_preconnect = */ false, is_websocket, enable_ip_based_pooling_for_h2, enable_alternative_services, session_->context() .quic_context->params() @@ -261,7 +261,7 @@ void HttpStreamFactory::PreconnectStreams(int num_streams, this, nullptr, session_, job_factory_.get(), request_info, /*is_preconnect=*/true, /*is_websocket=*/false, - /*enable_ip_based_pooling=*/true, + /*enable_ip_based_pooling_for_h2=*/true, /*enable_alternative_services=*/true, session_->context() .quic_context->params() diff --git a/naiveproxy/src/net/http/http_stream_factory.h b/naiveproxy/src/net/http/http_stream_factory.h index f18b6e68e3..48eb850731 100644 --- a/naiveproxy/src/net/http/http_stream_factory.h +++ b/naiveproxy/src/net/http/http_stream_factory.h @@ -131,7 +131,7 @@ class NET_EXPORT HttpStreamFactory { RequestPriority priority, const std::vector& allowed_bad_certs, HttpStreamRequest::Delegate* delegate, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool enable_alternative_services, const NetLogWithSource& net_log); @@ -144,7 +144,7 @@ class NET_EXPORT HttpStreamFactory { const std::vector& allowed_bad_certs, HttpStreamRequest::Delegate* delegate, WebSocketHandshakeStreamBase::CreateHelper* create_helper, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool enable_alternative_services, const NetLogWithSource& net_log); @@ -158,7 +158,7 @@ class NET_EXPORT HttpStreamFactory { RequestPriority priority, const std::vector& allowed_bad_certs, HttpStreamRequest::Delegate* delegate, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool enable_alternative_services, const NetLogWithSource& net_log); @@ -198,7 +198,7 @@ class NET_EXPORT HttpStreamFactory { WebSocketHandshakeStreamBase::CreateHelper* create_helper, HttpStreamRequest::StreamType stream_type, bool is_websocket, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool enable_alternative_services, const NetLogWithSource& net_log); diff --git a/naiveproxy/src/net/http/http_stream_factory_job.cc b/naiveproxy/src/net/http/http_stream_factory_job.cc index 3ade2a3097..d2ff50d380 100644 --- a/naiveproxy/src/net/http/http_stream_factory_job.cc +++ b/naiveproxy/src/net/http/http_stream_factory_job.cc @@ -23,6 +23,7 @@ #include "net/base/proxy_chain.h" #include "net/base/proxy_delegate.h" #include "net/base/session_usage.h" +#include "net/base/task/task_runner.h" #include "net/base/url_util.h" #include "net/cert/cert_verifier.h" #include "net/dns/public/secure_dns_policy.h" @@ -65,6 +66,14 @@ BASE_FEATURE(kLimitEarlyPreconnectsExperiment, "LimitEarlyPreconnects", base::FEATURE_ENABLED_BY_DEFAULT); +const scoped_refptr& TaskRunner( + net::RequestPriority priority) { + if (features::kNetTaskSchedulerHttpStreamFactoryJob.Get()) { + return net::GetTaskRunner(priority); + } + return base::SingleThreadTaskRunner::GetCurrentDefault(); +} + } // namespace const char* NetLogHttpStreamJobType(HttpStreamFactory::JobType job_type) { @@ -104,7 +113,7 @@ HttpStreamFactory::Job::Job( NextProto alternative_protocol, quic::ParsedQuicVersion quic_version, bool is_websocket, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, std::optional management_config, NetLog* net_log) : request_info_(request_info), @@ -123,8 +132,8 @@ HttpStreamFactory::Job::Job( try_websocket_over_http2_(is_websocket_ && origin_url_.SchemeIs(url::kWssScheme)), // Only support IP-based pooling for non-proxied streams. - enable_ip_based_pooling_(enable_ip_based_pooling && - proxy_info.is_direct()), + enable_ip_based_pooling_for_h2_(enable_ip_based_pooling_for_h2 && + proxy_info.is_direct()), delegate_(delegate), job_type_(job_type), using_ssl_(origin_url_.SchemeIs(url::kHttpsScheme) || @@ -530,7 +539,7 @@ void HttpStreamFactory::Job::RunLoop(int result) { RecordCompletionHistograms(result); if ((job_type_ == PRECONNECT) || (job_type_ == PRECONNECT_DNS_ALPN_H3)) { - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + TaskRunner(priority_)->PostTask( FROM_HERE, base::BindOnce(&HttpStreamFactory::Job::OnPreconnectsComplete, ptr_factory_.GetWeakPtr(), result)); @@ -543,7 +552,7 @@ void HttpStreamFactory::Job::RunLoop(int result) { GetSSLInfo(&ssl_info); next_state_ = STATE_WAITING_USER_ACTION; - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + TaskRunner(priority_)->PostTask( FROM_HERE, base::BindOnce(&HttpStreamFactory::Job::OnCertificateErrorCallback, ptr_factory_.GetWeakPtr(), result, ssl_info)); @@ -552,7 +561,7 @@ void HttpStreamFactory::Job::RunLoop(int result) { switch (result) { case ERR_SSL_CLIENT_AUTH_CERT_NEEDED: - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + TaskRunner(priority_)->PostTask( FROM_HERE, base::BindOnce( &Job::OnNeedsClientAuthCallback, ptr_factory_.GetWeakPtr(), @@ -563,31 +572,31 @@ void HttpStreamFactory::Job::RunLoop(int result) { next_state_ = STATE_DONE; if (is_websocket_) { DCHECK(websocket_stream_); - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + TaskRunner(priority_)->PostTask( FROM_HERE, base::BindOnce(&Job::OnWebSocketHandshakeStreamReadyCallback, ptr_factory_.GetWeakPtr())); } else if (stream_type_ == HttpStreamRequest::BIDIRECTIONAL_STREAM) { if (!bidirectional_stream_impl_) { - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + TaskRunner(priority_)->PostTask( FROM_HERE, base::BindOnce(&Job::OnStreamFailedCallback, ptr_factory_.GetWeakPtr(), ERR_FAILED)); } else { - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + TaskRunner(priority_)->PostTask( FROM_HERE, base::BindOnce(&Job::OnBidirectionalStreamImplReadyCallback, ptr_factory_.GetWeakPtr())); } } else { DCHECK(stream_.get()); - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + TaskRunner(priority_)->PostTask( FROM_HERE, base::BindOnce(&Job::OnStreamReadyCallback, ptr_factory_.GetWeakPtr())); } return; default: - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + TaskRunner(priority_)->PostTask( FROM_HERE, base::BindOnce(&Job::OnStreamFailedCallback, ptr_factory_.GetWeakPtr(), result)); return; @@ -735,18 +744,18 @@ int HttpStreamFactory::Job::DoInitConnectionImpl() { bool is_blocking_request_for_session; existing_spdy_session_ = session_->spdy_session_pool()->RequestSession( - spdy_session_key_, enable_ip_based_pooling_, is_websocket_, + spdy_session_key_, enable_ip_based_pooling_for_h2_, is_websocket_, net_log_, resume_callback, this, &spdy_session_request_, &is_blocking_request_for_session); if (!existing_spdy_session_ && should_throttle_connect && !is_blocking_request_for_session) { net_log_.AddEvent(NetLogEventType::HTTP_STREAM_JOB_THROTTLED); next_state_ = STATE_INIT_CONNECTION; - base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask( + TaskRunner(priority_)->PostDelayedTask( FROM_HERE, resume_callback, base::Milliseconds(kHTTP2ThrottleMs)); return ERR_IO_PENDING; } - } else if (enable_ip_based_pooling_) { + } else if (enable_ip_based_pooling_for_h2_) { // If already watching for an H2 session, still need to check for an // existing connection that can be reused through IP pooling, as those // don't post session available notifications. @@ -755,8 +764,8 @@ int HttpStreamFactory::Job::DoInitConnectionImpl() { // callback. existing_spdy_session_ = session_->spdy_session_pool()->FindAvailableSession( - spdy_session_key_, enable_ip_based_pooling_, is_websocket_, - net_log_); + spdy_session_key_, enable_ip_based_pooling_for_h2_, + is_websocket_, net_log_); } } if (existing_spdy_session_) { @@ -1131,7 +1140,7 @@ int HttpStreamFactory::Job::DoCreateStream() { existing_spdy_session_ = session_->spdy_session_pool()->FindAvailableSession( - spdy_session_key_, enable_ip_based_pooling_, + spdy_session_key_, enable_ip_based_pooling_for_h2_, /* is_websocket = */ false, net_log_); } if (existing_spdy_session_) { @@ -1258,7 +1267,7 @@ HttpStreamFactory::JobFactory::CreateJob( url::SchemeHostPort destination, GURL origin_url, bool is_websocket, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, NetLog* net_log, NextProto alternative_protocol, quic::ParsedQuicVersion quic_version, @@ -1266,8 +1275,8 @@ HttpStreamFactory::JobFactory::CreateJob( return std::make_unique( delegate, job_type, session, request_info, priority, proxy_info, allowed_bad_certs, std::move(destination), origin_url, - alternative_protocol, quic_version, is_websocket, enable_ip_based_pooling, - management_config, net_log); + alternative_protocol, quic_version, is_websocket, + enable_ip_based_pooling_for_h2, management_config, net_log); } bool HttpStreamFactory::Job::ShouldThrottleConnectForSpdy() const { diff --git a/naiveproxy/src/net/http/http_stream_factory_job.h b/naiveproxy/src/net/http/http_stream_factory_job.h index f1d18481b1..dd7236d86f 100644 --- a/naiveproxy/src/net/http/http_stream_factory_job.h +++ b/naiveproxy/src/net/http/http_stream_factory_job.h @@ -159,7 +159,7 @@ class HttpStreamFactory::Job NextProto alternative_protocol, quic::ParsedQuicVersion quic_version, bool is_websocket, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, std::optional management_config, NetLog* net_log); @@ -405,7 +405,7 @@ class HttpStreamFactory::Job // Enable pooling to a SpdySession with matching IP and certificate // even if the SpdySessionKey is different. - const bool enable_ip_based_pooling_; + const bool enable_ip_based_pooling_for_h2_; // Unowned. |this| job is owned by |delegate_|. const raw_ptr delegate_; @@ -510,7 +510,7 @@ class HttpStreamFactory::JobFactory { url::SchemeHostPort destination, GURL origin_url, bool is_websocket, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, NetLog* net_log, NextProto alternative_protocol, quic::ParsedQuicVersion quic_version, 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 6233f71a4c..a49e20c52c 100644 --- a/naiveproxy/src/net/http/http_stream_factory_job_controller.cc +++ b/naiveproxy/src/net/http/http_stream_factory_job_controller.cc @@ -23,6 +23,7 @@ #include "net/base/proxy_chain.h" #include "net/base/proxy_string_util.h" #include "net/base/session_usage.h" +#include "net/base/task/task_runner.h" #include "net/base/url_util.h" #include "net/http/alternative_service.h" #include "net/http/bidirectional_stream_impl.h" @@ -124,6 +125,14 @@ base::Value::Dict NetLogAltSvcParams(const AlternativeServiceInfo* alt_svc_info, return dict; } +const scoped_refptr& TaskRunner( + net::RequestPriority priority) { + if (features::kNetTaskSchedulerHttpStreamFactoryJobController.Get()) { + return net::GetTaskRunner(priority); + } + return base::SingleThreadTaskRunner::GetCurrentDefault(); +} + } // namespace // The maximum time to wait for the alternate job to complete before resuming @@ -138,7 +147,7 @@ HttpStreamFactory::JobController::JobController( const HttpRequestInfo& http_request_info, bool is_preconnect, bool is_websocket, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool enable_alternative_services, bool delay_main_job_with_available_spdy_session, const std::vector& allowed_bad_certs) @@ -148,7 +157,7 @@ HttpStreamFactory::JobController::JobController( delegate_(delegate), is_preconnect_(is_preconnect), is_websocket_(is_websocket), - enable_ip_based_pooling_(enable_ip_based_pooling), + enable_ip_based_pooling_for_h2_(enable_ip_based_pooling_for_h2), enable_alternative_services_(enable_alternative_services), delay_main_job_with_available_spdy_session_( delay_main_job_with_available_spdy_session), @@ -612,7 +621,7 @@ void HttpStreamFactory::JobController::ResumeMainJobLater( resume_main_job_callback_.Reset( base::BindOnce(&HttpStreamFactory::JobController::ResumeMainJob, ptr_factory_.GetWeakPtr())); - base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask( + TaskRunner(priority_)->PostDelayedTask( FROM_HERE, resume_main_job_callback_.callback(), delay); } @@ -756,7 +765,7 @@ void HttpStreamFactory::JobController::RunLoop(int result) { DCHECK(!main_job_); DCHECK(!alternative_job_); DCHECK(!dns_alpn_h3_job_); - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + TaskRunner(priority_)->PostTask( FROM_HERE, base::BindOnce(&HttpStreamFactory::JobController::NotifyRequestFailed, ptr_factory_.GetWeakPtr(), rv)); @@ -892,9 +901,10 @@ int HttpStreamFactory::JobController::DoCreateJobs() { std::unique_ptr preconnect_job = job_factory_->CreateJob( this, dns_alpn_h3_job_enabled ? PRECONNECT_DNS_ALPN_H3 : PRECONNECT, session_, request_info_, IDLE, proxy_info_, allowed_bad_certs_, - destination, origin_url_, is_websocket_, enable_ip_based_pooling_, - net_log_.net_log(), NextProto::kProtoUnknown, - quic::ParsedQuicVersion::Unsupported(), management_config_); + destination, origin_url_, is_websocket_, + enable_ip_based_pooling_for_h2_, net_log_.net_log(), + NextProto::kProtoUnknown, quic::ParsedQuicVersion::Unsupported(), + management_config_); // When there is an valid alternative service info, and `preconnect_job` // has no existing QUIC session, create a job for the alternative service. if (alternative_service_info_.protocol() != NextProto::kProtoUnknown && @@ -910,7 +920,7 @@ int HttpStreamFactory::JobController::DoCreateJobs() { main_job_ = job_factory_->CreateJob( this, PRECONNECT, session_, request_info_, IDLE, proxy_info_, allowed_bad_certs_, std::move(alternative_destination), origin_url_, - is_websocket_, enable_ip_based_pooling_, session_->net_log(), + is_websocket_, enable_ip_based_pooling_for_h2_, session_->net_log(), alternative_service_info_.protocol(), quic_version, management_config_); } else { @@ -920,7 +930,7 @@ int HttpStreamFactory::JobController::DoCreateJobs() { preconnect_backup_job_ = job_factory_->CreateJob( this, PRECONNECT, session_, request_info_, IDLE, proxy_info_, allowed_bad_certs_, std::move(destination), origin_url_, - is_websocket_, enable_ip_based_pooling_, net_log_.net_log(), + is_websocket_, enable_ip_based_pooling_for_h2_, net_log_.net_log(), NextProto::kProtoUnknown, quic::ParsedQuicVersion::Unsupported(), management_config_); } @@ -931,8 +941,9 @@ int HttpStreamFactory::JobController::DoCreateJobs() { main_job_ = job_factory_->CreateJob( this, MAIN, session_, request_info_, priority_, proxy_info_, allowed_bad_certs_, std::move(destination), origin_url_, is_websocket_, - enable_ip_based_pooling_, net_log_.net_log(), NextProto::kProtoUnknown, - quic::ParsedQuicVersion::Unsupported(), management_config_); + enable_ip_based_pooling_for_h2_, net_log_.net_log(), + NextProto::kProtoUnknown, quic::ParsedQuicVersion::Unsupported(), + management_config_); // Alternative Service can only be set for HTTPS requests while Alternative // Proxy is set for HTTP requests. @@ -959,7 +970,7 @@ int HttpStreamFactory::JobController::DoCreateJobs() { alternative_job_ = job_factory_->CreateJob( this, ALTERNATIVE, session_, request_info_, priority_, proxy_info_, allowed_bad_certs_, std::move(alternative_destination), origin_url_, - is_websocket_, enable_ip_based_pooling_, net_log_.net_log(), + is_websocket_, enable_ip_based_pooling_for_h2_, net_log_.net_log(), alternative_service_info_.protocol(), quic_version, management_config_); } @@ -970,7 +981,7 @@ int HttpStreamFactory::JobController::DoCreateJobs() { dns_alpn_h3_job_ = job_factory_->CreateJob( this, DNS_ALPN_H3, session_, request_info_, priority_, proxy_info_, allowed_bad_certs_, std::move(dns_alpn_h3_destination), origin_url_, - is_websocket_, enable_ip_based_pooling_, net_log_.net_log(), + is_websocket_, enable_ip_based_pooling_for_h2_, net_log_.net_log(), NextProto::kProtoUnknown, quic::ParsedQuicVersion::Unsupported(), management_config_); } @@ -1522,7 +1533,7 @@ void HttpStreamFactory::JobController::SwitchToHttpStreamPool() { base::BindOnce(&JobController::OnPoolPreconnectsComplete, ptr_factory_.GetWeakPtr())); if (rv != ERR_IO_PENDING) { - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + TaskRunner(priority_)->PostTask( FROM_HERE, base::BindOnce(&JobController::OnPoolPreconnectsComplete, ptr_factory_.GetWeakPtr(), rv)); } @@ -1533,10 +1544,10 @@ void HttpStreamFactory::JobController::SwitchToHttpStreamPool() { session_->http_stream_pool()->HandleStreamRequest( std::exchange(request_, nullptr), std::exchange(delegate_, nullptr), std::move(pool_request_info), priority_, allowed_bad_certs_, - enable_ip_based_pooling_, enable_alternative_services_); + enable_ip_based_pooling_for_h2_, enable_alternative_services_); // Delete `this` later as this method is called while running DoLoop(). - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + TaskRunner(priority_)->PostTask( FROM_HERE, base::BindOnce(&JobController::MaybeNotifyFactoryOfCompletion, ptr_factory_.GetWeakPtr())); } 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 d4e32b53fe..d30290fca9 100644 --- a/naiveproxy/src/net/http/http_stream_factory_job_controller.h +++ b/naiveproxy/src/net/http/http_stream_factory_job_controller.h @@ -42,7 +42,7 @@ class HttpStreamFactory::JobController const HttpRequestInfo& http_request_info, bool is_preconnect, bool is_websocket, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool enable_alternative_services, bool delay_main_job_with_available_spdy_session, const std::vector& allowed_bad_certs); @@ -321,7 +321,8 @@ class HttpStreamFactory::JobController // Enable pooling to a SpdySession with matching IP and certificate even if // the SpdySessionKey is different. - const bool enable_ip_based_pooling_; + // Note that this does nothing with QUIC. + const bool enable_ip_based_pooling_for_h2_; // Enable using alternative services for the request. If false, the // JobController will only create a |main_job_|. diff --git a/naiveproxy/src/net/http/http_stream_factory_test_util.cc b/naiveproxy/src/net/http/http_stream_factory_test_util.cc index c71bf6142a..2f12fb104a 100644 --- a/naiveproxy/src/net/http/http_stream_factory_test_util.cc +++ b/naiveproxy/src/net/http/http_stream_factory_test_util.cc @@ -29,7 +29,7 @@ MockHttpStreamFactoryJob::MockHttpStreamFactoryJob( NextProto alternative_protocol, quic::ParsedQuicVersion quic_version, bool is_websocket, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, std::optional management_config, NetLog* net_log) : HttpStreamFactory::Job(delegate, @@ -44,7 +44,7 @@ MockHttpStreamFactoryJob::MockHttpStreamFactoryJob( alternative_protocol, quic_version, is_websocket, - enable_ip_based_pooling, + enable_ip_based_pooling_for_h2, management_config, net_log) { DCHECK(!is_waiting()); @@ -71,7 +71,7 @@ std::unique_ptr TestJobFactory::CreateJob( url::SchemeHostPort destination, GURL origin_url, bool is_websocket, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, NetLog* net_log, NextProto alternative_protocol = NextProto::kProtoUnknown, quic::ParsedQuicVersion quic_version = @@ -81,8 +81,8 @@ std::unique_ptr TestJobFactory::CreateJob( auto job = std::make_unique( delegate, job_type, session, request_info, priority, proxy_info, allowed_bad_certs, std::move(destination), origin_url, - alternative_protocol, quic_version, is_websocket, enable_ip_based_pooling, - management_config, net_log); + alternative_protocol, quic_version, is_websocket, + enable_ip_based_pooling_for_h2, management_config, net_log); // Keep raw pointer to Job but pass ownership. switch (job_type) { diff --git a/naiveproxy/src/net/http/http_stream_factory_test_util.h b/naiveproxy/src/net/http/http_stream_factory_test_util.h index bb4de0f7b0..53d62f72d0 100644 --- a/naiveproxy/src/net/http/http_stream_factory_test_util.h +++ b/naiveproxy/src/net/http/http_stream_factory_test_util.h @@ -107,7 +107,7 @@ class MockHttpStreamFactoryJob : public HttpStreamFactory::Job { NextProto alternative_protocol, quic::ParsedQuicVersion quic_version, bool is_websocket, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, std::optional management_config, NetLog* net_log); @@ -137,7 +137,7 @@ class TestJobFactory : public HttpStreamFactory::JobFactory { url::SchemeHostPort destination, GURL origin_url, bool is_websocket, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, NetLog* net_log, NextProto alternative_protocol, quic::ParsedQuicVersion quic_version, diff --git a/naiveproxy/src/net/http/http_stream_pool.cc b/naiveproxy/src/net/http/http_stream_pool.cc index 01b19b6eea..798e377352 100644 --- a/naiveproxy/src/net/http/http_stream_pool.cc +++ b/naiveproxy/src/net/http/http_stream_pool.cc @@ -17,6 +17,7 @@ #include "base/metrics/field_trial_params.h" #include "base/notreached.h" #include "base/task/sequenced_task_runner.h" +#include "base/trace_event/trace_event.h" #include "net/base/completion_once_callback.h" #include "net/base/features.h" #include "net/base/host_port_pair.h" @@ -27,7 +28,6 @@ #include "net/base/proxy_chain.h" #include "net/base/request_priority.h" #include "net/base/session_usage.h" -#include "net/base/tracing.h" #include "net/http/alternative_service.h" #include "net/http/http_network_session.h" #include "net/http/http_stream_key.h" @@ -183,11 +183,11 @@ void HttpStreamPool::HandleStreamRequest( HttpStreamPoolRequestInfo request_info, RequestPriority priority, const std::vector& allowed_bad_certs, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool enable_alternative_services) { auto controller = std::make_unique( this, std::move(request_info), priority, allowed_bad_certs, - enable_ip_based_pooling, enable_alternative_services); + enable_ip_based_pooling_for_h2, enable_alternative_services); JobController* controller_raw_ptr = controller.get(); // Put `controller` into `job_controllers_` before calling HandleRequest() to // make sure `job_controllers_` always contains `controller` when @@ -206,7 +206,7 @@ int HttpStreamPool::Preconnect(HttpStreamPoolRequestInfo request_info, auto controller = std::make_unique( this, std::move(request_info), /*priority=*/RequestPriority::IDLE, /*allowed_bad_certs=*/std::vector(), - /*enable_ip_based_pooling=*/true, + /*enable_ip_based_pooling_for_h2=*/true, /*enable_alternative_services=*/true); JobController* controller_raw_ptr = controller.get(); CHECK_EQ(controller_raw_ptr->respect_limits(), RespectLimits::kRespect); @@ -388,13 +388,12 @@ bool HttpStreamPool::IsQuicBroken( bool HttpStreamPool::CanUseQuic( const url::SchemeHostPort& destination, const NetworkAnonymizationKey& network_anonymization_key, - bool enable_ip_based_pooling, bool enable_alternative_services) { if (http_network_session()->ShouldForceQuic(destination, ProxyInfo::Direct(), /*is_websocket=*/false)) { return true; } - return http_network_session()->IsQuicEnabled() && enable_ip_based_pooling && + return http_network_session()->IsQuicEnabled() && enable_alternative_services && GURL::SchemeIsCryptographic(destination.scheme()) && !RequiresHTTP11(destination, network_anonymization_key) && @@ -412,18 +411,24 @@ quic::ParsedQuicVersion HttpStreamPool::SelectQuicVersion( bool HttpStreamPool::CanUseExistingQuicSession( const QuicSessionAliasKey& quic_session_alias_key, - bool enable_ip_based_pooling, bool enable_alternative_services) { const url::SchemeHostPort& destination = quic_session_alias_key.destination(); return destination.IsValid() && CanUseQuic( destination, quic_session_alias_key.session_key().network_anonymization_key(), - enable_ip_based_pooling, enable_alternative_services) && + enable_alternative_services) && http_network_session()->quic_session_pool()->CanUseExistingSession( quic_session_alias_key.session_key(), destination); } +CompletionOnceCallback HttpStreamPool::GetAltSvcQuicPreconnectCallback() { + if (alt_svc_quic_preconnect_callback_for_testing_) { + return std::move(alt_svc_quic_preconnect_callback_for_testing_); + } + return base::DoNothing(); +} + void HttpStreamPool::SetDelegateForTesting( std::unique_ptr delegate) { delegate_for_testing_ = std::move(delegate); @@ -524,7 +529,7 @@ bool HttpStreamPool::CloseOneIdleStreamSocket() { base::WeakPtr HttpStreamPool::FindAvailableSpdySession( const HttpStreamKey& stream_key, const SpdySessionKey& spdy_session_key, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, const NetLogWithSource& net_log) { if (!GURL::SchemeIsCryptographic(stream_key.destination().scheme())) { return nullptr; @@ -532,8 +537,8 @@ base::WeakPtr HttpStreamPool::FindAvailableSpdySession( base::WeakPtr spdy_session = http_network_session()->spdy_session_pool()->FindAvailableSession( - spdy_session_key, enable_ip_based_pooling, /*is_websocket=*/false, - net_log); + spdy_session_key, enable_ip_based_pooling_for_h2, + /*is_websocket=*/false, net_log); if (spdy_session) { CHECK(!RequiresHTTP11(stream_key.destination(), stream_key.network_anonymization_key())); diff --git a/naiveproxy/src/net/http/http_stream_pool.h b/naiveproxy/src/net/http/http_stream_pool.h index 6d4ca0037c..798d99993b 100644 --- a/naiveproxy/src/net/http/http_stream_pool.h +++ b/naiveproxy/src/net/http/http_stream_pool.h @@ -62,6 +62,17 @@ class NET_EXPORT_PRIVATE HttpStreamPool kStartTimerOnFirstQuicAttempt, }; + // The type of a Job. A Job is a stream request or a preconnect. + enum class JobType { + // A stream request. + kRequest = 0, + // A normal preconnect. + kPreconnect = 1, + // A preconnect which is initiated when an alternative service is advertised + // via Alt-Svc but the current request is not using it. + kAltSvcQuicPreconnect = 2, + }; + // Observes events on the HttpStreamPool and may intercept preconnects. Used // only for tests. class NET_EXPORT_PRIVATE TestDelegate { @@ -183,7 +194,7 @@ class NET_EXPORT_PRIVATE HttpStreamPool HttpStreamPoolRequestInfo request_info, RequestPriority priority, const std::vector& allowed_bad_certs, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool enable_alternative_services); // Requests that enough connections/sessions for `num_streams` be opened. @@ -261,7 +272,6 @@ class NET_EXPORT_PRIVATE HttpStreamPool // Returns true when QUIC can be used for `destination`. bool CanUseQuic(const url::SchemeHostPort& destination, const NetworkAnonymizationKey& network_anonymization_key, - bool enable_ip_based_pooling, bool enable_alternative_services); // Returns the first quic::ParsedQuicVersion that has been advertised in @@ -275,9 +285,10 @@ class NET_EXPORT_PRIVATE HttpStreamPool // Returns true when there is an existing QUIC session for `quic_session_key`. bool CanUseExistingQuicSession( const QuicSessionAliasKey& quic_session_alias_key, - bool enable_ip_based_pooling, bool enable_alternative_services); + CompletionOnceCallback GetAltSvcQuicPreconnectCallback(); + // Retrieves information on the current state of the pool as a base::Value. base::Value::Dict GetInfoAsValue() const; @@ -317,6 +328,11 @@ class NET_EXPORT_PRIVATE HttpStreamPool return job_controllers_.size(); } + void SetAltSvcQuicPreconnectCallbackForTesting( + CompletionOnceCallback callback) { + alt_svc_quic_preconnect_callback_for_testing_ = std::move(callback); + } + private: // Returns true when NetLog events should provide more fields. // TODO(crbug.com/346835898): Remove this when we stabilize the @@ -346,7 +362,7 @@ class NET_EXPORT_PRIVATE HttpStreamPool base::WeakPtr FindAvailableSpdySession( const HttpStreamKey& stream_key, const SpdySessionKey& spdy_session_key, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, const NetLogWithSource& net_log = NetLogWithSource()); void OnPreconnectComplete(JobController* job_controller, @@ -392,6 +408,8 @@ class NET_EXPORT_PRIVATE HttpStreamPool std::unique_ptr delegate_for_testing_; + CompletionOnceCallback alt_svc_quic_preconnect_callback_for_testing_; + base::WeakPtrFactory weak_ptr_factory_{this}; }; diff --git a/naiveproxy/src/net/http/http_stream_pool_attempt_manager.cc b/naiveproxy/src/net/http/http_stream_pool_attempt_manager.cc index fcad1f5e52..114bf914c1 100644 --- a/naiveproxy/src/net/http/http_stream_pool_attempt_manager.cc +++ b/naiveproxy/src/net/http/http_stream_pool_attempt_manager.cc @@ -19,6 +19,7 @@ #include "base/task/sequenced_task_runner.h" #include "base/time/time.h" #include "base/timer/timer.h" +#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_id_helper.h" #include "net/base/completion_once_callback.h" #include "net/base/host_port_pair.h" @@ -27,7 +28,6 @@ #include "net/base/net_error_details.h" #include "net/base/net_errors.h" #include "net/base/request_priority.h" -#include "net/base/tracing.h" #include "net/dns/host_resolver.h" #include "net/http/http_network_session.h" #include "net/http/http_server_properties.h" @@ -221,7 +221,8 @@ void HttpStreamPool::AttemptManager::RequestStream(Job* job) { cert_and_status.cert->subject().GetDisplayName()); } dict.Set("allowed_bad_certs", std::move(allowed_bad_certs_list)); - dict.Set("enable_ip_based_pooling", job->enable_ip_based_pooling()); + dict.Set("enable_ip_based_pooling_for_h2", + job->enable_ip_based_pooling_for_h2()); dict.Set("enable_alternative_services", job->enable_alternative_services()); dict.Set("quic_version", @@ -240,8 +241,10 @@ void HttpStreamPool::AttemptManager::RequestStream(Job* job) { } void HttpStreamPool::AttemptManager::Preconnect(Job* job) { - // JobController should check active streams before starting a preconnect Job. - CHECK_LT(group_->ActiveStreamSocketCount(), job->num_streams()); + // JobController should check active streams before starting a preconnect + // Job unless the Job is AltSvc QUIC preconnect. + CHECK(job->type() == JobType::kAltSvcQuicPreconnect || + group_->ActiveStreamSocketCount() < job->num_streams()); TRACE_EVENT_INSTANT("net.stream", "AttemptManager::Preconnect", track_, NetLogWithSourceToFlow(job->request_net_log())); @@ -267,8 +270,11 @@ void HttpStreamPool::AttemptManager::OnServiceEndpointsUpdated() { return; } - TRACE_EVENT_INSTANT("net.stream", "AttemptManager::OnServiceEndpointsUpdated", - track_); + CHECK(service_endpoint_request_); + TRACE_EVENT_INSTANT( + "net.stream", "AttemptManager::OnServiceEndpointsUpdated", track_, + "endpoints", + GetServiceEndpointRequestAsValue(service_endpoint_request_.get())); net_log().AddEvent( NetLogEventType::HTTP_STREAM_POOL_ATTEMPT_MANAGER_DNS_RESOLUTION_UPDATED, [&] { @@ -284,11 +290,12 @@ void HttpStreamPool::AttemptManager::OnServiceEndpointRequestFinished(int rv) { return; } - TRACE_EVENT_INSTANT("net.stream", - "AttemptManager::OnServiceEndpointRequestFinished", - track_, "result", rv); CHECK(!service_endpoint_request_finished_); CHECK(service_endpoint_request_); + TRACE_EVENT_INSTANT( + "net.stream", "AttemptManager::OnServiceEndpointRequestFinished", track_, + "result", rv, "endpoints", + GetServiceEndpointRequestAsValue(service_endpoint_request_.get())); service_endpoint_request_finished_ = true; dns_resolution_end_time_ = base::TimeTicks::Now(); @@ -330,9 +337,10 @@ bool HttpStreamPool::AttemptManager::IsSvcbOptional() { return true; } + // See Section 5.1 of draft-ietf-tls-svcb-ech-08. base::span endpoints = service_endpoint_request_->GetEndpointResults(); - return !HostResolver::AllProtocolEndpointsHaveEch(endpoints); + return !HostResolver::AllAlternativeEndpointsHaveEch(endpoints); } bool HttpStreamPool::AttemptManager::HasEnoughTcpBasedAttemptsForSlowIPEndPoint( @@ -517,6 +525,7 @@ void HttpStreamPool::AttemptManager::CancelTcpBasedAttempts( void HttpStreamPool::AttemptManager::OnJobComplete(Job* job) { preconnect_jobs_.erase(job); + limit_ignoring_jobs_.erase(job); ip_based_pooling_disabling_jobs_.erase(job); alternative_service_disabling_jobs_.erase(job); @@ -559,7 +568,9 @@ size_t HttpStreamPool::AttemptManager::PendingPreconnectCount() const { // socket count is less than or equal to the active stream socket count. // This behavior is for compatibility with the non-HEv3 code path. See // TransportClientSocketPool::RequestSockets(). - if (num_streams <= group_->ActiveStreamSocketCount()) { + CHECK_GE(group_->ActiveStreamSocketCount(), slow_tcp_based_attempt_count_); + if (num_streams <= + group_->ActiveStreamSocketCount() - slow_tcp_based_attempt_count_) { return 0; } return PendingCountInternal(num_streams); @@ -971,7 +982,7 @@ base::Value::Dict HttpStreamPool::AttemptManager::GetStatesAsNetLogParams() static_cast(tcp_based_attempts_.size())); dict.Set("num_slow_attempts", static_cast(slow_tcp_based_attempt_count_)); - dict.Set("enable_ip_based_pooling", IsIpBasedPoolingEnabled()); + dict.Set("enable_ip_based_pooling_for_h2", IsIpBasedPoolingEnabledForH2()); dict.Set("enable_alternative_services", IsAlternativeServiceEnabled()); dict.Set("quic_attempt_alive", !!quic_attempt_); if (quic_attempt_result_.has_value()) { @@ -999,20 +1010,24 @@ void HttpStreamPool::AttemptManager::SetOnCompleteCallbackForTesting( void HttpStreamPool::AttemptManager::StartInternal(Job* job) { CHECK(availability_state_ == AvailabilityState::kAvailable); - if (job->IsPreconnect()) { - preconnect_jobs_.emplace(job); - } else { - request_jobs_.Insert(job, job->priority()); - if (base_ssl_config_.has_value()) { - base_ssl_config_->allowed_bad_certs = job->allowed_bad_certs(); - } + switch (job->type()) { + case JobType::kRequest: + request_jobs_.Insert(job, job->priority()); + if (base_ssl_config_.has_value()) { + base_ssl_config_->allowed_bad_certs = job->allowed_bad_certs(); + } + break; + case JobType::kPreconnect: + case JobType::kAltSvcQuicPreconnect: + preconnect_jobs_.emplace(job); + break; } if (job->respect_limits() == RespectLimits::kIgnore) { limit_ignoring_jobs_.emplace(job); } - if (!job->enable_ip_based_pooling()) { + if (!job->enable_ip_based_pooling_for_h2()) { ip_based_pooling_disabling_jobs_.emplace(job); } @@ -1024,8 +1039,11 @@ void HttpStreamPool::AttemptManager::StartInternal(Job* job) { // JobController should check the existing QUIC/SPDY sessions before starting // a Job. - DCHECK(!CanUseExistingQuicSession()); - DCHECK(!HasAvailableSpdySession()); + // TODO(crbug.com/346835898): Change to DCHECK once we stabilize the + // implementation. + CHECK(!CanUseExistingQuicSession()); + CHECK(job->type() == JobType::kAltSvcQuicPreconnect || + !HasAvailableSpdySession()); MaybeChangeServiceEndpointRequestPriority(); RestrictAllowedProtocols(job->allowed_alpns()); @@ -1193,7 +1211,8 @@ QuicChromiumClientSession* HttpStreamPool::AttemptManager:: base::WeakPtr HttpStreamPool::AttemptManager:: CanUseExistingSpdySessionAfterEndpointChanges() { - if (!IsIpBasedPoolingEnabled() || !UsingTls()) { + if (!IsIpBasedPoolingEnabledForH2() || !UsingTls() || + !CanUseTcpBasedProtocols()) { return nullptr; } @@ -1204,7 +1223,8 @@ base::WeakPtr HttpStreamPool::AttemptManager:: if (HasAvailableSpdySession()) { base::WeakPtr spdy_session = pool()->FindAvailableSpdySession( - stream_key(), spdy_session_key(), IsIpBasedPoolingEnabled(), net_log()); + stream_key(), spdy_session_key(), IsIpBasedPoolingEnabledForH2(), + net_log()); CHECK(spdy_session); CHECK(spdy_session->IsAvailable()); return spdy_session; @@ -1341,7 +1361,17 @@ void HttpStreamPool::AttemptManager::MaybeAttemptTcpBased( } bool HttpStreamPool::AttemptManager::IsTcpBasedAttemptReady() { - switch (CanAttemptConnection()) { + CanAttemptResult can_attempt = CanAttemptConnection(); + // TODO(crbug.com/383606724): Consider removing these trace and net log event + // once we figure out better endpoint selection algorithm. + TRACE_EVENT_INSTANT("net.stream", "AttemptManager::IsTcpBasedAttemptReady", + track_, "can_attempt", can_attempt); + net_log_.AddEvent( + NetLogEventType::HTTP_STREAM_POOL_ATTEMPT_MANAGER_CAN_ATTEMPT_TCP, [&] { + return base::Value::Dict().Set("can_attempt", + static_cast(can_attempt)); + }); + switch (can_attempt) { case CanAttemptResult::kAttempt: // If we ignore stream limits and the pool's limit has already reached, // try to close as much as possible. @@ -1421,7 +1451,7 @@ bool HttpStreamPool::AttemptManager::ShouldRespectLimits() const { return limit_ignoring_jobs_.empty(); } -bool HttpStreamPool::AttemptManager::IsIpBasedPoolingEnabled() const { +bool HttpStreamPool::AttemptManager::IsIpBasedPoolingEnabledForH2() const { return ip_based_pooling_disabling_jobs_.empty(); } @@ -1441,8 +1471,9 @@ bool HttpStreamPool::AttemptManager::ShouldThrottleAttemptForSpdy() const { CHECK(UsingTls()); - // The first attempt should not be blocked. - if (tcp_based_attempts_.empty()) { + // If there are no non-slow attempts, don't throttle new attempts. + CHECK_GE(tcp_based_attempts_.size(), slow_tcp_based_attempt_count_); + if (tcp_based_attempts_.size() - slow_tcp_based_attempt_count_ == 0) { return false; } @@ -1642,6 +1673,7 @@ void HttpStreamPool::AttemptManager::NotifyJobOfPreconnectComplete( raw_ptr job, int rv) { Job* raw_job = job.get(); + limit_ignoring_jobs_.erase(raw_job); notified_jobs_.emplace(std::move(job)); TRACE_EVENT_INSTANT("net.stream", "AttemptManager::NotifyJobOfPreconnectComplete", track_, @@ -1672,7 +1704,8 @@ void HttpStreamPool::AttemptManager::CreateTextBasedStreamAndNotify( bool HttpStreamPool::AttemptManager::HasAvailableSpdySession() const { return spdy_session_pool()->HasAvailableSession( - spdy_session_key(), IsIpBasedPoolingEnabled(), /*is_websocket=*/false); + spdy_session_key(), IsIpBasedPoolingEnabledForH2(), + /*is_websocket=*/false); } void HttpStreamPool::AttemptManager::MaybeStartDraining() { @@ -1691,7 +1724,7 @@ void HttpStreamPool::AttemptManager::MaybeStartDraining() { // slow. Currently we just cancel them for simplicity. If we want to keep // these attempts in the draining `this`, Group::ConnectingStreamSocketCount() // should check draining AttemptManagers. - CancelTcpBasedAttempts(StreamSocketCloseReason::kAbort); + CancelTcpBasedAttempts(StreamSocketCloseReason::kAttemptManagerDraining); if (quic_attempt_ && quic_attempt_->is_slow()) { CancelQuicAttempt(ERR_ABORTED); @@ -1925,6 +1958,8 @@ void HttpStreamPool::AttemptManager::HandleTcpBasedAttemptFailure( } void HttpStreamPool::AttemptManager::OnSpdyThrottleDelayPassed() { + TRACE_EVENT_INSTANT("net.stream", "AttemptManager::OnSpdyThrottleDelayPassed", + track_); CHECK(!spdy_throttle_delay_passed_); spdy_throttle_delay_passed_ = true; MaybeAttemptTcpBased(); @@ -1986,13 +2021,11 @@ bool HttpStreamPool::AttemptManager::CanUseQuic() { return allowed_alpns_.HasAny(kQuicBasedProtocols) && pool()->CanUseQuic(stream_key().destination(), stream_key().network_anonymization_key(), - IsIpBasedPoolingEnabled(), IsAlternativeServiceEnabled()); } bool HttpStreamPool::AttemptManager::CanUseExistingQuicSession() { return pool()->CanUseExistingQuicSession(quic_session_alias_key(), - IsIpBasedPoolingEnabled(), IsAlternativeServiceEnabled()); } diff --git a/naiveproxy/src/net/http/http_stream_pool_attempt_manager.h b/naiveproxy/src/net/http/http_stream_pool_attempt_manager.h index c1f76ef935..3f5fa4b42c 100644 --- a/naiveproxy/src/net/http/http_stream_pool_attempt_manager.h +++ b/naiveproxy/src/net/http/http_stream_pool_attempt_manager.h @@ -17,6 +17,7 @@ #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "base/timer/timer.h" +#include "base/trace_event/trace_event.h" #include "base/types/expected.h" #include "net/base/completion_once_callback.h" #include "net/base/ip_endpoint.h" @@ -26,7 +27,6 @@ #include "net/base/net_export.h" #include "net/base/priority_queue.h" #include "net/base/request_priority.h" -#include "net/base/tracing.h" #include "net/dns/host_resolver.h" #include "net/dns/public/resolve_error_info.h" #include "net/http/http_stream_pool.h" @@ -144,6 +144,8 @@ class HttpStreamPool::AttemptManager return dns_resolution_end_time_; } + NextProtoSet allowed_alpns() const { return allowed_alpns_; } + const NetLogWithSource& net_log(); // Starts `job` for a stream request. Will call one of Job::Delegate methods @@ -241,13 +243,6 @@ class HttpStreamPool::AttemptManager MultiplexedSessionCreationInitiator CalculateMultiplexedSessionCreationInitiator(); - // TODO(crbug.com/383606724): Remove this once we move unittests from - // HttpStreamPoolAttemptManagerTest to - // HttpStreamPoolIPEndPointStateTrackerTest - const IPEndPointStateTracker& ip_endpoint_state_tracker() const { - return ip_endpoint_state_tracker_; - } - std::optional GetQuicAttemptResultForTesting() { return quic_attempt_result_; } @@ -261,9 +256,6 @@ class HttpStreamPool::AttemptManager void SetOnCompleteCallbackForTesting(base::OnceClosure callback); private: - FRIEND_TEST_ALL_PREFIXES(HttpStreamPoolAttemptManagerTest, - GetIPEndPointToAttempt); - // Represents the availability of this instance. If not kAvailable, `this` // can't handle new Jobs and this should not have in-flight attempts. enum class AvailabilityState { @@ -376,8 +368,9 @@ class HttpStreamPool::AttemptManager // limits. bool ShouldRespectLimits() const; - // Returns true only when there are no jobs that disable IP based pooling. - bool IsIpBasedPoolingEnabled() const; + // Returns true only when there are no jobs that disable IP based pooling for + // HTTP/2. Note that this does nothing with QUIC. + bool IsIpBasedPoolingEnabledForH2() const; // Returns true only when there are no jobs that disable alternative services. bool IsAlternativeServiceEnabled() const; diff --git a/naiveproxy/src/net/http/http_stream_pool_group.cc b/naiveproxy/src/net/http/http_stream_pool_group.cc index 915b3d5ba1..2ce7086b6f 100644 --- a/naiveproxy/src/net/http/http_stream_pool_group.cc +++ b/naiveproxy/src/net/http/http_stream_pool_group.cc @@ -111,8 +111,8 @@ std::unique_ptr HttpStreamPool::Group::CreateJob( quic::ParsedQuicVersion quic_version, NextProto expected_protocol, const NetLogWithSource& request_net_log) { - return std::make_unique(delegate, this, quic_version, expected_protocol, - request_net_log); + return std::make_unique(delegate, JobType::kRequest, this, quic_version, + expected_protocol, request_net_log); } void HttpStreamPool::Group::OnJobComplete(Job* job) { @@ -315,7 +315,12 @@ void HttpStreamPool::Group::CancelJobs(int error) { } } -HttpStreamPool::AttemptManager* HttpStreamPool::Group::EnsureAttemptManager() { +HttpStreamPool::AttemptManager* HttpStreamPool::Group::GetAttemptManagerForJob( + Job* job) { + if (job->type() == JobType::kAltSvcQuicPreconnect) { + return GetAttemptManagerForAltSvcQuicPreconnect(); + } + if (!attempt_manager_) { attempt_manager_ = std::make_unique( this, http_network_session()->net_log()); @@ -325,9 +330,17 @@ HttpStreamPool::AttemptManager* HttpStreamPool::Group::EnsureAttemptManager() { void HttpStreamPool::Group::OnAttemptManagerShuttingDown( AttemptManager* attempt_manager) { - CHECK_EQ(attempt_manager_.get(), attempt_manager); - shutting_down_attempt_managers_.emplace(std::move(attempt_manager_)); - CHECK(!attempt_manager_.get()); + if (attempt_manager == attempt_manager_.get()) { + shutting_down_attempt_managers_.emplace(std::move(attempt_manager_)); + CHECK(!attempt_manager_.get()); + } else if (attempt_manager == + alt_svc_quic_preconnect_attempt_manager_.get()) { + shutting_down_attempt_managers_.emplace( + std::move(alt_svc_quic_preconnect_attempt_manager_)); + CHECK(!alt_svc_quic_preconnect_attempt_manager_.get()); + } else { + NOTREACHED(); + } } void HttpStreamPool::Group::OnAttemptManagerComplete( @@ -335,10 +348,17 @@ void HttpStreamPool::Group::OnAttemptManagerComplete( auto it = shutting_down_attempt_managers_.find(attempt_manager); if (it != shutting_down_attempt_managers_.end()) { CHECK_NE(attempt_manager_.get(), attempt_manager); + CHECK_NE(alt_svc_quic_preconnect_attempt_manager_.get(), attempt_manager); shutting_down_attempt_managers_.erase(it); } else { - CHECK_EQ(attempt_manager_.get(), attempt_manager); - attempt_manager_.reset(); + if (attempt_manager == attempt_manager_.get()) { + attempt_manager_.reset(); + } else if (attempt_manager == + alt_svc_quic_preconnect_attempt_manager_.get()) { + alt_svc_quic_preconnect_attempt_manager_.reset(); + } else { + NOTREACHED(); + } } MaybeComplete(); @@ -388,8 +408,18 @@ void HttpStreamPool::Group::CleanupIdleStreamSockets( MaybeCompleteLater(); } +HttpStreamPool::AttemptManager* +HttpStreamPool::Group::GetAttemptManagerForAltSvcQuicPreconnect() { + if (!alt_svc_quic_preconnect_attempt_manager_) { + alt_svc_quic_preconnect_attempt_manager_ = std::make_unique( + this, http_network_session()->net_log()); + } + return alt_svc_quic_preconnect_attempt_manager_.get(); +} + bool HttpStreamPool::Group::CanComplete() const { return ActiveStreamSocketCount() == 0 && !attempt_manager_ && + !alt_svc_quic_preconnect_attempt_manager_ && shutting_down_attempt_managers_.empty(); } diff --git a/naiveproxy/src/net/http/http_stream_pool_group.h b/naiveproxy/src/net/http/http_stream_pool_group.h index 08cb9721f5..71e7fdc6f3 100644 --- a/naiveproxy/src/net/http/http_stream_pool_group.h +++ b/naiveproxy/src/net/http/http_stream_pool_group.h @@ -175,8 +175,8 @@ class HttpStreamPool::Group { // Cancels all on-going jobs. void CancelJobs(int error); - // Create an AttemptManager if needed. - AttemptManager* EnsureAttemptManager(); + // Returns an active AttemptManager for `job`. + AttemptManager* GetAttemptManagerForJob(Job* job); // Called when the active AttemptManager is shutting down. void OnAttemptManagerShuttingDown(AttemptManager* attempt_manager); @@ -195,8 +195,6 @@ class HttpStreamPool::Group { void CleanupTimedoutIdleStreamSocketsForTesting(); private: - FRIEND_TEST_ALL_PREFIXES(HttpStreamPoolGroupTest, ComparePausedJobSet); - struct IdleStreamSocket { IdleStreamSocket(std::unique_ptr stream_socket, base::TimeTicks start_time); @@ -222,6 +220,9 @@ class HttpStreamPool::Group { void CleanupIdleStreamSockets(CleanupMode mode, std::string_view net_log_close_reason_utf8); + // Returns an `AttemptManager` for an Alt-Svc QUIC preconnect job. + AttemptManager* GetAttemptManagerForAltSvcQuicPreconnect(); + void MaybeComplete(); // Posts a task to call MaybeComplete() later. @@ -240,6 +241,9 @@ class HttpStreamPool::Group { std::unique_ptr attempt_manager_; + // An `AttemptManager` for Alt-Svc QUIC preconnects. + std::unique_ptr alt_svc_quic_preconnect_attempt_manager_; + // Keeps AttemptManagers that are shutting down. std::set, base::UniquePtrComparator> shutting_down_attempt_managers_; diff --git a/naiveproxy/src/net/http/http_stream_pool_job.cc b/naiveproxy/src/net/http/http_stream_pool_job.cc index 08c13e4ce5..477756d025 100644 --- a/naiveproxy/src/net/http/http_stream_pool_job.cc +++ b/naiveproxy/src/net/http/http_stream_pool_job.cc @@ -52,7 +52,6 @@ NextProtoSet CalculateAllowedAlpns(HttpStreamPool::Job::Delegate* delegate, if (!group->pool()->CanUseQuic( group->stream_key().destination(), group->stream_key().network_anonymization_key(), - delegate->enable_ip_based_pooling(), delegate->enable_alternative_services())) { allowed_alpns.Remove(NextProto::kProtoQUIC); } @@ -77,13 +76,15 @@ quic::ParsedQuicVersion CalculateQuicVersion( } // namespace HttpStreamPool::Job::Job(Delegate* delegate, + JobType type, Group* group, quic::ParsedQuicVersion quic_version, NextProto expected_protocol, const NetLogWithSource& request_net_log, size_t num_streams) : delegate_(delegate), - attempt_manager_(group->EnsureAttemptManager()), + type_(type), + attempt_manager_(group->GetAttemptManagerForJob(this)), quic_version_(CalculateQuicVersion(quic_version, group)), allowed_alpns_( CalculateAllowedAlpns(delegate_, group, expected_protocol)), @@ -93,6 +94,7 @@ HttpStreamPool::Job::Job(Delegate* delegate, NetLogSourceType::HTTP_STREAM_POOL_JOB)), num_streams_(num_streams), create_time_(base::TimeTicks::Now()) { + CHECK(attempt_manager_); job_net_log_.BeginEvent(NetLogEventType::HTTP_STREAM_POOL_JOB_ALIVE, [&] { base::Value::Dict dict; dict.Set("stream_key", group->stream_key().ToValue()); @@ -102,6 +104,7 @@ HttpStreamPool::Job::Job(Delegate* delegate, allowed_alpn_list.Append(NextProtoToString(alpn)); } dict.Set("allowed_alpns", std::move(allowed_alpn_list)); + dict.Set("type", static_cast(type_)); dict.Set("num_streams", static_cast(num_streams_)); delegate_->net_log().source().AddToEventParameters(dict); return dict; @@ -154,10 +157,14 @@ void HttpStreamPool::Job::Start() { CHECK(attempt_manager_); CHECK(!attempt_manager_->is_shutting_down()); - if (IsPreconnect()) { - attempt_manager_->Preconnect(this); - } else { - attempt_manager_->RequestStream(this); + switch (type_) { + case JobType::kRequest: + attempt_manager_->RequestStream(this); + break; + case JobType::kPreconnect: + case JobType::kAltSvcQuicPreconnect: + attempt_manager_->Preconnect(this); + break; } } diff --git a/naiveproxy/src/net/http/http_stream_pool_job.h b/naiveproxy/src/net/http/http_stream_pool_job.h index e29bdfcaef..de9867ffa6 100644 --- a/naiveproxy/src/net/http/http_stream_pool_job.h +++ b/naiveproxy/src/net/http/http_stream_pool_job.h @@ -50,7 +50,7 @@ class HttpStreamPool::Job { const = 0; // True when IP-based pooling is enabled. - virtual bool enable_ip_based_pooling() const = 0; + virtual bool enable_ip_based_pooling_for_h2() const = 0; // True when alternative services is enabled. virtual bool enable_alternative_services() const = 0; @@ -87,6 +87,7 @@ class HttpStreamPool::Job { // `delegate` must outlive `this`. For a stream request, `num_streams` must // not be specified. For a preconnect, `num_streams` must be specified. Job(Delegate* delegate, + JobType type, Group* group, quic::ParsedQuicVersion quic_version, NextProto expected_protocol, @@ -138,8 +139,8 @@ class HttpStreamPool::Job { RespectLimits respect_limits() const { return delegate_->respect_limits(); } - bool enable_ip_based_pooling() const { - return delegate_->enable_ip_based_pooling(); + bool enable_ip_based_pooling_for_h2() const { + return delegate_->enable_ip_based_pooling_for_h2(); } bool enable_alternative_services() const { @@ -166,7 +167,7 @@ class HttpStreamPool::Job { size_t num_streams() const { return num_streams_; } - bool IsPreconnect() const { return num_streams_ > 0; } + JobType type() const { return type_; } const ConnectionAttempts& connection_attempts() const { return connection_attempts_; @@ -176,6 +177,7 @@ class HttpStreamPool::Job { private: const raw_ptr delegate_; + const JobType type_; raw_ptr attempt_manager_; const quic::ParsedQuicVersion quic_version_; diff --git a/naiveproxy/src/net/http/http_stream_pool_job_controller.cc b/naiveproxy/src/net/http/http_stream_pool_job_controller.cc index 780f75f248..2d8c93a5eb 100644 --- a/naiveproxy/src/net/http/http_stream_pool_job_controller.cc +++ b/naiveproxy/src/net/http/http_stream_pool_job_controller.cc @@ -103,12 +103,12 @@ HttpStreamPool::JobController::JobController( HttpStreamPoolRequestInfo request_info, RequestPriority priority, std::vector allowed_bad_certs, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool enable_alternative_services) : pool_(pool), priority_(priority), allowed_bad_certs_(std::move(allowed_bad_certs)), - enable_ip_based_pooling_(enable_ip_based_pooling), + enable_ip_based_pooling_for_h2_(enable_ip_based_pooling_for_h2), enable_alternative_services_(enable_alternative_services), respect_limits_(request_info.load_flags & LOAD_IGNORE_LIMITS ? RespectLimits::kIgnore @@ -138,7 +138,8 @@ HttpStreamPool::JobController::JobController( dict.Set("alternative_destination", alternative_->stream_key.destination().Serialize()); } - dict.Set("enable_ip_based_pooling", enable_ip_based_pooling_); + dict.Set("enable_ip_based_pooling_for_h2", + enable_ip_based_pooling_for_h2_); dict.Set("enable_alternative_services", enable_alternative_services_); dict.Set("respect_limits", respect_limits_ == RespectLimits::kRespect); return dict; @@ -182,6 +183,10 @@ void HttpStreamPool::JobController::HandleStreamRequest( auto stream_with_protocol = MaybeCreateStreamFromExistingSession(); if (stream_with_protocol) { + if (stream_with_protocol->negotiated_protocol != NextProto::kProtoQUIC && + origin_quic_version_.IsKnown()) { + StartAltSvcQuicPreconnect(); + } base::SequencedTaskRunner::GetCurrentDefault()->PostTask( FROM_HERE, base::BindOnce( @@ -225,10 +230,19 @@ int HttpStreamPool::JobController::Preconnect( return OK; } + // If the preconnect explicitly requests QUIC, start preconnecting before + // checking existing SpdySession and idle streams. + if (origin_quic_version_.IsKnown()) { + preconnect_callback_ = std::move(callback); + StartAltSvcQuicPreconnect(); + return ERR_IO_PENDING; + } + SpdySessionKey spdy_session_key = origin_stream_key_.CalculateSpdySessionKey(); - if (pool_->FindAvailableSpdySession(origin_stream_key_, spdy_session_key, - /*enable_ip_based_pooling=*/true)) { + if (pool_->FindAvailableSpdySession( + origin_stream_key_, spdy_session_key, + /*enable_ip_based_pooling_for_h2=*/true)) { net_log_.AddEvent( NetLogEventType:: HTTP_STREAM_POOL_JOB_CONTROLLER_FOUND_EXISTING_SPDY_SESSION); @@ -251,9 +265,9 @@ int HttpStreamPool::JobController::Preconnect( } preconnect_callback_ = std::move(callback); - origin_job_ = - std::make_unique(this, &group, origin_quic_version_, - NextProto::kProtoUnknown, net_log_, num_streams); + origin_job_ = std::make_unique( + this, JobType::kPreconnect, &group, origin_quic_version_, + NextProto::kProtoUnknown, net_log_, num_streams); origin_job_->Start(); return ERR_IO_PENDING; } @@ -272,8 +286,8 @@ HttpStreamPool::JobController::allowed_bad_certs() const { return allowed_bad_certs_; } -bool HttpStreamPool::JobController::enable_ip_based_pooling() const { - return enable_ip_based_pooling_; +bool HttpStreamPool::JobController::enable_ip_based_pooling_for_h2() const { + return enable_ip_based_pooling_for_h2_; } bool HttpStreamPool::JobController::enable_alternative_services() const { @@ -439,7 +453,7 @@ HttpStreamPool::JobController::MaybeCreateStreamFromExistingSession() { SpdySessionKey spdy_session_key = origin_stream_key_.CalculateSpdySessionKey(); base::WeakPtr spdy_session = pool_->FindAvailableSpdySession( - origin_stream_key_, spdy_session_key, enable_ip_based_pooling_, + origin_stream_key_, spdy_session_key, enable_ip_based_pooling_for_h2_, stream_request_->net_log()); if (spdy_session) { net_log_.AddEvent( @@ -494,9 +508,9 @@ std::unique_ptr HttpStreamPool::JobController::MaybeCreateStreamFromExistingQuicSessionInternal( const QuicSessionAliasKey& key) { if (!key.destination().IsValid() || - !pool_->CanUseQuic( - key.destination(), key.session_key().network_anonymization_key(), - enable_ip_based_pooling_, enable_alternative_services_)) { + !pool_->CanUseQuic(key.destination(), + key.session_key().network_anonymization_key(), + enable_alternative_services_)) { return nullptr; } @@ -536,8 +550,20 @@ bool HttpStreamPool::JobController::MaybeStartAlternativeJob() { } bool HttpStreamPool::JobController::CanUseExistingQuicSession() { - return pool_->CanUseExistingQuicSession( - origin_quic_key_, enable_ip_based_pooling_, enable_alternative_services_); + return pool_->CanUseExistingQuicSession(origin_quic_key_, + enable_alternative_services_); +} + +void HttpStreamPool::JobController::StartAltSvcQuicPreconnect() { + Group& group = pool_->GetOrCreateGroup(origin_stream_key_, origin_quic_key_); + if (preconnect_callback_.is_null()) { + preconnect_callback_ = pool_->GetAltSvcQuicPreconnectCallback(); + } + origin_job_ = std::make_unique(this, JobType::kAltSvcQuicPreconnect, + &group, origin_quic_version_, + NextProto::kProtoQUIC, net_log_, + /*num_streams=*/1); + origin_job_->Start(); } void HttpStreamPool::JobController::CallRequestCompleteAndStreamReady( diff --git a/naiveproxy/src/net/http/http_stream_pool_job_controller.h b/naiveproxy/src/net/http/http_stream_pool_job_controller.h index bb5794d1fd..5a8d18009d 100644 --- a/naiveproxy/src/net/http/http_stream_pool_job_controller.h +++ b/naiveproxy/src/net/http/http_stream_pool_job_controller.h @@ -44,7 +44,7 @@ class HttpStreamPool::JobController : public HttpStreamPool::Job::Delegate, HttpStreamPoolRequestInfo request_info, RequestPriority priority, std::vector allowed_bad_certs, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool enable_alternative_services); JobController(const JobController&) = delete; @@ -65,7 +65,7 @@ class HttpStreamPool::JobController : public HttpStreamPool::Job::Delegate, RespectLimits respect_limits() const override; const std::vector& allowed_bad_certs() const override; - bool enable_ip_based_pooling() const override; + bool enable_ip_based_pooling_for_h2() const override; bool enable_alternative_services() const override; NextProtoSet allowed_alpns() const override; const ProxyInfo& proxy_info() const override; @@ -138,6 +138,10 @@ class HttpStreamPool::JobController : public HttpStreamPool::Job::Delegate, // Returns true when a QUIC session can be used for the request. bool CanUseExistingQuicSession(); + // Starts a QUIC preconnect job when an alternative service is advertised via + // Alt-Svc but the current request is not using it. + void StartAltSvcQuicPreconnect(); + // Calls the request's Complete() and tells the delegate that `stream` is // ready. Used when there is an existing QUIC/SPDY session that can serve // the request. @@ -177,7 +181,7 @@ class HttpStreamPool::JobController : public HttpStreamPool::Job::Delegate, const raw_ptr pool_; RequestPriority priority_; const std::vector allowed_bad_certs_; - const bool enable_ip_based_pooling_; + const bool enable_ip_based_pooling_for_h2_; const bool enable_alternative_services_; const RespectLimits respect_limits_; NextProtoSet allowed_alpns_; diff --git a/naiveproxy/src/net/http/http_stream_pool_quic_attempt.cc b/naiveproxy/src/net/http/http_stream_pool_quic_attempt.cc index cb6e1063a6..026df00dbe 100644 --- a/naiveproxy/src/net/http/http_stream_pool_quic_attempt.cc +++ b/naiveproxy/src/net/http/http_stream_pool_quic_attempt.cc @@ -9,13 +9,13 @@ #include "base/task/sequenced_task_runner.h" #include "base/time/time.h" +#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_id_helper.h" #include "base/values.h" #include "net/base/connection_endpoint_metadata.h" #include "net/base/ip_endpoint.h" #include "net/base/net_error_details.h" #include "net/base/net_errors.h" -#include "net/base/tracing.h" #include "net/dns/host_resolver.h" #include "net/dns/public/host_resolver_results.h" #include "net/http/http_network_session.h" @@ -25,6 +25,8 @@ #include "net/log/net_log_source_type.h" #include "net/log/net_log_with_source.h" #include "net/quic/quic_session_alias_key.h" +#include "net/quic/quic_session_attempt_manager.h" +#include "net/quic/quic_session_attempt_request.h" #include "net/quic/quic_session_key.h" #include "net/quic/quic_session_pool.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h" @@ -62,30 +64,8 @@ HttpStreamPool::QuicAttempt::QuicAttempt(AttemptManager* manager, NetLogEventType::HTTP_STREAM_POOL_ATTEMPT_MANAGER_QUIC_ATTEMPT_BOUND, net_log_.source()); - SSLConfig ssl_config; - ssl_config.disable_cert_verification_network_fetches = - stream_key().disable_cert_network_fetches(); - int cert_verify_flags = ssl_config.GetCertVerifyFlags(); - - base::TimeTicks dns_resolution_start_time = - manager_->dns_resolution_start_time(); - // The DNS resolution end time could be null when the resolution is still - // ongoing. In that case, use the current time to make sure the connect - // start time is already greater than the DNS resolution end time. - base::TimeTicks dns_resolution_end_time = - manager_->dns_resolution_end_time().is_null() - ? base::TimeTicks::Now() - : manager_->dns_resolution_end_time(); - - std::set dns_aliases = - manager_->service_endpoint_request()->GetDnsAliasResults(); - - session_attempt_ = GetQuicSessionPool()->CreateSessionAttempt( - this, GetKey().session_key(), quic_endpoint_, cert_verify_flags, - dns_resolution_start_time, dns_resolution_end_time, - /*use_dns_aliases=*/true, std::move(dns_aliases), - manager_->CalculateMultiplexedSessionCreationInitiator(), - /*connection_management_config=*/std::nullopt); + request_ = quic_session_pool()->session_attempt_manager()->CreateRequest( + quic_session_alias_key()); } HttpStreamPool::QuicAttempt::~QuicAttempt() { @@ -103,8 +83,31 @@ void HttpStreamPool::QuicAttempt::Start() { manager_->MaybeRunTcpBasedAttemptDelayTimer(); } - int rv = session_attempt_->Start(base::BindOnce( - &QuicAttempt::OnSessionAttemptComplete, weak_ptr_factory_.GetWeakPtr())); + SSLConfig ssl_config; + ssl_config.disable_cert_verification_network_fetches = + stream_key().disable_cert_network_fetches(); + int cert_verify_flags = ssl_config.GetCertVerifyFlags(); + + base::TimeTicks dns_resolution_start_time = + manager_->dns_resolution_start_time(); + // The DNS resolution end time could be null when the resolution is still + // ongoing. In that case, use the current time to make sure the connect + // start time is already greater than the DNS resolution end time. + base::TimeTicks dns_resolution_end_time = + manager_->dns_resolution_end_time().is_null() + ? base::TimeTicks::Now() + : manager_->dns_resolution_end_time(); + + std::set dns_aliases = + manager_->service_endpoint_request()->GetDnsAliasResults(); + int rv = request_->RequestSession( + quic_endpoint_, cert_verify_flags, dns_resolution_start_time, + dns_resolution_end_time, /*use_dns_aliases=*/true, std::move(dns_aliases), + manager_->CalculateMultiplexedSessionCreationInitiator(), + /*connection_management_config=*/std::nullopt, net_log_, + base::BindOnce(&QuicAttempt::OnSessionAttemptComplete, + weak_ptr_factory_.GetWeakPtr())); + if (rv == ERR_IO_PENDING) { slow_timer_.Start(FROM_HERE, HttpStreamPool::GetConnectionAttemptDelay(), base::BindOnce(&QuicAttempt::OnSessionAttemptSlow, @@ -114,18 +117,6 @@ void HttpStreamPool::QuicAttempt::Start() { } } -QuicSessionPool* HttpStreamPool::QuicAttempt::GetQuicSessionPool() { - return manager_->group()->http_network_session()->quic_session_pool(); -} - -const QuicSessionAliasKey& HttpStreamPool::QuicAttempt::GetKey() { - return manager_->group()->quic_session_alias_key(); -} - -const NetLogWithSource& HttpStreamPool::QuicAttempt::GetNetLog() { - return net_log_; -} - base::Value::Dict HttpStreamPool::QuicAttempt::GetInfoAsValue() const { base::Value::Dict dict; dict.Set("quic_version", @@ -143,6 +134,15 @@ const HttpStreamKey& HttpStreamPool::QuicAttempt::stream_key() const { return manager_->group()->stream_key(); } +const QuicSessionAliasKey& HttpStreamPool::QuicAttempt::quic_session_alias_key() + const { + return manager_->group()->quic_session_alias_key(); +} + +QuicSessionPool* HttpStreamPool::QuicAttempt::quic_session_pool() { + return manager_->group()->http_network_session()->quic_session_pool(); +} + void HttpStreamPool::QuicAttempt::OnSessionAttemptSlow() { CHECK(!is_slow_); is_slow_ = true; @@ -159,17 +159,17 @@ void HttpStreamPool::QuicAttempt::OnSessionAttemptComplete(int rv) { } if (rv == OK && - !GetQuicSessionPool()->has_quic_ever_worked_on_current_network()) { - GetQuicSessionPool()->set_has_quic_ever_worked_on_current_network(true); + !quic_session_pool()->has_quic_ever_worked_on_current_network()) { + quic_session_pool()->set_has_quic_ever_worked_on_current_network(true); } result_ = rv; QuicAttemptOutcome outcome(rv); - if (session_attempt_) { - outcome.session = session_attempt_->session(); - session_attempt_->PopulateNetErrorDetails(&outcome.error_details); + if (request_) { + outcome.session = request_->session(); + outcome.error_details = request_->error_details(); } - session_attempt_.reset(); + request_.reset(); manager_->OnQuicAttemptComplete(std::move(outcome)); // `this` is deleted. } diff --git a/naiveproxy/src/net/http/http_stream_pool_quic_attempt.h b/naiveproxy/src/net/http/http_stream_pool_quic_attempt.h index 585d50af22..2508924ed1 100644 --- a/naiveproxy/src/net/http/http_stream_pool_quic_attempt.h +++ b/naiveproxy/src/net/http/http_stream_pool_quic_attempt.h @@ -11,13 +11,13 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/timer/timer.h" +#include "base/trace_event/trace_event.h" #include "base/values.h" #include "net/base/ip_endpoint.h" -#include "net/base/tracing.h" #include "net/dns/host_resolver.h" #include "net/http/http_stream_pool.h" #include "net/http/http_stream_pool_attempt_manager.h" -#include "net/quic/quic_session_attempt.h" +#include "net/quic/quic_session_attempt_request.h" #include "net/quic/quic_session_pool.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h" @@ -28,7 +28,7 @@ class QuicSessionAliasKey; // Handles a single QUIC session attempt for HttpStreamPool::AttemptManager. // Owned by an AttemptManager. -class HttpStreamPool::QuicAttempt : public QuicSessionAttempt::Delegate { +class HttpStreamPool::QuicAttempt { public: // `manager` must outlive `this`. QuicAttempt(AttemptManager* manager, QuicEndpoint quic_endpoint); @@ -36,15 +36,10 @@ class HttpStreamPool::QuicAttempt : public QuicSessionAttempt::Delegate { QuicAttempt(const QuicAttempt&) = delete; QuicAttempt& operator=(const QuicAttempt&) = delete; - ~QuicAttempt() override; + ~QuicAttempt(); void Start(); - // QuicSessionAttempt::Delegate implementation. - QuicSessionPool* GetQuicSessionPool() override; - const QuicSessionAliasKey& GetKey() override; - const NetLogWithSource& GetNetLog() override; - // Retrieves information on the current state of `this` as a base::Value. base::Value::Dict GetInfoAsValue() const; @@ -56,6 +51,8 @@ class HttpStreamPool::QuicAttempt : public QuicSessionAttempt::Delegate { private: const HttpStreamKey& stream_key() const; + const QuicSessionAliasKey& quic_session_alias_key() const; + QuicSessionPool* quic_session_pool(); void OnSessionAttemptSlow(); void OnSessionAttemptComplete(int rv); @@ -67,7 +64,7 @@ class HttpStreamPool::QuicAttempt : public QuicSessionAttempt::Delegate { const perfetto::Track track_; const perfetto::Flow flow_; - std::unique_ptr session_attempt_; + std::unique_ptr request_; base::OneShotTimer slow_timer_; bool is_slow_ = false; std::optional result_; diff --git a/naiveproxy/src/net/http/http_stream_pool_tcp_based_attempt.cc b/naiveproxy/src/net/http/http_stream_pool_tcp_based_attempt.cc index 5b4091b384..a37bea24e8 100644 --- a/naiveproxy/src/net/http/http_stream_pool_tcp_based_attempt.cc +++ b/naiveproxy/src/net/http/http_stream_pool_tcp_based_attempt.cc @@ -12,13 +12,13 @@ #include "base/task/sequenced_task_runner.h" #include "base/time/time.h" #include "base/timer/timer.h" +#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_id_helper.h" #include "base/types/expected.h" #include "base/values.h" #include "net/base/completion_once_callback.h" #include "net/base/host_port_pair.h" #include "net/base/ip_endpoint.h" -#include "net/base/tracing.h" #include "net/http/http_stream_key.h" #include "net/http/http_stream_pool.h" #include "net/http/http_stream_pool_attempt_manager.h" @@ -60,6 +60,8 @@ std::string_view GetHistogramSuffixForTcpBasedAttemptCancel( return "ExistingSpdySession"; case StreamSocketCloseReason::kUsingExistingQuicSession: return "ExistingQuicSession"; + case StreamSocketCloseReason::kAttemptManagerDraining: + return "AttemptManagerDraining"; case StreamSocketCloseReason::kUnspecified: case StreamSocketCloseReason::kCloseAllConnections: case StreamSocketCloseReason::kIpAddressChanged: diff --git a/naiveproxy/src/net/http/http_stream_pool_tcp_based_attempt.h b/naiveproxy/src/net/http/http_stream_pool_tcp_based_attempt.h index 9e5ada5a13..0e8b6d1406 100644 --- a/naiveproxy/src/net/http/http_stream_pool_tcp_based_attempt.h +++ b/naiveproxy/src/net/http/http_stream_pool_tcp_based_attempt.h @@ -10,11 +10,11 @@ #include "base/time/time.h" #include "base/timer/timer.h" +#include "base/trace_event/trace_event.h" #include "base/types/expected.h" #include "base/values.h" #include "net/base/completion_once_callback.h" #include "net/base/ip_endpoint.h" -#include "net/base/tracing.h" #include "net/http/http_stream_pool.h" #include "net/socket/stream_attempt.h" #include "net/socket/stream_socket_close_reason.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 index 96cac006db..32b7d56830 100644 --- a/naiveproxy/src/net/http/http_stream_pool_test_util.cc +++ b/naiveproxy/src/net/http/http_stream_pool_test_util.cc @@ -158,7 +158,7 @@ int FakeServiceEndpointRequest::Start(Delegate* delegate) { return resolution_.start_result(); } -const std::vector& +base::span FakeServiceEndpointRequest::GetEndpointResults() { return resolution_.endpoints(); } @@ -441,7 +441,7 @@ TestJobDelegate::allowed_bad_certs() const { return allowed_bad_certs_; } -bool TestJobDelegate::enable_ip_based_pooling() const { +bool TestJobDelegate::enable_ip_based_pooling_for_h2() const { return true; } diff --git a/naiveproxy/src/net/http/http_stream_pool_test_util.h b/naiveproxy/src/net/http/http_stream_pool_test_util.h index 3eb5866eca..1f4fe941c7 100644 --- a/naiveproxy/src/net/http/http_stream_pool_test_util.h +++ b/naiveproxy/src/net/http/http_stream_pool_test_util.h @@ -104,7 +104,7 @@ class FakeServiceEndpointRequest : public HostResolver::ServiceEndpointRequest { // HostResolver::ServiceEndpointRequest methods: int Start(Delegate* delegate) override; - const std::vector& GetEndpointResults() override; + base::span GetEndpointResults() override; const std::set& GetDnsAliasResults() override; bool EndpointsCryptoReady() override; ResolveErrorInfo GetResolveErrorInfo() override; @@ -327,7 +327,7 @@ class TestJobDelegate : public HttpStreamPool::Job::Delegate { HttpStreamPool::RespectLimits respect_limits() const override; const std::vector& allowed_bad_certs() const override; - bool enable_ip_based_pooling() const override; + bool enable_ip_based_pooling_for_h2() const override; bool enable_alternative_services() const override; NextProtoSet allowed_alpns() const override; const ProxyInfo& proxy_info() const override; diff --git a/naiveproxy/src/net/http/mock_gssapi_library_posix.cc b/naiveproxy/src/net/http/mock_gssapi_library_posix.cc index cc21d4e5ed..30e7cf446b 100644 --- a/naiveproxy/src/net/http/mock_gssapi_library_posix.cc +++ b/naiveproxy/src/net/http/mock_gssapi_library_posix.cc @@ -2,13 +2,9 @@ // 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/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "net/http/mock_gssapi_library_posix.h" +#include "base/compiler_specific.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "testing/gtest/include/gtest/gtest.h" @@ -83,7 +79,7 @@ void SetBuffer(gss_buffer_t dest, const void* src, size_t length) { dest->length = length; if (length) { dest->value = new char[length]; - memcpy(dest->value, src, length); + UNSAFE_TODO(memcpy(dest->value, src, length)); } } @@ -436,9 +432,9 @@ OM_uint32 MockGSSAPILibrary::init_sec_context( } else { EXPECT_EQ(input_token->length, security_query.expected_input_token.length); if (input_token->length) { - EXPECT_EQ(0, memcmp(input_token->value, - security_query.expected_input_token.value, - input_token->length)); + UNSAFE_TODO(EXPECT_EQ(0, memcmp(input_token->value, + security_query.expected_input_token.value, + input_token->length))); } } CopyBuffer(output_token, &security_query.output_token); diff --git a/naiveproxy/src/net/http/mock_http_cache.cc b/naiveproxy/src/net/http/mock_http_cache.cc index 0fa4ba9878..51623cfb4b 100644 --- a/naiveproxy/src/net/http/mock_http_cache.cc +++ b/naiveproxy/src/net/http/mock_http_cache.cc @@ -80,13 +80,13 @@ base::Time MockDiskEntry::GetLastUsed() const { return base::Time::Now(); } -int32_t MockDiskEntry::GetDataSize(int index) const { +int64_t MockDiskEntry::GetDataSize(int index) const { DCHECK(index >= 0 && index < kNumCacheEntryDataIndices); - return static_cast(data_[index].size()); + return static_cast(data_[index].size()); } int MockDiskEntry::ReadData(int index, - int offset, + int64_t offset, IOBuffer* buf, int buf_len, CompletionOnceCallback callback) { @@ -100,11 +100,14 @@ int MockDiskEntry::ReadData(int index, if (offset < 0 || offset > static_cast(data_[index].size())) { return ERR_FAILED; } - if (static_cast(offset) == data_[index].size()) { + + // `offset` is not larger than int max so it's in size_t range. + if (base::checked_cast(offset) == data_[index].size()) { return 0; } - int num = std::min(buf_len, static_cast(data_[index].size()) - offset); + int num = std::min(buf_len, static_cast(data_[index].size()) - + base::checked_cast(offset)); buf->span().copy_prefix_from(base::span(data_[index]) .subspan(base::checked_cast(offset), base::checked_cast(num))); @@ -132,7 +135,7 @@ void MockDiskEntry::ResumeDiskEntryOperation() { } int MockDiskEntry::WriteData(int index, - int offset, + int64_t offset, IOBuffer* buf, int buf_len, CompletionOnceCallback callback, @@ -150,8 +153,13 @@ int MockDiskEntry::WriteData(int index, return ERR_FAILED; } - DCHECK_LT(offset + buf_len, kMaxMockCacheEntrySize); - if (offset + buf_len > max_file_size_ && index == 1) { + if (offset + buf_len > kMaxMockCacheEntrySize) { + return net::ERR_INVALID_ARGUMENT; + } + + // `offset` is not larger than int max so it's in size_t range. + if (base::checked_cast(offset) + buf_len > max_file_size_ && + index == 1) { return ERR_FAILED; } diff --git a/naiveproxy/src/net/http/mock_http_cache.h b/naiveproxy/src/net/http/mock_http_cache.h index 21db02e274..f9211fa3a1 100644 --- a/naiveproxy/src/net/http/mock_http_cache.h +++ b/naiveproxy/src/net/http/mock_http_cache.h @@ -61,14 +61,14 @@ class MockDiskEntry : public disk_cache::Entry, void Close() override; std::string GetKey() const override; base::Time GetLastUsed() const override; - int32_t GetDataSize(int index) const override; + int64_t GetDataSize(int index) const override; int ReadData(int index, - int offset, + int64_t offset, IOBuffer* buf, int buf_len, CompletionOnceCallback callback) override; int WriteData(int index, - int offset, + int64_t offset, IOBuffer* buf, int buf_len, CompletionOnceCallback callback, diff --git a/naiveproxy/src/net/http/no_vary_search_cache_storage.cc b/naiveproxy/src/net/http/no_vary_search_cache_storage.cc index a5efcb3b5e..fecb790498 100644 --- a/naiveproxy/src/net/http/no_vary_search_cache_storage.cc +++ b/naiveproxy/src/net/http/no_vary_search_cache_storage.cc @@ -25,6 +25,7 @@ #include "base/task/thread_pool.h" #include "base/time/time.h" #include "base/types/cxx23_to_underlying.h" +#include "net/base/features.h" #include "net/base/pickle.h" #include "net/base/pickle_base_types.h" #include "net/base/pickle_traits.h" @@ -355,6 +356,12 @@ class NoVarySearchCacheStorage::Loader final { if (!operations_->Init()) { return GiveUp(Result::kOperationsInitFailed); } + + if (features::kHttpCacheNoVarySearchFakePersistence.Get()) { + std::ignore = StartFromScratch(Result::kSnapshotLoadFailed); + return base::unexpected(LoadFailed::kCannotJournal); + } + auto maybe_load_result = operations_->Load(kSnapshotFilename, kMaxFileSize); if (!maybe_load_result.has_value()) { base::UmaHistogramExactLinear("HttpCache.NoVarySearch.SnapshotLoadError", diff --git a/naiveproxy/src/net/http/no_vary_search_cache_storage_file_operations.cc b/naiveproxy/src/net/http/no_vary_search_cache_storage_file_operations.cc index 09644058c4..80e4a5e880 100644 --- a/naiveproxy/src/net/http/no_vary_search_cache_storage_file_operations.cc +++ b/naiveproxy/src/net/http/no_vary_search_cache_storage_file_operations.cc @@ -66,6 +66,11 @@ bool IsAcceptableFilename(std::string_view filename) { filename != "." && filename != ".."; } +// Logs `error` to histogram `name`. +void UmaHistogramFileError(std::string_view name, base::File::Error error) { + base::UmaHistogramExactLinear(name, -error, -FILE_ERROR_MAX); +} + // Creates the directory `path` and all non-existent parent directories if // possible. Reports the results to histograms using `histogram_suffix`. bool CreateDirectoryIfNotExists(const base::FilePath& path, @@ -91,10 +96,10 @@ bool CreateDirectoryIfNotExists(const base::FilePath& path, base::File::Error error; if (!base::CreateDirectoryAndGetError(path, &error)) { - base::UmaHistogramExactLinear( + UmaHistogramFileError( base::StrCat({"HttpCache.NoVarySearch.DirectoryCreateError.", histogram_suffix}), - -error, -FILE_ERROR_MAX); + error); return CreateDirectoryResult::kCreateFailed; } @@ -119,9 +124,8 @@ bool DeleteLoggingErrors( return true; } - base::UmaHistogramExactLinear(base::StrCat(histogram_name_parts), - -base::File::GetLastFileError(), - -FILE_ERROR_MAX); + UmaHistogramFileError(base::StrCat(histogram_name_parts), + base::File::GetLastFileError()); return false; } @@ -167,10 +171,10 @@ void RenameOrDeleteIfExists(const base::FilePath& old_path, // just give up. This rename functionality is purely best-effort and it's // not critical if it fails, as the NoVarySearchCache will just be // recreated. - base::UmaHistogramExactLinear( + UmaHistogramFileError( base::StrCat( {"HttpCache.NoVarySearch.InitRenameError.", histogram_suffix}), - -error, -FILE_ERROR_MAX); + error); return RenameResult::kRenameFailed; } @@ -183,20 +187,6 @@ void RenameOrDeleteIfExists(const base::FilePath& old_path, result); } -constexpr std::string_view kSnapshotFilename = - NoVarySearchCacheStorage::kSnapshotFilename; - -void MoveOldFilesIfNeeded(const base::FilePath& parent_path, - const base::FilePath& path) { - static constexpr std::string_view kJournalFilename = - NoVarySearchCacheStorage::kJournalFilename; - - RenameOrDeleteIfExists(parent_path.AppendASCII(kSnapshotFilename), - path.AppendASCII(kSnapshotFilename), "Snapshot"); - RenameOrDeleteIfExists(parent_path.AppendASCII(kJournalFilename), - path.AppendASCII(kJournalFilename), "Journal"); -} - void DeleteIfExists(const base::FilePath& path, std::string_view histogram_suffix) { // base::DeleteFile actually already tests if the file exists, but since it @@ -209,12 +199,48 @@ void DeleteIfExists(const base::FilePath& path, path, {"HttpCache.NoVarySearch.DeleteIfExistsError.", histogram_suffix}); } -void DeleteTempFilesIfNeeded(const base::FilePath& parent_path, - const base::FilePath& path) { +constexpr std::string_view kSnapshotFilename = + NoVarySearchCacheStorage::kSnapshotFilename; + +void DeleteTempFileIfNeeded(const base::FilePath& path, + std::string_view histogram_suffix) { const std::string snapshot_tempfile = base::StrCat({kSnapshotFilename, "-new"}); - DeleteIfExists(parent_path.AppendASCII(snapshot_tempfile), "Parent"); - DeleteIfExists(path.AppendASCII(snapshot_tempfile), "NoVarySearch"); + DeleteIfExists(path.AppendASCII(snapshot_tempfile), histogram_suffix); +} + +void MoveOldFilesIfNeededBetween(const base::FilePath& old_path, + const base::FilePath& new_path, + std::string_view old_path_histogram_suffix) { + static constexpr std::string_view kJournalFilename = + NoVarySearchCacheStorage::kJournalFilename; + + RenameOrDeleteIfExists( + old_path.AppendASCII(kSnapshotFilename), + new_path.AppendASCII(kSnapshotFilename), + base::StrCat({old_path_histogram_suffix, ".Snapshot"})); + RenameOrDeleteIfExists(old_path.AppendASCII(kJournalFilename), + new_path.AppendASCII(kJournalFilename), + base::StrCat({old_path_histogram_suffix, ".Journal"})); + DeleteTempFileIfNeeded(old_path, old_path_histogram_suffix); +} + +void MoveOldFilesIfNeeded(const base::FilePath& legacy_path, + const base::FilePath& legacy_subdirectory, + const base::FilePath& path) { + if (base::DirectoryExists(legacy_subdirectory)) { + // We should do a two-step move to ensure nothing is left behind. + MoveOldFilesIfNeededBetween(legacy_path, legacy_subdirectory, "Parent"); + MoveOldFilesIfNeededBetween(legacy_subdirectory, path, "NoVarySearch"); + if (!base::DeleteFile(legacy_subdirectory)) { + UmaHistogramFileError( + "HttpCache.NoVarySearch.LegacySubdirectoryDeleteError", + base::File::GetLastFileError()); + } + } else { + // A one-step move is sufficient. + MoveOldFilesIfNeededBetween(legacy_path, path, "Parent"); + } } #if BUILDFLAG(IS_WIN) @@ -271,8 +297,9 @@ class RealFileOperations : public FileOperations { public: using enum base::File::Flags; - explicit RealFileOperations(const base::FilePath& path) - : parent_path_(path), path_(path.AppendASCII(kNoVarySearchDirName)) { + explicit RealFileOperations(const base::FilePath& dedicated_path, + const base::FilePath& legacy_path) + : legacy_path_(legacy_path), path_(dedicated_path) { // It's normal to construct this on a different thread than it will be used. DETACH_FROM_SEQUENCE(sequence_checker_); } @@ -283,20 +310,23 @@ class RealFileOperations : public FileOperations { bool Init() override { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!CreateDirectoryIfNotExists(parent_path_, - /*histogram_suffix=*/"Parent") || - !CreateDirectoryIfNotExists(path_, - /*histogram_suffix=*/"NoVarySearch")) { + const base::FilePath legacy_subdirectory = + legacy_path_.AppendASCII(kLegacyNoVarySearchDirName); + + if (!CreateDirectoryIfNotExists(path_, + /*histogram_suffix=*/"Dedicated")) { return false; } - // TODO(https://crbug.com/421927600): Remove this in December 2025 provided - // the kSourceDidNotExist bucket of the - // HttpCache.NoVarySearch.RenameOrDeleteResult.Snapshot histogram has - // reached 100%. - MoveOldFilesIfNeeded(parent_path_, path_); + if (base::DirectoryExists(legacy_path_)) { + // TODO(https://crbug.com/421927600): Remove this in December 2025 + // provided the kSourceDidNotExist bucket of the + // HttpCache.NoVarySearch.RenameOrDeleteResult.Snapshot histogram has + // reached 100%. + MoveOldFilesIfNeeded(legacy_path_, legacy_subdirectory, path_); + } - DeleteTempFilesIfNeeded(parent_path_, path_); + DeleteTempFileIfNeeded(path_, "Dedicated"); return true; } @@ -393,8 +423,8 @@ class RealFileOperations : public FileOperations { base::File::Error replace_error = FILE_OK; if (!replace_file_func(temp_path, path, &replace_error)) { - base::UmaHistogramExactLinear("HttpCache.NoVarySearch.ReplaceFileError", - -replace_error, -FILE_ERROR_MAX); + UmaHistogramFileError("HttpCache.NoVarySearch.ReplaceFileError", + replace_error); return base::unexpected(replace_error); } @@ -433,7 +463,11 @@ class RealFileOperations : public FileOperations { return path_.AppendASCII(filename); } - const base::FilePath parent_path_ GUARDED_BY_CONTEXT(sequence_checker_); + // TODO(https://crbug.com/433551601): Remove `legacy_path_` once the + // SourceDidNotExist bucket of all the + // HttpCache.NoVarySearch.RenameOrDeleteResult.{NoVarySearch,Parent}.{Journal,Snapshot} + // histograms has reached 100.00%. + const base::FilePath legacy_path_ GUARDED_BY_CONTEXT(sequence_checker_); const base::FilePath path_ GUARDED_BY_CONTEXT(sequence_checker_); SEQUENCE_CHECKER(sequence_checker_); @@ -459,8 +493,9 @@ NoVarySearchCacheStorageFileOperations:: ~NoVarySearchCacheStorageFileOperations() = default; std::unique_ptr FileOperations::Create( - const base::FilePath& path) { - return std::make_unique(path); + const base::FilePath& dedicated_path, + const base::FilePath& legacy_path) { + return std::make_unique(dedicated_path, legacy_path); } } // namespace net diff --git a/naiveproxy/src/net/http/no_vary_search_cache_storage_file_operations.h b/naiveproxy/src/net/http/no_vary_search_cache_storage_file_operations.h index b6a6c0f527..37585dba79 100644 --- a/naiveproxy/src/net/http/no_vary_search_cache_storage_file_operations.h +++ b/naiveproxy/src/net/http/no_vary_search_cache_storage_file_operations.h @@ -33,7 +33,9 @@ namespace net { // these interfaces, so calls will be devirtualized and may be inlined. class NET_EXPORT NoVarySearchCacheStorageFileOperations { public: - static constexpr char kNoVarySearchDirName[] = "no-vary-search"; + // TODO(https://crbug.com/433551601): Remove this once the rate of migrations + // drops to zero. + static constexpr char kLegacyNoVarySearchDirName[] = "no-vary-search"; // Result of a call to Load(). struct NET_EXPORT LoadResult { @@ -70,10 +72,15 @@ class NET_EXPORT NoVarySearchCacheStorageFileOperations { }; // Creates a NoVarySearchCacheStorageFileOperations object that accesses the - // real file system. All filenames will be treated as relative to a - // subdirectory of `path` named `kNoVarySearchDirName`. + // real file system. All filenames will be treated as relative to + // `dedicated_path`. If there are existing persisted files inside + // `legacy_path` they will be moved to `dedicated_path` during the call to + // Init(). + // TODO(https://crbug.com/433551601): Remove `legacy_path` once the rate of + // migrations drops to zero. static std::unique_ptr Create( - const base::FilePath& path); + const base::FilePath& dedicated_path, + const base::FilePath& legacy_path); NoVarySearchCacheStorageFileOperations( const NoVarySearchCacheStorageFileOperations&) = delete; diff --git a/naiveproxy/src/net/http/proxy_fallback.cc b/naiveproxy/src/net/http/proxy_fallback.cc index d3359aac0a..a8b1b48e9a 100644 --- a/naiveproxy/src/net/http/proxy_fallback.cc +++ b/naiveproxy/src/net/http/proxy_fallback.cc @@ -23,7 +23,7 @@ NET_EXPORT bool CanFalloverToNextProxy(const ProxyChain& proxy_chain, if (const int chain_id = proxy_chain.ip_protection_chain_id(); chain_id != ProxyChain::kNotIpProtectionChainId) { base::UmaHistogramSparse( - base::StrCat({"Net.IpProtection.CanFalloverToNextProxy.Error.Chain", + base::StrCat({"Net.IpProtection.CanFalloverToNextProxy2.Error.Chain", base::NumberToString(chain_id)}), error); } @@ -76,6 +76,23 @@ NET_EXPORT bool CanFalloverToNextProxy(const ProxyChain& proxy_chain, // server (like a captive portal). case ERR_SSL_PROTOCOL_ERROR: return true; + // A failure while establishing a tunnel through the proxy can fail for + // reasons related to the request itself (for instance, failing to resolve + // the hostname of the request) or because of issues with the proxy itself. + // A ProxyDelegate differentiates the two based on response codes and/or + // response headers. The delegate signals a destination-related error by + // returning ERR_PROXY_UNABLE_TO_CONNECT_TO_DESTINATION, which prevents + // fallback. + case ERR_PROXY_UNABLE_TO_CONNECT_TO_DESTINATION: + return false; + case ERR_TUNNEL_CONNECTION_FAILED: + // Tunnel connection failures not indicated by + // ERR_PROXY_UNABLE_TO_CONNECT_TO_DESTINATION are only considered grounds + // for fallback when connecting to an IP Protection proxy. Other browsers + // similarly don't fallback, and some client's PAC configurations rely on + // this for some degree of content blocking. See https://crbug.com/680837 + // for details. + return is_for_ip_protection; case ERR_SOCKS_CONNECTION_HOST_UNREACHABLE: // Remap the SOCKS-specific "host unreachable" error to a more @@ -88,14 +105,6 @@ NET_EXPORT bool CanFalloverToNextProxy(const ProxyChain& proxy_chain, // ERR_ADDRESS_UNREACHABLE. *final_error = ERR_ADDRESS_UNREACHABLE; return false; - - case ERR_TUNNEL_CONNECTION_FAILED: - // A failure while establishing a tunnel to the proxy is only considered - // grounds for fallback when connecting to an IP Protection proxy. Other - // browsers similarly don't fallback, and some client's PAC configurations - // rely on this for some degree of content blocking. See - // https://crbug.com/680837 for details. - return is_for_ip_protection; } return false; } diff --git a/naiveproxy/src/net/http/transport_security_state.cc b/naiveproxy/src/net/http/transport_security_state.cc index 7a8a4d9239..080da71985 100644 --- a/naiveproxy/src/net/http/transport_security_state.cc +++ b/naiveproxy/src/net/http/transport_security_state.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 "net/http/transport_security_state.h" #include @@ -71,19 +66,16 @@ TransportSecurityState::HashedHost HashHost( // Returns true if the intersection of |a| and |b| is not empty. If either // |a| or |b| is empty, returns false. -bool HashesIntersect(const HashValueVector& a, const HashValueVector& b) { - for (const auto& hash : a) { - if (base::Contains(b, hash)) +bool HashesIntersect(const absl::flat_hash_set& a, + const std::vector& b) { + for (const auto& hash : b) { + if (a.contains(hash)) { return true; + } } return false; } -bool AddHash(base::span sha256_hash, HashValueVector& out) { - out.emplace_back(sha256_hash); - return true; -} - // Converts |hostname| from dotted form ("www.google.com") to the form // used in DNS: "\x03www\x06google\x03com", lowercases that, and returns // the result. @@ -218,9 +210,8 @@ bool DecodeHSTSPreload(std::string_view search_hostname, PreloadResult* out) { } HSTSPreloadDecoder decoder( - g_hsts_source->huffman_tree, g_hsts_source->huffman_tree_size, - g_hsts_source->preloaded_data, g_hsts_source->preloaded_bits, - g_hsts_source->root_position); + g_hsts_source->huffman_tree, g_hsts_source->preloaded_data, + g_hsts_source->preloaded_bits, g_hsts_source->root_position); if (!decoder.Decode(hostname, &found)) { DCHECK(false) << "Internal error in DecodeHSTSPreload for hostname " << hostname; @@ -328,7 +319,7 @@ bool TransportSecurityState::ShouldUpgradeToSSL( TransportSecurityState::PKPStatus TransportSecurityState::CheckPublicKeyPins( std::string_view host, bool is_issued_by_known_root, - const HashValueVector& public_key_hashes) { + const std::vector& public_key_hashes) { // Perform pin validation only if the server actually has public key pins. if (!HasPublicKeyPins(host)) { return PKPStatus::OK; @@ -346,7 +337,7 @@ bool TransportSecurityState::HasPublicKeyPins(std::string_view host) { ct::CTRequirementsStatus TransportSecurityState::CheckCTRequirements( std::string_view host, bool is_issued_by_known_root, - const HashValueVector& public_key_hashes, + const std::vector& public_key_hashes, const X509Certificate* validated_certificate_chain, ct::CTPolicyCompliance policy_compliance) { // If CT is emergency disabled, we don't require CT for any host. @@ -396,7 +387,7 @@ void TransportSecurityState::UpdatePinList( void TransportSecurityState::AddHSTSInternal( std::string_view host, TransportSecurityState::STSState::UpgradeMode upgrade_mode, - const base::Time& expiry, + base::Time expiry, bool include_subdomains) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); const std::vector canonicalized_host = CanonicalizeHost(host); @@ -424,8 +415,8 @@ void TransportSecurityState::AddHSTSInternal( } void TransportSecurityState::AddHPKPInternal(std::string_view host, - const base::Time& last_observed, - const base::Time& expiry, + base::Time last_observed, + base::Time expiry, bool include_subdomains, const HashValueVector& hashes) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); @@ -439,7 +430,11 @@ void TransportSecurityState::AddHPKPInternal(std::string_view host, pkp_state.last_observed = last_observed; pkp_state.expiry = expiry; pkp_state.include_subdomains = include_subdomains; - pkp_state.spki_hashes = hashes; + for (const auto& hash : hashes) { + if (hash.tag() == HASH_VALUE_SHA256) { + pkp_state.spki_hashes.insert(hash.sha256hashvalue()); + } + } // Only store new state when HPKP is explicitly enabled. If it is // disabled, remove the state from the enabled hosts. @@ -461,7 +456,7 @@ void TransportSecurityState:: TransportSecurityState::PKPStatus TransportSecurityState::CheckPins( bool is_issued_by_known_root, const TransportSecurityState::PKPState& pkp_state, - const HashValueVector& hashes) { + const std::vector& hashes) { if (pkp_state.CheckPublicKeyPins(hashes)) { return PKPStatus::OK; } @@ -577,14 +572,14 @@ bool TransportSecurityState::AddHSTSHeader(std::string_view host, } void TransportSecurityState::AddHSTS(std::string_view host, - const base::Time& expiry, + base::Time expiry, bool include_subdomains) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); AddHSTSInternal(host, STSState::MODE_FORCE_HTTPS, expiry, include_subdomains); } void TransportSecurityState::AddHPKP(std::string_view host, - const base::Time& expiry, + base::Time expiry, bool include_subdomains, const HashValueVector& hashes) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); @@ -610,9 +605,10 @@ bool TransportSecurityState::IsBuildTimely() { } TransportSecurityState::PKPStatus -TransportSecurityState::CheckPublicKeyPinsImpl(std::string_view host, - bool is_issued_by_known_root, - const HashValueVector& hashes) { +TransportSecurityState::CheckPublicKeyPinsImpl( + std::string_view host, + bool is_issued_by_known_root, + const std::vector& hashes) { PKPState pkp_state; bool found_state = GetPKPState(host, &pkp_state); @@ -679,18 +675,10 @@ bool TransportSecurityState::GetStaticPKPState(std::string_view host, pkp_result->include_subdomains = iter->second.second; const PinSet* pinset = iter->second.first; for (const auto& hash : pinset->static_spki_hashes()) { - // If the update is malformed, it's preferable to skip the hash than - // crash. - if (hash.size() == crypto::hash::kSha256Size) { - AddHash(hash, pkp_result->spki_hashes); - } + pkp_result->spki_hashes.insert(hash); } for (const auto& hash : pinset->bad_static_spki_hashes()) { - // If the update is malformed, it's preferable to skip the hash than - // crash. - if (hash.size() == 32) { - AddHash(hash, pkp_result->bad_spki_hashes); - } + pkp_result->bad_spki_hashes.insert(hash); } return true; } @@ -705,8 +693,9 @@ bool TransportSecurityState::GetStaticPKPState(std::string_view host, search_hostname = search_hostname.substr(dot_pos + 1); } } else if (DecodeHSTSPreload(host, &result) && result.has_pins) { - if (result.pinset_id >= g_hsts_source->pinsets_count) + if (result.pinset_id >= g_hsts_source->pinsets.size()) { return false; + } pkp_result->domain = host.substr(result.hostname_offset); pkp_result->include_subdomains = result.pkp_include_subdomains; @@ -715,23 +704,11 @@ bool TransportSecurityState::GetStaticPKPState(std::string_view host, const TransportSecurityStateSource::Pinset* pinset = &g_hsts_source->pinsets[result.pinset_id]; - if (pinset->accepted_pins) { - const char* const* sha256_hash = pinset->accepted_pins; - while (*sha256_hash) { - AddHash(UNSAFE_TODO(base::as_bytes(base::span( - *sha256_hash, crypto::hash::kSha256Size))), - pkp_result->spki_hashes); - sha256_hash++; - } + for (const SHA256HashValue* hash : pinset->accepted_pins) { + pkp_result->spki_hashes.insert(*hash); } - if (pinset->rejected_pins) { - const char* const* sha256_hash = pinset->rejected_pins; - while (*sha256_hash) { - AddHash(UNSAFE_TODO(base::as_bytes(base::span( - *sha256_hash, crypto::hash::kSha256Size))), - pkp_result->bad_spki_hashes); - sha256_hash++; - } + for (const SHA256HashValue* hash : pinset->rejected_pins) { + pkp_result->bad_spki_hashes.insert(*hash); } return true; } @@ -869,8 +846,8 @@ TransportSecurityState::PKPState::~PKPState() = default; TransportSecurityState::PinSet::PinSet( std::string name, - std::vector> static_spki_hashes, - std::vector> bad_static_spki_hashes) + std::vector static_spki_hashes, + std::vector bad_static_spki_hashes) : name_(std::move(name)), static_spki_hashes_(std::move(static_spki_hashes)), bad_static_spki_hashes_(std::move(bad_static_spki_hashes)) {} @@ -886,7 +863,7 @@ TransportSecurityState::PinSetInfo::PinSetInfo(std::string hostname, include_subdomains_(std::move(include_subdomains)) {} bool TransportSecurityState::PKPState::CheckPublicKeyPins( - const HashValueVector& hashes) const { + const std::vector& hashes) const { // Validate that hashes is not empty. By the time this code is called (in // production), that should never happen, but it's good to be defensive. // And, hashes *can* be empty in some test scenarios. @@ -910,7 +887,7 @@ bool TransportSecurityState::PKPState::CheckPublicKeyPins( } bool TransportSecurityState::PKPState::HasPublicKeyPins() const { - return spki_hashes.size() > 0 || bad_spki_hashes.size() > 0; + return !spki_hashes.empty() || !bad_spki_hashes.empty(); } bool TransportSecurityState::IsStaticPKPListTimely() const { diff --git a/naiveproxy/src/net/http/transport_security_state.h b/naiveproxy/src/net/http/transport_security_state.h index 9903e338bd..1307572dc2 100644 --- a/naiveproxy/src/net/http/transport_security_state.h +++ b/naiveproxy/src/net/http/transport_security_state.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "base/feature_list.h" #include "base/functional/callback.h" @@ -31,6 +32,7 @@ #include "net/http/transport_security_state_source.h" #include "net/log/net_log_with_source.h" #include "net/net_buildflags.h" +#include "third_party/abseil-cpp/absl/container/flat_hash_set.h" namespace net { @@ -160,12 +162,12 @@ class NET_EXPORT TransportSecurityState { base::Time expiry; // Optional; hashes of pinned SubjectPublicKeyInfos. - HashValueVector spki_hashes; + absl::flat_hash_set spki_hashes; // Optional; hashes of static known-bad SubjectPublicKeyInfos which MUST // NOT intersect with the set of SPKIs in the TLS server's certificate // chain. - HashValueVector bad_spki_hashes; + absl::flat_hash_set bad_spki_hashes; // Are subdomains subject to this policy state? bool include_subdomains = false; @@ -190,7 +192,7 @@ class NET_EXPORT TransportSecurityState { // // |bad_static_spki_hashes| contains public keys that we don't want to // trust. - bool CheckPublicKeyPins(const HashValueVector& hashes) const; + bool CheckPublicKeyPins(const std::vector& hashes) const; // Returns true if any of the HashValueVectors |static_spki_hashes|, // |bad_static_spki_hashes|, or |dynamic_spki_hashes| contains any @@ -201,23 +203,23 @@ class NET_EXPORT TransportSecurityState { class NET_EXPORT PinSet { public: PinSet(std::string name, - std::vector> static_spki_hashes, - std::vector> bad_static_spki_hashes); + std::vector static_spki_hashes, + std::vector bad_static_spki_hashes); PinSet(const PinSet& other); ~PinSet(); const std::string& name() const { return name_; } - const std::vector>& static_spki_hashes() const { + const std::vector& static_spki_hashes() const { return static_spki_hashes_; } - const std::vector>& bad_static_spki_hashes() const { + const std::vector& bad_static_spki_hashes() const { return bad_static_spki_hashes_; } private: std::string name_; - std::vector> static_spki_hashes_; - std::vector> bad_static_spki_hashes_; + std::vector static_spki_hashes_; + std::vector bad_static_spki_hashes_; }; struct NET_EXPORT PinSetInfo { @@ -259,9 +261,10 @@ class NET_EXPORT TransportSecurityState { bool ShouldUpgradeToSSL(std::string_view host, bool is_top_level_nav, const NetLogWithSource& net_log = NetLogWithSource()); - PKPStatus CheckPublicKeyPins(std::string_view host, - bool is_issued_by_known_root, - const HashValueVector& hashes); + PKPStatus CheckPublicKeyPins( + std::string_view host, + bool is_issued_by_known_root, + const std::vector& public_key_hashes); bool HasPublicKeyPins(std::string_view host); // Returns CT_REQUIREMENTS_NOT_MET if a connection violates CT policy @@ -281,7 +284,7 @@ class NET_EXPORT TransportSecurityState { ct::CTRequirementsStatus CheckCTRequirements( std::string_view host, bool is_issued_by_known_root, - const HashValueVector& public_key_hashes, + const std::vector& public_key_hashes, const X509Certificate* validated_certificate_chain, ct::CTPolicyCompliance policy_compliance); @@ -383,13 +386,13 @@ class NET_EXPORT TransportSecurityState { // Adds explicitly-specified data as if it was processed from an // HSTS header (used for net-internals and unit tests). void AddHSTS(std::string_view host, - const base::Time& expiry, + base::Time expiry, bool include_subdomains); // Adds explicitly-specified data as if it was processed from an HPKP header. // Note: dynamic PKP data is not persisted. void AddHPKP(std::string_view host, - const base::Time& expiry, + base::Time expiry, bool include_subdomains, const HashValueVector& hashes); @@ -440,7 +443,7 @@ class NET_EXPORT TransportSecurityState { // Helper method for actually checking pins. PKPStatus CheckPublicKeyPinsImpl(std::string_view host, bool is_issued_by_known_root, - const HashValueVector& hashes); + const std::vector& hashes); // If a Delegate is present, notify it that the internal state has // changed. @@ -452,11 +455,11 @@ class NET_EXPORT TransportSecurityState { // The new state for |host| is persisted using the Delegate (if any). void AddHSTSInternal(std::string_view host, STSState::UpgradeMode upgrade_mode, - const base::Time& expiry, + base::Time expiry, bool include_subdomains); void AddHPKPInternal(std::string_view host, - const base::Time& last_observed, - const base::Time& expiry, + base::Time last_observed, + base::Time expiry, bool include_subdomains, const HashValueVector& hashes); @@ -464,7 +467,7 @@ class NET_EXPORT TransportSecurityState { // satisfies the pins in |pkp_state|, and false otherwise. PKPStatus CheckPins(bool is_issued_by_known_root, const TransportSecurityState::PKPState& pkp_state, - const HashValueVector& hashes); + const std::vector& hashes); // Returns true if the static key pinning list has been updated in the last 10 // weeks. diff --git a/naiveproxy/src/net/http/transport_security_state_source.cc b/naiveproxy/src/net/http/transport_security_state_source.cc deleted file mode 100644 index 397192f0f5..0000000000 --- a/naiveproxy/src/net/http/transport_security_state_source.cc +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2017 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/transport_security_state_source.h" - -namespace net { - -const char kNoReportURI[] = ""; - -} // namespace net diff --git a/naiveproxy/src/net/http/transport_security_state_source.h b/naiveproxy/src/net/http/transport_security_state_source.h index a10e403c65..3be0f7d439 100644 --- a/naiveproxy/src/net/http/transport_security_state_source.h +++ b/naiveproxy/src/net/http/transport_security_state_source.h @@ -9,32 +9,29 @@ #include #include "base/memory/raw_ptr_exclusion.h" +#include "net/base/hash_value.h" #include "net/base/net_export.h" namespace net { -// kNoReportURI is a placeholder for when a pinset does not have a report URI. -NET_EXPORT_PRIVATE extern const char kNoReportURI[]; - struct TransportSecurityStateSource { struct Pinset { // RAW_PTR_EXCLUSION: accepted_pins always points to static data. - RAW_PTR_EXCLUSION const char* const* const accepted_pins; + RAW_PTR_EXCLUSION const base::span + accepted_pins; // RAW_PTR_EXCLUSION: rejected_pins always points to static data. - RAW_PTR_EXCLUSION const char* const* const rejected_pins; - const char* const report_uri; + RAW_PTR_EXCLUSION const base::span + rejected_pins; }; // RAW_PTR_EXCLUSION: huffman_tree always points to static data. - const uint8_t* huffman_tree; - size_t huffman_tree_size; + RAW_PTR_EXCLUSION const base::span huffman_tree; // RAW_PTR_EXCLUSION: preloaded_data always points to static data. - const uint8_t* preloaded_data; + RAW_PTR_EXCLUSION const base::span preloaded_data; size_t preloaded_bits; size_t root_position; // RAW_PTR_EXCLUSION: pinsets always points to static data. - RAW_PTR_EXCLUSION const Pinset* pinsets; - size_t pinsets_count; + RAW_PTR_EXCLUSION const base::span pinsets; }; } // namespace net diff --git a/naiveproxy/src/net/http/transport_security_state_static.pins b/naiveproxy/src/net/http/transport_security_state_static.pins index de9fca1679..a7199ae49d 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: 2025-07-28 12:53 UTC +# Last updated: 2025-09-07 12:54 UTC PinsListTimestamp -1753707231 +1757249642 TestSPKI sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= diff --git a/naiveproxy/src/net/http/transport_security_state_static.template b/naiveproxy/src/net/http/transport_security_state_static.template index a8ab0731d1..e088091b03 100644 --- a/naiveproxy/src/net/http/transport_security_state_static.template +++ b/naiveproxy/src/net/http/transport_security_state_static.template @@ -12,44 +12,38 @@ #include #include "base/time/time.h" +#include "net/base/hash_value.h" #include "net/http/transport_security_state_source.h" // This is the time at which the key pins list was last updated. -const base::Time kPinsListTimestamp = base::Time::FromTimeT([[PINS_LIST_TIMESTAMP]]); +constexpr base::Time kPinsListTimestamp = base::Time::FromTimeT([[PINS_LIST_TIMESTAMP]]); // These are SubjectPublicKeyInfo hashes for public key pinning. The // hashes are SHA256 digests. [[SPKI_HASHES]] -// kNoRejectedPublicKeys is a placeholder for when no public keys are rejected. -static const char* const kNoRejectedPublicKeys[] = { - nullptr, -}; - [[ACCEPTABLE_CERTS]] -static const net::TransportSecurityStateSource::Pinset kPinsets[] = [[PINSETS]]; +static constexpr net::TransportSecurityStateSource::Pinset kPinsets[] = [[PINSETS]]; // kHSTSHuffmanTree describes a Huffman tree. The nodes of the tree are pairs // of uint8s. The last node in the array is the root of the tree. Each pair is // two uint8_t values, the first is "left" and the second is "right". If a // uint8_t value has the MSB set then it represents a literal leaf value. // Otherwise it's a pointer to the n'th element of the array. -static const uint8_t kHSTSHuffmanTree[] = [[HUFFMAN_TREE]]; +static constexpr uint8_t kHSTSHuffmanTree[] = [[HUFFMAN_TREE]]; -static const uint8_t kPreloadedHSTSData[] = [[HSTS_TRIE]]; +static constexpr uint8_t kPreloadedHSTSData[] = [[HSTS_TRIE]]; -static const unsigned kPreloadedHSTSBits = [[HSTS_TRIE_BITS]]; -static const unsigned kHSTSRootPosition = [[HSTS_TRIE_ROOT]]; +static constexpr unsigned kPreloadedHSTSBits = [[HSTS_TRIE_BITS]]; +static constexpr unsigned kHSTSRootPosition = [[HSTS_TRIE_ROOT]]; -static const net::TransportSecurityStateSource kHSTSSource = { +static constexpr net::TransportSecurityStateSource kHSTSSource = { kHSTSHuffmanTree, - sizeof(kHSTSHuffmanTree), kPreloadedHSTSData, kPreloadedHSTSBits, kHSTSRootPosition, kPinsets, - std::size(kPinsets) }; #endif // NET_HTTP_TRANSPORT_SECURITY_STATE_STATIC_H_ 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 d2702171e5..782993f614 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: 2025-07-28 12:53 UTC +// Last updated: 2025-09-07 12:54 UTC // { "pinsets": [ diff --git a/naiveproxy/src/net/http/transport_security_state_static_unittest.template b/naiveproxy/src/net/http/transport_security_state_static_unittest.template index c6133c79ee..c342b1d489 100644 --- a/naiveproxy/src/net/http/transport_security_state_static_unittest.template +++ b/naiveproxy/src/net/http/transport_security_state_static_unittest.template @@ -12,27 +12,21 @@ [[SPKI_HASHES]] -static const char* const kNoRejectedPublicKeys[] = { - nullptr, -}; - [[ACCEPTABLE_CERTS]] -static const struct net::TransportSecurityStateSource::Pinset kPinsets[] = [[PINSETS]]; +static constexpr net::TransportSecurityStateSource::Pinset kPinsets[] = [[PINSETS]]; -static const uint8_t kHSTSHuffmanTree[] = [[HUFFMAN_TREE]]; +static constexpr uint8_t kHSTSHuffmanTree[] = [[HUFFMAN_TREE]]; -static const uint8_t kPreloadedHSTSData[] = [[HSTS_TRIE]]; +static constexpr uint8_t kPreloadedHSTSData[] = [[HSTS_TRIE]]; -static const unsigned kPreloadedHSTSBits = [[HSTS_TRIE_BITS]]; -static const unsigned kHSTSRootPosition = [[HSTS_TRIE_ROOT]]; +static constexpr unsigned kPreloadedHSTSBits = [[HSTS_TRIE_BITS]]; +static constexpr unsigned kHSTSRootPosition = [[HSTS_TRIE_ROOT]]; -static const net::TransportSecurityStateSource kHSTSSource = { +static constexpr net::TransportSecurityStateSource kHSTSSource = { kHSTSHuffmanTree, - sizeof(kHSTSHuffmanTree), kPreloadedHSTSData, kPreloadedHSTSBits, kHSTSRootPosition, kPinsets, - std::size(kPinsets) }; diff --git a/naiveproxy/src/net/http/transport_security_state_test_util.cc b/naiveproxy/src/net/http/transport_security_state_test_util.cc index b27070d8ac..4b257eac45 100644 --- a/naiveproxy/src/net/http/transport_security_state_test_util.cc +++ b/naiveproxy/src/net/http/transport_security_state_test_util.cc @@ -2,20 +2,9 @@ // 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 "net/http/transport_security_state_test_util.h" -#include -#include - -#include "base/stl_util.h" -#include "base/strings/string_number_conversions.h" #include "net/http/transport_security_state.h" -#include "url/gurl.h" namespace net { @@ -30,42 +19,7 @@ ScopedTransportSecurityStateSource::ScopedTransportSecurityStateSource() { ScopedTransportSecurityStateSource::ScopedTransportSecurityStateSource( uint16_t reporting_port) { - // TODO(mattm): allow using other source? - const TransportSecurityStateSource* base_source = &test_default::kHSTSSource; - std::string reporting_port_string = base::NumberToString(reporting_port); - GURL::Replacements replace_port; - replace_port.SetPortStr(reporting_port_string); - - const char* last_report_uri = nullptr; - for (size_t i = 0; i < base_source->pinsets_count; ++i) { - const auto* pinset = &base_source->pinsets[i]; - if (pinset->report_uri == kNoReportURI) - continue; - // Currently only one PKP report URI is supported. - if (last_report_uri) - DCHECK_EQ(std::string_view(last_report_uri), pinset->report_uri); - else - last_report_uri = pinset->report_uri; - pkp_report_uri_ = - GURL(pinset->report_uri).ReplaceComponents(replace_port).spec(); - } - for (size_t i = 0; i < base_source->pinsets_count; ++i) { - const auto* pinset = &base_source->pinsets[i]; - pinsets_.push_back({pinset->accepted_pins, pinset->rejected_pins, - pinset->report_uri == kNoReportURI - ? kNoReportURI - : pkp_report_uri_.c_str()}); - } - - const TransportSecurityStateSource new_source = { - base_source->huffman_tree, base_source->huffman_tree_size, - base_source->preloaded_data, base_source->preloaded_bits, - base_source->root_position, pinsets_.data(), - base_source->pinsets_count}; - - source_ = std::make_unique(new_source); - - SetTransportSecurityStateSourceForTesting(source_.get()); + SetTransportSecurityStateSourceForTesting(&test_default::kHSTSSource); } ScopedTransportSecurityStateSource::~ScopedTransportSecurityStateSource() { diff --git a/naiveproxy/src/net/http/transport_security_state_test_util.h b/naiveproxy/src/net/http/transport_security_state_test_util.h index 99260c2c30..446a6ada45 100644 --- a/naiveproxy/src/net/http/transport_security_state_test_util.h +++ b/naiveproxy/src/net/http/transport_security_state_test_util.h @@ -5,10 +5,6 @@ #ifndef NET_HTTP_TRANSPORT_SECURITY_STATE_TEST_UTIL_H_ #define NET_HTTP_TRANSPORT_SECURITY_STATE_TEST_UTIL_H_ -#include -#include -#include - #include "net/http/transport_security_state_source.h" namespace net { @@ -19,8 +15,8 @@ class ScopedTransportSecurityStateSource { // the transport_security_state_static_unittest_default source. ScopedTransportSecurityStateSource(); - // As above, but modifies the reporting URIs in the test source to have a - // port number of |reporting_port|. + // Deprecated interface, now does the same as the default constructor. + // TODO(crbug.com/41485778): remove this. explicit ScopedTransportSecurityStateSource(uint16_t reporting_port); ScopedTransportSecurityStateSource( @@ -29,14 +25,6 @@ class ScopedTransportSecurityStateSource { const ScopedTransportSecurityStateSource&) = delete; ~ScopedTransportSecurityStateSource(); - - private: - std::unique_ptr source_; - - // This data backs the members of |source_|, if they had to be modified to - // use a different reporting port number. - std::string pkp_report_uri_; - std::vector pinsets_; }; } // namespace net diff --git a/naiveproxy/src/net/log/net_log.cc b/naiveproxy/src/net/log/net_log.cc index 9b49a0eff5..6cd28326c9 100644 --- a/naiveproxy/src/net/log/net_log.cc +++ b/naiveproxy/src/net/log/net_log.cc @@ -196,7 +196,7 @@ std::string NetLog::TickCountToString(const base::TimeTicks& time) { } // static -std::string NetLog::TimeToString(const base::Time& time) { +std::string NetLog::TimeToString(base::Time time) { // Convert the base::Time to its (approximate) equivalent in base::TimeTicks. base::TimeTicks time_ticks = base::TimeTicks::UnixEpoch() + (time - base::Time::UnixEpoch()); diff --git a/naiveproxy/src/net/log/net_log.h b/naiveproxy/src/net/log/net_log.h index bebc9d84e9..6248610f2a 100644 --- a/naiveproxy/src/net/log/net_log.h +++ b/naiveproxy/src/net/log/net_log.h @@ -305,7 +305,7 @@ class NET_EXPORT NetLog { // Same as above but takes a base::Time. Should not be used if precise // timestamps are desired, but is suitable for e.g. expiration times. - static std::string TimeToString(const base::Time& time); + static std::string TimeToString(base::Time time); // Returns a dictionary that maps event type symbolic names to their enum // values. 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 e3e688cd91..77f9602d10 100644 --- a/naiveproxy/src/net/log/net_log_event_type_list.h +++ b/naiveproxy/src/net/log/net_log_event_type_list.h @@ -1667,6 +1667,14 @@ EVENT_TYPE(HTTP_STREAM_POOL_ATTEMPT_MANAGER_QUIC_ATTEMPT_BOUND) // } EVENT_TYPE(HTTP_STREAM_POOL_ATTEMPT_MANAGER_QUIC_ATTEMPT_COMPLETED) +// Emitted when an HttpStreamPool::AttemptManager checks whether it can attempt +// a TCP based connection. The event parameter is: +// { +// "can_attempt": , +// } +EVENT_TYPE(HTTP_STREAM_POOL_ATTEMPT_MANAGER_CAN_ATTEMPT_TCP) + // Marks the start/end of a HttpStreamPool::AttemptManager::QuicAttempt. // For the BEGIN phase, the following parameters are attached: // { diff --git a/naiveproxy/src/net/log/trace_net_log_observer.cc b/naiveproxy/src/net/log/trace_net_log_observer.cc index 60974fb3fa..4c0af32e56 100644 --- a/naiveproxy/src/net/log/trace_net_log_observer.cc +++ b/naiveproxy/src/net/log/trace_net_log_observer.cc @@ -13,8 +13,8 @@ #include "base/check.h" #include "base/json/json_writer.h" #include "base/strings/stringprintf.h" +#include "base/trace_event/trace_event.h" #include "base/values.h" -#include "net/base/tracing.h" #include "net/log/net_log_entry.h" #include "net/log/net_log_event_type.h" #include "third_party/perfetto/include/perfetto/tracing/track_event.h" diff --git a/naiveproxy/src/net/log/trace_net_log_observer.h b/naiveproxy/src/net/log/trace_net_log_observer.h index a4aa0f6a1b..8fa541b1b0 100644 --- a/naiveproxy/src/net/log/trace_net_log_observer.h +++ b/naiveproxy/src/net/log/trace_net_log_observer.h @@ -8,8 +8,9 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/rand_util.h" +#include "base/trace_event/trace_event.h" +#include "base/trace_event/trace_log.h" #include "net/base/net_export.h" -#include "net/base/tracing.h" #include "net/log/net_log.h" #include "net/log/net_log_capture_mode.h" diff --git a/naiveproxy/src/net/nqe/network_quality_estimator.cc b/naiveproxy/src/net/nqe/network_quality_estimator.cc index 44ca4b6a08..7645667837 100644 --- a/naiveproxy/src/net/nqe/network_quality_estimator.cc +++ b/naiveproxy/src/net/nqe/network_quality_estimator.cc @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - #include "net/nqe/network_quality_estimator.h" #include @@ -27,6 +26,7 @@ #include "base/task/lazy_thread_pool_task_runner.h" #include "base/task/single_thread_task_runner.h" #include "base/time/default_tick_clock.h" +#include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "net/base/features.h" #include "net/base/host_port_pair.h" @@ -34,7 +34,6 @@ #include "net/base/load_timing_info.h" #include "net/base/network_interfaces.h" #include "net/base/trace_constants.h" -#include "net/base/tracing.h" #include "net/http/http_response_headers.h" #include "net/http/http_response_info.h" #include "net/http/http_status_code.h" diff --git a/naiveproxy/src/net/nqe/network_quality_estimator_util.cc b/naiveproxy/src/net/nqe/network_quality_estimator_util.cc index f6093e1535..a13a522d97 100644 --- a/naiveproxy/src/net/nqe/network_quality_estimator_util.cc +++ b/naiveproxy/src/net/nqe/network_quality_estimator_util.cc @@ -38,13 +38,13 @@ bool IsPrivateHost(HostResolver* host_resolver, int rv = request->Start(base::BindOnce([](int error) { NOTREACHED(); })); DCHECK_NE(rv, ERR_IO_PENDING); - if (rv == OK && request->GetAddressResults() && - !request->GetAddressResults()->empty()) { + if (rv == OK && !request->GetAddressResults().empty()) { // Checking only the first address should be sufficient. - IPEndPoint ip_endpoint = request->GetAddressResults()->front(); + IPEndPoint ip_endpoint = request->GetAddressResults().front(); IPAddress ip_address = ip_endpoint.address(); - if (!ip_address.IsPubliclyRoutable()) + if (!ip_address.IsPubliclyRoutable()) { return true; + } } return false; diff --git a/naiveproxy/src/net/ntlm/ntlm.cc b/naiveproxy/src/net/ntlm/ntlm.cc index 3f1027f7b2..57dd894d63 100644 --- a/naiveproxy/src/net/ntlm/ntlm.cc +++ b/naiveproxy/src/net/ntlm/ntlm.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 "net/ntlm/ntlm.h" #include @@ -15,6 +10,7 @@ #include #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/notreached.h" #include "base/strings/utf_string_conversions.h" @@ -173,7 +169,7 @@ void Create3DesKeysFromNtlmHash( keys[16] = ntlm_hash[14]; keys[17] = ntlm_hash[14] << 7 | ntlm_hash[15] >> 1; keys[18] = ntlm_hash[15] << 6; - memset(keys.data() + 19, 0, 5); + std::ranges::fill(keys.subspan(19u, 5u), 0); } void GenerateNtlmHashV1(const std::u16string& password, @@ -198,20 +194,24 @@ void GenerateResponseDesl(base::span hash, static_assert(kResponseLenV1 == block_count * block_size, "kResponseLenV1 must equal block_count * block_size"); + // Safety: Covers the same memory as `response`; DES_cblock contains an 8-char + // array so alignment should be fine, too. + base::span response_as_cblock = + UNSAFE_BUFFERS(base::span(reinterpret_cast(response.data()), + response.size() / sizeof(DES_cblock))); + const DES_cblock* challenge_block = reinterpret_cast(challenge.data()); - std::array keys; + std::array keys; // Map the NTLM hash to three 8 byte DES keys, with 7 bits of the key in each // byte and the least significant bit set with odd parity. Then encrypt the // 8 byte challenge with each of the three keys. This produces three 8 byte // encrypted blocks into |response|. - Create3DesKeysFromNtlmHash(hash, keys); - for (size_t ix = 0; ix < block_count * block_size; ix += block_size) { - DES_cblock* key_block = reinterpret_cast( - base::span(keys).subspan(ix).data()); - DES_cblock* response_block = - reinterpret_cast(response.data() + ix); + Create3DesKeysFromNtlmHash(hash, base::as_writable_byte_span(keys)); + for (size_t i = 0; i < block_count; ++i) { + DES_cblock* key_block = &keys[i]; + DES_cblock* response_block = &response_as_cblock[i]; DES_key_schedule key_schedule; DES_set_odd_parity(key_block); @@ -239,7 +239,7 @@ void GenerateResponsesV1( // In NTLM v1 (with LMv1 disabled), the lm_response and ntlm_response are the // same. So just copy the ntlm_response into the lm_response. - memcpy(lm_response.data(), ntlm_response.data(), kResponseLenV1); + lm_response.copy_from(ntlm_response); } void GenerateLMResponseV1WithSessionSecurity( @@ -247,8 +247,9 @@ void GenerateLMResponseV1WithSessionSecurity( base::span lm_response) { // In NTLM v1 with Session Security (aka NTLM2) the lm_response is 8 bytes of // client challenge and 16 bytes of zeros. (See 3.3.1) - memcpy(lm_response.data(), client_challenge.data(), kChallengeLen); - memset(lm_response.data() + kChallengeLen, 0, kResponseLenV1 - kChallengeLen); + auto [out_challenge, out_zeroes] = lm_response.split_at(kChallengeLen); + out_challenge.copy_from(client_challenge); + std::ranges::fill(out_zeroes, 0); } void GenerateSessionHashV1WithSessionSecurity( diff --git a/naiveproxy/src/net/ntlm/ntlm_buffer_reader.cc b/naiveproxy/src/net/ntlm/ntlm_buffer_reader.cc index 77e018cd63..47ea361eaa 100644 --- a/naiveproxy/src/net/ntlm/ntlm_buffer_reader.cc +++ b/naiveproxy/src/net/ntlm/ntlm_buffer_reader.cc @@ -2,16 +2,12 @@ // 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 "net/ntlm/ntlm_buffer_reader.h" #include #include "base/check_op.h" +#include "base/compiler_specific.h" namespace net::ntlm { @@ -61,32 +57,21 @@ bool NtlmBufferReader::ReadBytes(base::span buffer) { if (buffer.empty()) return true; - memcpy(buffer.data(), GetBufferAtCursor(), buffer.size()); + buffer.copy_from(GetSubspanAtCursor(buffer.size())); AdvanceCursor(buffer.size()); return true; } -bool NtlmBufferReader::ReadBytesFrom(const SecurityBuffer& sec_buf, - base::span buffer) { - if (!CanReadFrom(sec_buf) || buffer.size() < sec_buf.length) - return false; - - if (buffer.empty()) - return true; - - memcpy(buffer.data(), GetBufferPtr() + sec_buf.offset, sec_buf.length); - - return true; -} - bool NtlmBufferReader::ReadPayloadAsBufferReader(const SecurityBuffer& sec_buf, NtlmBufferReader* reader) { if (!CanReadFrom(sec_buf)) return false; - *reader = NtlmBufferReader( - base::span(GetBufferPtr() + sec_buf.offset, sec_buf.length)); + *reader = + sec_buf.length + ? NtlmBufferReader(buffer_.subspan(sec_buf.offset, sec_buf.length)) + : NtlmBufferReader(); return true; } @@ -138,7 +123,8 @@ bool NtlmBufferReader::ReadTargetInfo(size_t target_info_len, return false; // Take a copy of the payload in the AVPair. - pair.buffer.assign(GetBufferAtCursor(), GetBufferAtCursor() + pair.avlen); + auto payload = GetSubspanAtCursor(pair.avlen); + pair.buffer.assign(payload.begin(), payload.end()); if (pair.avid == TargetInfoAvId::kEol) { // Terminator must have zero length. if (pair.avlen != 0) @@ -245,8 +231,9 @@ bool NtlmBufferReader::MatchSignature() { if (!CanRead(kSignatureLen)) return false; - if (memcmp(kSignature, GetBufferAtCursor(), kSignatureLen) != 0) + if (GetSubspanAtCursor(kSignatureLen) != base::span(kSignature)) { return false; + } AdvanceCursor(kSignatureLen); return true; @@ -266,9 +253,11 @@ bool NtlmBufferReader::MatchZeros(size_t count) { if (!CanRead(count)) return false; + auto to_check = GetSubspanAtCursor(count); for (size_t i = 0; i < count; i++) { - if (GetBufferAtCursor()[i] != 0) + if (to_check[i] != 0) { return false; + } } AdvanceCursor(count); diff --git a/naiveproxy/src/net/ntlm/ntlm_buffer_reader.h b/naiveproxy/src/net/ntlm/ntlm_buffer_reader.h index 3c9f965d36..2e20e1ee15 100644 --- a/naiveproxy/src/net/ntlm/ntlm_buffer_reader.h +++ b/naiveproxy/src/net/ntlm/ntlm_buffer_reader.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 NET_NTLM_NTLM_BUFFER_READER_H_ #define NET_NTLM_NTLM_BUFFER_READER_H_ @@ -95,13 +90,6 @@ class NET_EXPORT_PRIVATE NtlmBufferReader { // Reads |len| bytes and copies them into |buffer|. [[nodiscard]] bool ReadBytes(base::span buffer); - // Reads |sec_buf.length| bytes from offset |sec_buf.offset| and copies them - // into |buffer|. If the security buffer specifies a payload outside the - // buffer, then the call fails. Unlike the other Read* methods, this does - // not move the cursor. - [[nodiscard]] bool ReadBytesFrom(const SecurityBuffer& sec_buf, - base::span buffer); - // Reads |sec_buf.length| bytes from offset |sec_buf.offset| and assigns // |reader| an |NtlmBufferReader| representing the payload. If the security // buffer specifies a payload outside the buffer, then the call fails, and @@ -206,17 +194,15 @@ class NET_EXPORT_PRIVATE NtlmBufferReader { // method. void AdvanceCursor(size_t count) { SetCursor(GetCursor() + count); } - // Returns a constant pointer to the start of the buffer. - const uint8_t* GetBufferPtr() const { return buffer_.data(); } - - // Returns a pointer to the underlying buffer at the current cursor - // position. - const uint8_t* GetBufferAtCursor() const { return GetBufferPtr() + cursor_; } + // Returns a span of given length starting from the current cursor position. + base::span GetSubspanAtCursor(size_t length) const { + return buffer_.subspan(cursor_, length); + } // Returns the byte at the current cursor position. uint8_t GetByteAtCursor() const { DCHECK(!IsEndOfBuffer()); - return *(GetBufferAtCursor()); + return buffer_[cursor_]; } base::raw_span buffer_; diff --git a/naiveproxy/src/net/ntlm/ntlm_buffer_writer.cc b/naiveproxy/src/net/ntlm/ntlm_buffer_writer.cc index 37e26830d8..784772a7d6 100644 --- a/naiveproxy/src/net/ntlm/ntlm_buffer_writer.cc +++ b/naiveproxy/src/net/ntlm/ntlm_buffer_writer.cc @@ -2,18 +2,15 @@ // 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 "net/ntlm/ntlm_buffer_writer.h" #include +#include #include #include "base/check_op.h" +#include "base/containers/span_writer.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" @@ -28,8 +25,9 @@ bool NtlmBufferWriter::CanWrite(size_t len) const { if (len == 0) return true; - if (!GetBufferPtr()) + if (buffer_.empty()) { return false; + } DCHECK_LE(GetCursor(), GetLength()); @@ -37,15 +35,30 @@ bool NtlmBufferWriter::CanWrite(size_t len) const { } bool NtlmBufferWriter::WriteUInt16(uint16_t value) { - return WriteUInt(value); + base::SpanWriter writer(base::span(buffer_).subspan(cursor_)); + if (writer.WriteU16LittleEndian(value)) { + AdvanceCursor(sizeof(value)); + return true; + } + return false; } bool NtlmBufferWriter::WriteUInt32(uint32_t value) { - return WriteUInt(value); + base::SpanWriter writer(base::span(buffer_).subspan(cursor_)); + if (writer.WriteU32LittleEndian(value)) { + AdvanceCursor(sizeof(value)); + return true; + } + return false; } bool NtlmBufferWriter::WriteUInt64(uint64_t value) { - return WriteUInt(value); + base::SpanWriter writer(base::span(buffer_).subspan(cursor_)); + if (writer.WriteU64LittleEndian(value)) { + AdvanceCursor(sizeof(value)); + return true; + } + return false; } bool NtlmBufferWriter::WriteFlags(NegotiateFlags flags) { @@ -59,7 +72,7 @@ bool NtlmBufferWriter::WriteBytes(base::span bytes) { if (!CanWrite(bytes.size())) return false; - memcpy(GetBufferPtrAtCursor(), bytes.data(), bytes.size()); + GetSubspanAtCursor(bytes.size()).copy_from(bytes); AdvanceCursor(bytes.size()); return true; } @@ -71,7 +84,7 @@ bool NtlmBufferWriter::WriteZeros(size_t count) { if (!CanWrite(count)) return false; - memset(GetBufferPtrAtCursor(), 0, count); + std::ranges::fill(GetSubspanAtCursor(count), 0); AdvanceCursor(count); return true; } @@ -133,17 +146,15 @@ bool NtlmBufferWriter::WriteUtf16String(const std::u16string& str) { if (!CanWrite(num_bytes)) return false; + auto dest = GetSubspanAtCursor(num_bytes); #if defined(ARCH_CPU_BIG_ENDIAN) - uint8_t* ptr = reinterpret_cast(GetBufferPtrAtCursor()); for (int i = 0; i < num_bytes; i += 2) { - ptr[i] = str[i / 2] & 0xff; - ptr[i + 1] = str[i / 2] >> 8; + dest[i] = str[i / 2] & 0xff; + dest[i + 1] = str[i / 2] >> 8; } #else - memcpy(reinterpret_cast(GetBufferPtrAtCursor()), str.c_str(), - num_bytes); - + dest.copy_from(base::as_byte_span(str)); #endif AdvanceCursor(num_bytes); @@ -162,23 +173,8 @@ bool NtlmBufferWriter::WriteMessageHeader(MessageType message_type) { return WriteSignature() && WriteMessageType(message_type); } -template -bool NtlmBufferWriter::WriteUInt(T value) { - size_t int_size = sizeof(T); - if (!CanWrite(int_size)) - return false; - - for (size_t i = 0; i < int_size; i++) { - GetBufferPtrAtCursor()[i] = static_cast(value & 0xff); - value >>= 8; - } - - AdvanceCursor(int_size); - return true; -} - void NtlmBufferWriter::SetCursor(size_t cursor) { - DCHECK(GetBufferPtr() && cursor <= GetLength()); + DCHECK(!buffer_.empty() && cursor <= GetLength()); cursor_ = cursor; } diff --git a/naiveproxy/src/net/ntlm/ntlm_buffer_writer.h b/naiveproxy/src/net/ntlm/ntlm_buffer_writer.h index 8d07b03e52..7c3fe86707 100644 --- a/naiveproxy/src/net/ntlm/ntlm_buffer_writer.h +++ b/naiveproxy/src/net/ntlm/ntlm_buffer_writer.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 NET_NTLM_NTLM_BUFFER_WRITER_H_ #define NET_NTLM_NTLM_BUFFER_WRITER_H_ @@ -168,10 +163,6 @@ class NET_EXPORT_PRIVATE NtlmBufferWriter { [[nodiscard]] bool WriteMessageHeader(MessageType message_type); private: - // Writes |sizeof(T)| bytes little-endian of an integer type to the buffer. - template - bool WriteUInt(T value); - // Sets the cursor position. The caller should use |GetLength| or // |CanWrite| to verify the bounds before calling this method. void SetCursor(size_t cursor); @@ -180,15 +171,14 @@ class NET_EXPORT_PRIVATE NtlmBufferWriter { // |CanWrite| to verify the bounds before calling this method. void AdvanceCursor(size_t count) { SetCursor(GetCursor() + count); } - // Returns a pointer to the start of the buffer. - const uint8_t* GetBufferPtr() const { return buffer_.data(); } - uint8_t* GetBufferPtr() { return buffer_.data(); } - - // Returns pointer into the buffer at the current cursor location. - const uint8_t* GetBufferPtrAtCursor() const { - return GetBufferPtr() + GetCursor(); + // Returns a span of given length starting from the current cursor position. + base::span GetSubspanAtCursor(size_t length) const { + return base::span(buffer_).subspan(cursor_, length); + } + + base::span GetSubspanAtCursor(size_t length) { + return base::span(buffer_).subspan(cursor_, length); } - uint8_t* GetBufferPtrAtCursor() { return GetBufferPtr() + GetCursor(); } std::vector buffer_; size_t cursor_ = 0; diff --git a/naiveproxy/src/net/ntlm/ntlm_client.cc b/naiveproxy/src/net/ntlm/ntlm_client.cc index 99c40cf083..0788507ccd 100644 --- a/naiveproxy/src/net/ntlm/ntlm_client.cc +++ b/naiveproxy/src/net/ntlm/ntlm_client.cc @@ -2,16 +2,14 @@ // 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 "net/ntlm/ntlm_client.h" #include +#include + #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/logging.h" #include "base/numerics/safe_math.h" @@ -238,7 +236,7 @@ std::vector NtlmClient::GenerateAuthenticateMessage( GenerateUpdatedTargetInfo(IsMicEnabled(), IsEpaEnabled(), channel_bindings, spn, av_pairs, ×tamp); - memset(lm_response, 0, kResponseLenV1); + std::ranges::fill(base::span(lm_response), 0); if (timestamp == UINT64_MAX) { // If the server didn't send a time, then use the clients time. timestamp = client_time; diff --git a/naiveproxy/src/net/ntlm/ntlm_test_data.h b/naiveproxy/src/net/ntlm/ntlm_test_data.h index 8b4f3c370b..223dbd3b15 100644 --- a/naiveproxy/src/net/ntlm/ntlm_test_data.h +++ b/naiveproxy/src/net/ntlm/ntlm_test_data.h @@ -16,6 +16,8 @@ #ifndef NET_NTLM_NTLM_TEST_DATA_H_ #define NET_NTLM_NTLM_TEST_DATA_H_ +#include + #include "net/ntlm/ntlm_constants.h" namespace net::ntlm::test { @@ -252,15 +254,17 @@ inline constexpr uint8_t kExpectedTargetInfoFromSpecPlusServerTimestampV2[] = { // // AvPair 6 [86-87] |TargetInfoAvId::kEol| Av ID = 0x0000 // AvPair 6 [88-89] Av Length = 0x0000 -inline constexpr uint8_t kExpectedTargetInfoSpecResponseV2[] = { - 0x02, 0x00, 0x0c, 0x00, 'D', 0x00, 'o', 0x00, 'm', 0x00, 'a', 0x00, - 'i', 0x00, 'n', 0x00, 0x01, 0x00, 0x0c, 0x00, 'S', 0x00, 'e', 0x00, - 'r', 0x00, 'v', 0x00, 'e', 0x00, 'r', 0x00, 0x06, 0x00, 0x04, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x65, 0x86, 0xE9, 0x9D, - 0x81, 0xC2, 0xFC, 0x98, 0x4E, 0x47, 0x17, 0x2F, 0xD4, 0xDD, 0x03, 0x10, - 0x09, 0x00, 0x16, 0x00, 'H', 0x00, 'T', 0x00, 'T', 0x00, 'P', 0x00, - '/', 0x00, 'S', 0x00, 'e', 0x00, 'r', 0x00, 'v', 0x00, 'e', 0x00, - 'r', 0x00, 0x00, 0x00, 0x00, 0x00}; +inline constexpr auto kExpectedTargetInfoSpecResponseV2 = + std::to_array({ + 0x02, 0x00, 0x0c, 0x00, 'D', 0x00, 'o', 0x00, 'm', 0x00, 'a', 0x00, + 'i', 0x00, 'n', 0x00, 0x01, 0x00, 0x0c, 0x00, 'S', 0x00, 'e', 0x00, + 'r', 0x00, 'v', 0x00, 'e', 0x00, 'r', 0x00, 0x06, 0x00, 0x04, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x65, 0x86, 0xE9, 0x9D, + 0x81, 0xC2, 0xFC, 0x98, 0x4E, 0x47, 0x17, 0x2F, 0xD4, 0xDD, 0x03, 0x10, + 0x09, 0x00, 0x16, 0x00, 'H', 0x00, 'T', 0x00, 'T', 0x00, 'P', 0x00, + '/', 0x00, 'S', 0x00, 'e', 0x00, 'r', 0x00, 'v', 0x00, 'e', 0x00, + 'r', 0x00, 0x00, 0x00, 0x00, 0x00, + }); // Test result value defined in [MS-NLMP] Section 4.2.4.2.2. inline constexpr uint8_t kExpectedProofFromSpecV2[kNtlmProofLenV2] = { diff --git a/naiveproxy/src/net/proxy_resolution/proxy_config_service_android.cc b/naiveproxy/src/net/proxy_resolution/proxy_config_service_android.cc index 79afcc6f99..6b5413265e 100644 --- a/naiveproxy/src/net/proxy_resolution/proxy_config_service_android.cc +++ b/naiveproxy/src/net/proxy_resolution/proxy_config_service_android.cc @@ -431,7 +431,6 @@ class ProxyConfigServiceAndroid::Delegate // ProxyConfigServiceAndroid::JNIDelegate overrides. void ProxySettingsChangedTo( JNIEnv* env, - const JavaParamRef& jself, const JavaParamRef& jhost, jint jport, const JavaParamRef& jpac_url, @@ -439,15 +438,14 @@ class ProxyConfigServiceAndroid::Delegate std::string host = ConvertJavaStringToUTF8(env, jhost); std::string pac_url; if (jpac_url) - ConvertJavaStringToUTF8(env, jpac_url, &pac_url); + pac_url = ConvertJavaStringToUTF8(env, jpac_url); std::vector exclusion_list; base::android::AppendJavaStringArrayToStringVector( env, jexclusion_list, &exclusion_list); delegate_->ProxySettingsChangedTo(host, jport, pac_url, exclusion_list); } - void ProxySettingsChanged(JNIEnv* env, - const JavaParamRef& self) override { + void ProxySettingsChanged(JNIEnv* env) override { delegate_->ProxySettingsChanged(); } diff --git a/naiveproxy/src/net/proxy_resolution/proxy_config_service_android.h b/naiveproxy/src/net/proxy_resolution/proxy_config_service_android.h index 2664eb2e6b..5b6b9a01ae 100644 --- a/naiveproxy/src/net/proxy_resolution/proxy_config_service_android.h +++ b/naiveproxy/src/net/proxy_resolution/proxy_config_service_android.h @@ -6,6 +6,7 @@ #define NET_PROXY_RESOLUTION_PROXY_CONFIG_SERVICE_ANDROID_H_ #include +#include #include "base/android/jni_android.h" #include "base/compiler_specific.h" @@ -44,7 +45,6 @@ class NET_EXPORT ProxyConfigServiceAndroid : public ProxyConfigService { // The fourth argument is the proxy exclusion list. virtual void ProxySettingsChangedTo( JNIEnv*, - const base::android::JavaParamRef&, const base::android::JavaParamRef&, jint, const base::android::JavaParamRef&, @@ -52,9 +52,7 @@ class NET_EXPORT ProxyConfigServiceAndroid : public ProxyConfigService { // Called from Java (on JNI thread) to signal that the proxy settings have // changed. New proxy settings are fetched from the system property store. - virtual void ProxySettingsChanged( - JNIEnv*, - const base::android::JavaParamRef&) = 0; + virtual void ProxySettingsChanged(JNIEnv*) = 0; }; ProxyConfigServiceAndroid( diff --git a/naiveproxy/src/net/proxy_resolution/proxy_resolver_apple.cc b/naiveproxy/src/net/proxy_resolution/proxy_resolver_apple.cc index 9b2225f9eb..ba3f4b9615 100644 --- a/naiveproxy/src/net/proxy_resolution/proxy_resolver_apple.cc +++ b/naiveproxy/src/net/proxy_resolution/proxy_resolver_apple.cc @@ -12,8 +12,8 @@ #include "base/apple/foundation_util.h" #include "base/apple/scoped_cftyperef.h" #include "base/check.h" -#include "base/lazy_instance.h" #include "base/memory/raw_ref.h" +#include "base/no_destructor.h" #include "base/strings/string_util.h" #include "base/strings/sys_string_conversions.h" #include "base/synchronization/lock.h" @@ -48,8 +48,10 @@ namespace { // 1. Adding the source to the run loop. // 2. Handling the source result. // 3. Removing the source from the run loop. -static base::LazyInstance::Leaky g_cfnetwork_pac_runloop_lock = - LAZY_INSTANCE_INITIALIZER; +base::Lock& GetCFNetworkPacRunloopLock() { + static base::NoDestructor lock; + return *lock; +} // Forward declaration of the callback function used by the // SynchronizedRunLoopObserver class. @@ -271,13 +273,13 @@ int ProxyResolverApple::GetProxyForURL( // Add the run loop observer to synchronize events of // CFNetworkExecuteProxyAutoConfigurationURL sources. See the definition of // |g_cfnetwork_pac_runloop_lock|. - SynchronizedRunLoopObserver observer(g_cfnetwork_pac_runloop_lock.Get()); + SynchronizedRunLoopObserver observer(GetCFNetworkPacRunloopLock()); observer.AddToCurrentRunLoop(private_runloop_mode); // Make sure that no CFNetworkExecuteProxyAutoConfigurationURL sources // are added to the run loop concurrently. { - base::AutoLock lock(g_cfnetwork_pac_runloop_lock.Get()); + base::AutoLock lock(GetCFNetworkPacRunloopLock()); CFRunLoopAddSource(CFRunLoopGetCurrent(), runloop_source.get(), private_runloop_mode); } @@ -287,7 +289,7 @@ int ProxyResolverApple::GetProxyForURL( // Make sure that no CFNetworkExecuteProxyAutoConfigurationURL sources // are removed from the run loop concurrently. { - base::AutoLock lock(g_cfnetwork_pac_runloop_lock.Get()); + base::AutoLock lock(GetCFNetworkPacRunloopLock()); CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runloop_source.get(), private_runloop_mode); } diff --git a/naiveproxy/src/net/proxy_resolution/win/dhcpcsvc_init_win.cc b/naiveproxy/src/net/proxy_resolution/win/dhcpcsvc_init_win.cc index d2e2a62580..b048af03cc 100644 --- a/naiveproxy/src/net/proxy_resolution/win/dhcpcsvc_init_win.cc +++ b/naiveproxy/src/net/proxy_resolution/win/dhcpcsvc_init_win.cc @@ -9,8 +9,9 @@ #include #include +#include + #include "base/check_op.h" -#include "base/lazy_instance.h" namespace { @@ -23,17 +24,15 @@ class DhcpcsvcInitSingleton { } }; -// Worker pool threads that use the DHCP API may still be running at shutdown. -// Leak instance and skip cleanup. -static base::LazyInstance::Leaky - g_dhcpcsvc_init_singleton = LAZY_INSTANCE_INITIALIZER; - } // namespace namespace net { void EnsureDhcpcsvcInit() { - g_dhcpcsvc_init_singleton.Get(); + // Worker pool threads that use the DHCP API may still be running at shutdown. + // Leak instance and skip cleanup. + static_assert(std::is_trivially_destructible::value); + static DhcpcsvcInitSingleton instance; } } // namespace net diff --git a/naiveproxy/src/net/proxy_resolution/win/winhttp_status.h b/naiveproxy/src/net/proxy_resolution/win/winhttp_status.h index ae5f9ee08b..9111194169 100644 --- a/naiveproxy/src/net/proxy_resolution/win/winhttp_status.h +++ b/naiveproxy/src/net/proxy_resolution/win/winhttp_status.h @@ -12,40 +12,47 @@ namespace net { // by the Windows error code, which will be supplied alongside this enum. // // Keep in sync with proxy_resolver_win.mojom.WinHttpStatus. + +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +// LINT.IfChange(WinHttpStatus) enum class WinHttpStatus { // No Error. - kOk, + kOk = 0, // Aborted by caller. - kAborted, + kAborted = 1, // WinHttpOpen() API failed. - kWinHttpOpenFailed, + kWinHttpOpenFailed = 2, // WinHttpSetTimeouts() API failed. - kWinHttpSetTimeoutsFailed, + kWinHttpSetTimeoutsFailed = 3, // WinHttpSetStatusCallback() API failed. - kWinHttpSetStatusCallbackFailed, + kWinHttpSetStatusCallbackFailed = 4, // WinHttpGetIEProxyConfigForCurrentUser() API failed. - kWinHttpGetIEProxyConfigForCurrentUserFailed, + kWinHttpGetIEProxyConfigForCurrentUserFailed = 5, // WinHttpCreateProxyResolver() API failed. - kWinHttpCreateProxyResolverFailed, + kWinHttpCreateProxyResolverFailed = 6, // WinHttpGetProxyForURLEx() API failed. - kWinHttpGetProxyForURLExFailed, + kWinHttpGetProxyForURLExFailed = 7, // Proxy resolution callback returned an error. - kStatusCallbackFailed, + kStatusCallbackFailed = 8, // WinHttpGetProxyResult() API failed. - kWinHttpGetProxyResultFailed, + kWinHttpGetProxyResultFailed = 9, // WinHttpGetProxyResult() API unexpectedly returned an empty list. - kEmptyProxyList, + kEmptyProxyList = 10, + + kMaxValue = kEmptyProxyList, }; +// LINT.ThenChange(//tools/metrics/histograms/metadata/net/enums.xml:WinHttpStatus) } // namespace net diff --git a/naiveproxy/src/net/quic/crypto/proof_source_chromium.cc b/naiveproxy/src/net/quic/crypto/proof_source_chromium.cc index c7fabad57a..024118c320 100644 --- a/naiveproxy/src/net/quic/crypto/proof_source_chromium.cc +++ b/naiveproxy/src/net/quic/crypto/proof_source_chromium.cc @@ -2,20 +2,16 @@ // 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 "net/quic/crypto/proof_source_chromium.h" +#include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_view_util.h" #include "crypto/openssl_util.h" +#include "crypto/sign.h" #include "net/cert/x509_util.h" #include "net/third_party/quiche/src/quiche/quic/core/crypto/crypto_protocol.h" -#include "third_party/boringssl/src/include/openssl/digest.h" -#include "third_party/boringssl/src/include/openssl/evp.h" -#include "third_party/boringssl/src/include/openssl/rsa.h" using std::string; @@ -55,9 +51,8 @@ bool ProofSourceChromium::Initialize(const base::FilePath& cert_path, return false; } - const uint8_t* p = reinterpret_cast(key_data.data()); - std::vector input(p, p + key_data.size()); - private_key_ = crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input); + private_key_ = crypto::keypair::PrivateKey::FromPrivateKeyInfo( + base::as_byte_span(key_data)); if (!private_key_) { DLOG(FATAL) << "Unable to create private key."; return false; @@ -84,46 +79,19 @@ bool ProofSourceChromium::GetProofInner( quiche::QuicheReferenceCountedPointer* out_chain, quic::QuicCryptoProof* proof) { DCHECK(proof != nullptr); - DCHECK(private_key_.get()) << " this: " << this; + DCHECK(private_key_) << " this: " << this; - crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); - bssl::ScopedEVP_MD_CTX sign_context; - EVP_PKEY_CTX* pkey_ctx; + crypto::sign::Signer signer(crypto::sign::RSA_PSS_SHA256, *private_key_); + signer.Update( + base::byte_span_with_nul_from_cstring(quic::kProofSignatureLabel)); + uint32_t chlo_hash_len = chlo_hash.length(); + signer.Update(base::byte_span_from_ref(chlo_hash_len)); + signer.Update(base::as_byte_span(chlo_hash)); + signer.Update(base::as_byte_span(server_config)); + std::vector signature = signer.Finish(); + + proof->signature.assign(base::as_string_view(signature)); - uint32_t len_tmp = chlo_hash.length(); - if (!EVP_DigestSignInit(sign_context.get(), &pkey_ctx, EVP_sha256(), nullptr, - private_key_->key()) || - !EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) || - !EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, -1) || - !EVP_DigestSignUpdate( - sign_context.get(), - reinterpret_cast(quic::kProofSignatureLabel), - sizeof(quic::kProofSignatureLabel)) || - !EVP_DigestSignUpdate(sign_context.get(), - reinterpret_cast(&len_tmp), - sizeof(len_tmp)) || - !EVP_DigestSignUpdate(sign_context.get(), - reinterpret_cast(chlo_hash.data()), - len_tmp) || - !EVP_DigestSignUpdate( - sign_context.get(), - reinterpret_cast(server_config.data()), - server_config.size())) { - return false; - } - // Determine the maximum length of the signature. - size_t len = 0; - if (!EVP_DigestSignFinal(sign_context.get(), nullptr, &len)) { - return false; - } - std::vector signature(len); - // Sign it. - if (!EVP_DigestSignFinal(sign_context.get(), signature.data(), &len)) { - return false; - } - signature.resize(len); - proof->signature.assign(reinterpret_cast(signature.data()), - signature.size()); *out_chain = chain_; VLOG(1) << "signature: " << base::HexEncode(proof->signature); proof->leaf_cert_scts = signed_certificate_timestamp_; @@ -173,32 +141,10 @@ void ProofSourceChromium::ComputeTlsSignature( uint16_t signature_algorithm, std::string_view in, std::unique_ptr callback) { - crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); - bssl::ScopedEVP_MD_CTX sign_context; - EVP_PKEY_CTX* pkey_ctx; - - size_t siglen; - string sig; - if (!EVP_DigestSignInit(sign_context.get(), &pkey_ctx, EVP_sha256(), nullptr, - private_key_->key()) || - !EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) || - !EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, -1) || - !EVP_DigestSignUpdate(sign_context.get(), - reinterpret_cast(in.data()), - in.size()) || - !EVP_DigestSignFinal(sign_context.get(), nullptr, &siglen)) { - callback->Run(false, std::move(sig), nullptr); - return; - } - sig.resize(siglen); - if (!EVP_DigestSignFinal( - sign_context.get(), - reinterpret_cast(const_cast(sig.data())), &siglen)) { - callback->Run(false, std::move(sig), nullptr); - return; - } - sig.resize(siglen); - callback->Run(true, std::move(sig), nullptr); + DCHECK(private_key_); + std::vector sig = crypto::sign::Sign( + crypto::sign::RSA_PSS_SHA256, *private_key_, base::as_byte_span(in)); + callback->Run(true, std::string(base::as_string_view(sig)), nullptr); } absl::InlinedVector diff --git a/naiveproxy/src/net/quic/crypto/proof_source_chromium.h b/naiveproxy/src/net/quic/crypto/proof_source_chromium.h index 52e36dc46b..158263066d 100644 --- a/naiveproxy/src/net/quic/crypto/proof_source_chromium.h +++ b/naiveproxy/src/net/quic/crypto/proof_source_chromium.h @@ -10,7 +10,7 @@ #include "base/compiler_specific.h" #include "base/files/file_util.h" -#include "crypto/rsa_private_key.h" +#include "crypto/keypair.h" #include "net/base/net_export.h" #include "net/cert/x509_certificate.h" #include "net/third_party/quiche/src/quiche/quic/core/crypto/proof_source.h" @@ -75,7 +75,11 @@ class NET_EXPORT_PRIVATE ProofSourceChromium : public quic::ProofSource { out_chain, quic::QuicCryptoProof* proof); - std::unique_ptr private_key_; + // Theoretically this should not be an optional since it doesn't make sense to + // have a ProofSource without a private key. The private key isn't available + // at construction time though, only during Initialize(), so this can be + // nullopt before Initialize() is called. + std::optional private_key_; CertificateList certs_in_file_; quiche::QuicheReferenceCountedPointer chain_; std::string signed_certificate_timestamp_; 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 386e72ef6b..fe8547b0ce 100644 --- a/naiveproxy/src/net/quic/dedicated_web_transport_http3_client.cc +++ b/naiveproxy/src/net/quic/dedicated_web_transport_http3_client.cc @@ -508,6 +508,11 @@ int DedicatedWebTransportHttp3Client::DoInit() { if (!IsPortAllowedForScheme(url_.EffectiveIntPort(), url_.scheme_piece())) return ERR_UNSAFE_PORT; + if (!application_protocols_.empty() && + !webtransport::ValidateSubprotocolList(application_protocols_)) { + return ERR_INVALID_ARGUMENT; + } + // TODO(vasilvv): check if QUIC is disabled by policy. // Ensure that RFC 9000 is always supported. @@ -565,7 +570,7 @@ int DedicatedWebTransportHttp3Client::DoResolveHostComplete(int rv) { if (rv != OK) return rv; - DCHECK(resolve_host_request_->GetAddressResults()); + DCHECK(!resolve_host_request_->GetAddressResults().empty()); next_connect_state_ = CONNECT_STATE_CONNECT; return OK; } @@ -584,7 +589,7 @@ int DedicatedWebTransportHttp3Client::DoConnect() { socket_->UseNonBlockingIO(); IPEndPoint server_address = - *resolve_host_request_->GetAddressResults()->begin(); + resolve_host_request_->GetAddressResults().front(); visitor_->OnBeforeConnect(server_address); return socket_->ConnectAsync( server_address, base::BindOnce(&DedicatedWebTransportHttp3Client::DoLoop, @@ -598,7 +603,7 @@ void DedicatedWebTransportHttp3Client::CreateConnection() { packet_reader_ = nullptr; IPEndPoint server_address = - *resolve_host_request_->GetAddressResults()->begin(); + resolve_host_request_->GetAddressResults().front(); quic::QuicConnectionId connection_id = quic::QuicUtils::CreateRandomConnectionId( quic_context_->random_generator()); diff --git a/naiveproxy/src/net/quic/mock_decrypter.cc b/naiveproxy/src/net/quic/mock_decrypter.cc index 965235592e..e43911a2ae 100644 --- a/naiveproxy/src/net/quic/mock_decrypter.cc +++ b/naiveproxy/src/net/quic/mock_decrypter.cc @@ -2,15 +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/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "net/quic/mock_decrypter.h" #include +#include "base/compiler_specific.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h" #include "net/third_party/quiche/src/quiche/quic/platform/api/quic_bug_tracker.h" @@ -80,7 +76,7 @@ bool MockDecrypter::DecryptPacket(uint64_t /*packet_number*/, return false; } - memcpy(output, ciphertext.data(), plaintext_size); + UNSAFE_TODO(memcpy(output, ciphertext.data(), plaintext_size)); *output_length = plaintext_size; return true; } diff --git a/naiveproxy/src/net/quic/mock_encrypter.cc b/naiveproxy/src/net/quic/mock_encrypter.cc index 2a3202ddfa..47c5876ad7 100644 --- a/naiveproxy/src/net/quic/mock_encrypter.cc +++ b/naiveproxy/src/net/quic/mock_encrypter.cc @@ -2,13 +2,9 @@ // 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/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "net/quic/mock_encrypter.h" +#include "base/compiler_specific.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_data_writer.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h" @@ -48,7 +44,7 @@ bool MockEncrypter::EncryptPacket(uint64_t /*packet_number*/, if (max_output_length < ciphertext_size) { return false; } - memcpy(output, plaintext.data(), ciphertext_size); + UNSAFE_TODO(memcpy(output, plaintext.data(), ciphertext_size)); *output_length = ciphertext_size; return true; } diff --git a/naiveproxy/src/net/quic/mock_quic_data.cc b/naiveproxy/src/net/quic/mock_quic_data.cc index 2a4d32a5c5..8e522ee314 100644 --- a/naiveproxy/src/net/quic/mock_quic_data.cc +++ b/naiveproxy/src/net/quic/mock_quic_data.cc @@ -24,15 +24,15 @@ void MockQuicData::AddConnect(MockConnectCompleter* completer) { void MockQuicData::AddRead(IoMode mode, std::unique_ptr packet) { - reads_.emplace_back(mode, packet->data(), packet->length(), - sequence_number_++, + reads_.emplace_back(mode, packet->AsStringPiece(), /*result=*/0, + /*seq=*/sequence_number_++, static_cast(packet->ecn_codepoint())); packets_.push_back(std::move(packet)); } void MockQuicData::AddRead(IoMode mode, std::unique_ptr packet) { - reads_.emplace_back(mode, packet->data(), packet->length(), - sequence_number_++, /*tos=*/0); + reads_.emplace_back(mode, packet->AsStringPiece(), /*result=*/0, + /*seq=*/sequence_number_++, /*tos=*/0); packets_.push_back(std::move(packet)); } void MockQuicData::AddRead(IoMode mode, int rv) { @@ -51,8 +51,8 @@ void MockQuicData::AddReadPauseForever() { void MockQuicData::AddWrite(IoMode mode, std::unique_ptr packet) { - writes_.emplace_back(mode, packet->data(), packet->length(), - sequence_number_++); + writes_.emplace_back(mode, packet->AsStringPiece(), /*result=*/0, + /*seq=*/sequence_number_++); packets_.push_back(std::move(packet)); } diff --git a/naiveproxy/src/net/quic/quic_chromium_client_session.cc b/naiveproxy/src/net/quic/quic_chromium_client_session.cc index 8e66f0ef5a..6120cf9670 100644 --- a/naiveproxy/src/net/quic/quic_chromium_client_session.cc +++ b/naiveproxy/src/net/quic/quic_chromium_client_session.cc @@ -57,6 +57,7 @@ #include "net/quic/quic_chromium_packet_writer.h" #include "net/quic/quic_crypto_client_stream_factory.h" #include "net/quic/quic_server_info.h" +#include "net/quic/quic_session_attempt_manager.h" #include "net/quic/quic_session_pool.h" #include "net/socket/datagram_client_socket.h" #include "net/spdy/multiplexed_session_creation_initiator.h" @@ -1276,6 +1277,10 @@ void QuicChromiumClientSession::OnOriginFrame(const quic::OriginFrame& frame) { [&] { return NetLogReceivedOrigins(received_origins_); }); base::UmaHistogramCounts100("Net.QuicSession.NumReceivedOrigins", received_origins_.size()); + + if (session_pool_ && session_pool_->session_attempt_manager()) { + session_pool_->session_attempt_manager()->OnOriginFrame(this); + } } void QuicChromiumClientSession::AddHandle(Handle* handle) { @@ -1403,10 +1408,6 @@ bool QuicChromiumClientSession::ShouldCreateOutgoingBidirectionalStream() { return true; } -bool QuicChromiumClientSession::ShouldCreateOutgoingUnidirectionalStream() { - NOTREACHED() << "Try to create outgoing unidirectional streams"; -} - bool QuicChromiumClientSession::WasConnectionEverUsed() { const quic::QuicConnectionStats& stats = connection()->GetStats(); return stats.bytes_sent > 0 || stats.bytes_received > 0; @@ -1417,11 +1418,6 @@ QuicChromiumClientSession::CreateOutgoingBidirectionalStream() { NOTREACHED() << "CreateOutgoingReliableStreamImpl should be called directly"; } -QuicChromiumClientStream* -QuicChromiumClientSession::CreateOutgoingUnidirectionalStream() { - NOTREACHED() << "Try to create outgoing unidirectional stream"; -} - QuicChromiumClientStream* QuicChromiumClientSession::CreateOutgoingReliableStreamImpl( const NetworkTrafficAnnotationTag& traffic_annotation) { diff --git a/naiveproxy/src/net/quic/quic_chromium_client_session.h b/naiveproxy/src/net/quic/quic_chromium_client_session.h index 44cf6fe0f8..5f3bd8aabe 100644 --- a/naiveproxy/src/net/quic/quic_chromium_client_session.h +++ b/naiveproxy/src/net/quic/quic_chromium_client_session.h @@ -745,7 +745,6 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession // quic::QuicSession methods: QuicChromiumClientStream* CreateOutgoingBidirectionalStream() override; - QuicChromiumClientStream* CreateOutgoingUnidirectionalStream() override; const quic::QuicCryptoClientStream* GetCryptoStream() const override; quic::QuicCryptoClientStream* GetMutableCryptoStream() override; void SetDefaultEncryptionLevel(quic::EncryptionLevel level) override; @@ -983,7 +982,6 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession // quic::QuicSession methods: bool ShouldCreateIncomingStream(quic::QuicStreamId id) override; bool ShouldCreateOutgoingBidirectionalStream() override; - bool ShouldCreateOutgoingUnidirectionalStream() override; QuicChromiumClientStream* CreateIncomingStream( quic::QuicStreamId id) override; diff --git a/naiveproxy/src/net/quic/quic_chromium_client_stream.cc b/naiveproxy/src/net/quic/quic_chromium_client_stream.cc index f6becb91d0..1a267f5f48 100644 --- a/naiveproxy/src/net/quic/quic_chromium_client_stream.cc +++ b/naiveproxy/src/net/quic/quic_chromium_client_stream.cc @@ -2,16 +2,12 @@ // 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/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "net/quic/quic_chromium_client_stream.h" #include #include +#include "base/containers/span.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/location.h" @@ -19,6 +15,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/metrics/histogram_functions.h" +#include "base/strings/strcat.h" #include "base/task/single_thread_task_runner.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" @@ -313,10 +310,7 @@ int QuicChromiumClientStream::Handle::WriteConnectUdpPayload( // Set Context ID to zero as per RFC 9298 // (https://datatracker.ietf.org/doc/html/rfc9298#name-http-datagram-payload-forma) // and copy packet data. - std::string http_payload; - http_payload.resize(1 + packet.size()); - http_payload[0] = 0; - memcpy(&http_payload[1], packet.data(), packet.size()); + std::string http_payload = base::StrCat({std::string(1, '\0'), packet}); // Attempt to send the HTTP payload as a datagram over the stream. quic::MessageStatus message_status = stream_->SendHttp3Datagram(http_payload); diff --git a/naiveproxy/src/net/quic/quic_chromium_packet_writer.cc b/naiveproxy/src/net/quic/quic_chromium_packet_writer.cc index 53444bf20d..c36b4f6ad2 100644 --- a/naiveproxy/src/net/quic/quic_chromium_packet_writer.cc +++ b/naiveproxy/src/net/quic/quic_chromium_packet_writer.cc @@ -2,17 +2,14 @@ // 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/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "net/quic/quic_chromium_packet_writer.h" #include #include #include "base/check_op.h" +#include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/functional/bind.h" #include "base/location.h" #include "base/metrics/histogram_macros.h" @@ -100,7 +97,8 @@ void QuicChromiumPacketWriter::ReusableIOBuffer::Set(const char* buffer, CHECK_LE(buf_len, capacity_); CHECK(HasOneRef()); size_ = buf_len; - std::memcpy(data(), buffer, buf_len); + span().copy_prefix_from( + base::as_bytes(UNSAFE_TODO(base::span(buffer, buf_len)))); } QuicChromiumPacketWriter::QuicChromiumPacketWriter( diff --git a/naiveproxy/src/net/quic/quic_crypto_client_stream_factory.cc b/naiveproxy/src/net/quic/quic_crypto_client_stream_factory.cc index 0983164bab..7935fb31d4 100644 --- a/naiveproxy/src/net/quic/quic_crypto_client_stream_factory.cc +++ b/naiveproxy/src/net/quic/quic_crypto_client_stream_factory.cc @@ -4,7 +4,7 @@ #include "net/quic/quic_crypto_client_stream_factory.h" -#include "base/lazy_instance.h" +#include "base/no_destructor.h" #include "net/quic/crypto/proof_verifier_chromium.h" #include "net/quic/quic_chromium_client_session.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_stream.h" @@ -26,15 +26,13 @@ class DefaultCryptoStreamFactory : public QuicCryptoClientStreamFactory { } }; -static base::LazyInstance::Leaky - g_default_crypto_stream_factory = LAZY_INSTANCE_INITIALIZER; - } // namespace // static QuicCryptoClientStreamFactory* QuicCryptoClientStreamFactory::GetDefaultFactory() { - return g_default_crypto_stream_factory.Pointer(); + static base::NoDestructor factory; + return factory.get(); } } // namespace net diff --git a/naiveproxy/src/net/quic/quic_endpoint.cc b/naiveproxy/src/net/quic/quic_endpoint.cc new file mode 100644 index 0000000000..a674eb73b5 --- /dev/null +++ b/naiveproxy/src/net/quic/quic_endpoint.cc @@ -0,0 +1,28 @@ +// Copyright 2025 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/quic/quic_endpoint.h" + +#include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h" + +namespace net { + +QuicEndpoint::QuicEndpoint(quic::ParsedQuicVersion quic_version, + IPEndPoint ip_endpoint, + ConnectionEndpointMetadata metadata) + : quic_version(quic_version), + ip_endpoint(ip_endpoint), + metadata(metadata) {} + +QuicEndpoint::~QuicEndpoint() = default; + +base::Value::Dict QuicEndpoint::ToValue() const { + base::Value::Dict dict; + dict.Set("quic_version", quic::ParsedQuicVersionToString(quic_version)); + dict.Set("ip_endpoint", ip_endpoint.ToString()); + dict.Set("metadata", metadata.ToValue()); + return dict; +} + +} // namespace net diff --git a/naiveproxy/src/net/quic/quic_endpoint.h b/naiveproxy/src/net/quic/quic_endpoint.h new file mode 100644 index 0000000000..49320701dc --- /dev/null +++ b/naiveproxy/src/net/quic/quic_endpoint.h @@ -0,0 +1,39 @@ +// Copyright 2025 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_QUIC_QUIC_ENDPOINT_H_ +#define NET_QUIC_QUIC_ENDPOINT_H_ + +#include "base/values.h" +#include "net/base/connection_endpoint_metadata.h" +#include "net/base/ip_endpoint.h" +#include "net/base/net_export.h" +#include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h" + +namespace net { + +// Represents a single QUIC endpoint and the information necessary to attempt +// a QUIC session. +struct NET_EXPORT_PRIVATE QuicEndpoint { + QuicEndpoint(quic::ParsedQuicVersion quic_version, + IPEndPoint ip_endpoint, + ConnectionEndpointMetadata metadata); + + QuicEndpoint(QuicEndpoint&&) = default; + QuicEndpoint& operator=(QuicEndpoint&&) = default; + QuicEndpoint(const QuicEndpoint&) = default; + QuicEndpoint& operator=(const QuicEndpoint&) = default; + + ~QuicEndpoint(); + + quic::ParsedQuicVersion quic_version = quic::ParsedQuicVersion::Unsupported(); + IPEndPoint ip_endpoint; + ConnectionEndpointMetadata metadata; + + base::Value::Dict ToValue() const; +}; + +} // namespace net + +#endif // NET_QUIC_QUIC_ENDPOINT_H_ diff --git a/naiveproxy/src/net/quic/quic_http3_logger.cc b/naiveproxy/src/net/quic/quic_http3_logger.cc index b127311f6b..943c8ba1d6 100644 --- a/naiveproxy/src/net/quic/quic_http3_logger.cc +++ b/naiveproxy/src/net/quic/quic_http3_logger.cc @@ -222,7 +222,7 @@ void QuicHttp3Logger::OnHeadersFrameReceived( } void QuicHttp3Logger::OnHeadersDecoded(quic::QuicStreamId stream_id, - quic::QuicHeaderList headers) { + const quic::QuicHeaderList& headers) { if (!net_log_.IsCapturing()) { return; } diff --git a/naiveproxy/src/net/quic/quic_http3_logger.h b/naiveproxy/src/net/quic/quic_http3_logger.h index 889fa783e8..4852b783a0 100644 --- a/naiveproxy/src/net/quic/quic_http3_logger.h +++ b/naiveproxy/src/net/quic/quic_http3_logger.h @@ -45,7 +45,7 @@ class NET_EXPORT_PRIVATE QuicHttp3Logger : public quic::Http3DebugVisitor { quic::QuicStreamId stream_id, quic::QuicByteCount compressed_headers_length) override; void OnHeadersDecoded(quic::QuicStreamId stream_id, - quic::QuicHeaderList headers) override; + const quic::QuicHeaderList& headers) override; void OnUnknownFrameReceived(quic::QuicStreamId stream_id, uint64_t frame_type, 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 6a1fc1c24c..600dd1c211 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 @@ -6,6 +6,7 @@ #define NET_QUIC_QUIC_PROXY_CLIENT_SOCKET_TEST_BASE_H_ #include +#include #include #include "base/memory/ptr_util.h" @@ -56,46 +57,37 @@ #include "url/scheme_host_port.h" #include "url/url_constants.h" -namespace { - -inline constexpr char kOriginHost[] = "www.google.com"; -inline constexpr int kOriginPort = 443; -inline constexpr char kProxyUrl[] = "https://myproxy:6121/"; -inline constexpr char kProxyHost[] = "myproxy"; -inline constexpr int kProxyPort = 6121; -inline constexpr char kUserAgent[] = "Mozilla/1.0"; -inline constexpr char kRedirectUrl[] = "https://example.com/"; - -inline constexpr char kMsg1[] = "\0hello!\xff"; -inline constexpr int kLen1 = 8; -inline constexpr char kMsg2[] = "\0a2345678\0"; -inline constexpr int kLen2 = 10; -inline constexpr char kMsg3[] = "bye!"; -inline constexpr int kLen3 = 4; -inline constexpr char kMsg33[] = "bye!bye!"; -inline constexpr int kLen33 = kLen3 + kLen3; -inline constexpr char kMsg333[] = "bye!bye!bye!"; -inline constexpr int kLen333 = kLen3 + kLen3 + kLen3; - -inline constexpr char kDatagramPayload[] = "youveGotMail"; -inline constexpr int kDatagramLen = 12; - -static inline constexpr int k0ByteConnectionId = 0; -static inline constexpr int k8ByteConnectionId = 8; - -inline constexpr char kTestHeaderName[] = "Foo"; -// Note: `kTestQuicHeaderName` should be a lowercase version of -// `kTestHeaderName`. -inline constexpr char kTestQuicHeaderName[] = "foo"; - -} // anonymous namespace - namespace net { class QuicProxyClientSocketTestBase : public ::testing::TestWithParam, public WithTaskEnvironment { public: + static constexpr char kOriginHost[] = "www.google.com"; + static constexpr int kOriginPort = 443; + static constexpr char kProxyUrl[] = "https://myproxy:6121/"; + static constexpr char kProxyHost[] = "myproxy"; + static constexpr int kProxyPort = 6121; + static constexpr char kUserAgent[] = "Mozilla/1.0"; + static constexpr char kRedirectUrl[] = "https://example.com/"; + + static constexpr auto kMsg1 = base::span_from_cstring("\0hello!\xff"); + static constexpr auto kMsg2 = base::span_from_cstring("\0a2345678\0"); + static constexpr auto kMsg3 = base::span_from_cstring("bye!"); + static constexpr auto kMsg33 = base::span_from_cstring("bye!bye!"); + static constexpr auto kMsg333 = base::span_from_cstring("bye!bye!bye!"); + + static constexpr auto kDatagramPayload = + base::span_from_cstring("youveGotMail"); + + static constexpr int k0ByteConnectionId = 0; + static constexpr int k8ByteConnectionId = 8; + + static constexpr char kTestHeaderName[] = "Foo"; + // Note: `kTestQuicHeaderName` should be a lowercase version of + // `kTestHeaderName`. + static constexpr char kTestQuicHeaderName[] = "foo"; + QuicProxyClientSocketTestBase(); QuicProxyClientSocketTestBase(const QuicProxyClientSocketTestBase&) = delete; QuicProxyClientSocketTestBase& operator=( @@ -224,16 +216,16 @@ class QuicProxyClientSocketTestBase virtual void AssertConnectFails(int result) = 0; - virtual void AssertWriteReturns(const char* data, int len, int rv) = 0; + virtual void AssertWriteReturns(base::span data, int rv) = 0; - virtual void AssertSyncWriteSucceeds(const char* data, int len) = 0; + virtual void AssertSyncWriteSucceeds(base::span data) = 0; - virtual void AssertSyncReadEquals(const char* data, int len) = 0; - virtual void AssertAsyncReadEquals(const char* data, int len) = 0; + virtual void AssertSyncReadEquals(base::span data) = 0; + virtual void AssertAsyncReadEquals(base::span data) = 0; - virtual void AssertReadStarts(const char* data, int len) = 0; + virtual void AssertReadStarts(base::span data) = 0; - virtual void AssertReadReturns(const char* data, int len) = 0; + virtual void AssertReadReturns(base::span data) = 0; std::string ConstructDataHeader(size_t body_len); 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 fefd6ebdcd..73c3b1b523 100644 --- a/naiveproxy/src/net/quic/quic_proxy_datagram_client_socket.cc +++ b/naiveproxy/src/net/quic/quic_proxy_datagram_client_socket.cc @@ -2,13 +2,9 @@ // 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/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "net/quic/quic_proxy_datagram_client_socket.h" +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/strings/string_number_conversions.h" @@ -176,7 +172,7 @@ void QuicProxyDatagramClientSocket::OnHttp3Datagram( CHECK(read_buf_ != nullptr); CHECK(read_buf_len_ > 0); - std::memcpy(read_buf_->data(), http_payload.data(), http_payload.size()); + read_buf_->span().copy_prefix_from(base::as_byte_span(http_payload)); result = bytes_read; } @@ -284,7 +280,7 @@ int QuicProxyDatagramClientSocket::Read(IOBuffer* buf, if (datagram.size() > static_cast(buf_len)) { result = ERR_MSG_TOO_BIG; } else { - std::memcpy(buf->data(), datagram.data(), datagram.size()); + buf->span().copy_prefix_from(base::as_byte_span(datagram)); result = bytes_read; } datagrams_.pop(); diff --git a/naiveproxy/src/net/quic/quic_session_attempt.h b/naiveproxy/src/net/quic/quic_session_attempt.h index b702cdd7ef..1781433e6d 100644 --- a/naiveproxy/src/net/quic/quic_session_attempt.h +++ b/naiveproxy/src/net/quic/quic_session_attempt.h @@ -102,6 +102,12 @@ class NET_EXPORT_PRIVATE QuicSessionAttempt { bool session_creation_finished() const { return session_creation_finished_; } + const quic::ParsedQuicVersion& quic_version() const { return quic_version_; } + + const IPEndPoint& ip_endpoint() const { return ip_endpoint_; } + + const ConnectionEndpointMetadata& metadata() const { return metadata_; } + QuicChromiumClientSession* session() const { return session_.get(); } void PopulateNetErrorDetails(NetErrorDetails* details) const; diff --git a/naiveproxy/src/net/quic/quic_session_attempt_manager.cc b/naiveproxy/src/net/quic/quic_session_attempt_manager.cc new file mode 100644 index 0000000000..e1c35c22de --- /dev/null +++ b/naiveproxy/src/net/quic/quic_session_attempt_manager.cc @@ -0,0 +1,275 @@ +// Copyright 2025 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/quic/quic_session_attempt_manager.h" + +#include +#include +#include +#include + +#include "base/check.h" +#include "base/containers/flat_map.h" +#include "base/memory/ptr_util.h" +#include "base/memory/raw_ptr.h" +#include "base/time/time.h" +#include "net/base/net_errors.h" +#include "net/base/net_export.h" +#include "net/base/reconnect_notifier.h" +#include "net/log/net_log_with_source.h" +#include "net/quic/quic_chromium_client_session.h" +#include "net/quic/quic_endpoint.h" +#include "net/quic/quic_session_alias_key.h" +#include "net/quic/quic_session_attempt.h" +#include "net/quic/quic_session_attempt_request.h" +#include "net/quic/quic_session_pool.h" + +namespace net { + +// A Job is responsible for creating a QUIC session for a specific +// QuicSessionAliasKey. It manages multiple concurrent connection attempts +// (`QuicSessionAttempt`) to different endpoints and notifies multiple clients +// (`QuicSessionAttemptRequest`) upon completion. +// +// If any attempt succeeds, the Job immediately notifies all waiting requests +// and cancels any other ongoing attempts. If an attempt fails, the Job will +// wait for other attempts to complete. Only when the last attempt fails does +// the Job notify all waiting requests of the failure. +// +// The Job is owned by the QuicSessionAttemptManager and is destroyed once the +// session is created or all attempts have failed. +class QuicSessionAttemptManager::Job : public QuicSessionAttempt::Delegate { + public: + Job(QuicSessionAttemptManager* manager, + QuicSessionAliasKey key, + const NetLogWithSource& net_log) + : manager_(manager), key_(std::move(key)), net_log_(net_log) {} + + ~Job() override { + // Notify all pending requests that the job is aborted. + if (!requests_.empty()) { + NotifyRequests(ERR_ABORTED, /*session=*/nullptr, NetErrorDetails()); + } + } + + Job(const Job&) = delete; + Job& operator=(const Job&) = delete; + + // Attempts to create a QUIC session for the given endpoint. If an attempt + // already exists for the endpoint, returns ERR_IO_PENDING and the request + // will be notified when the attempt completes. Otherwise, a new attempt is + // created and started, and the request will be notified when the attempt + // completes. + // + // The request will be added to the job and notified upon completion. + int MaybeAttemptEndpoint( + QuicSessionAttemptRequest* request, + QuicEndpoint endpoint, + int cert_verify_flags, + base::TimeTicks dns_resolution_start_time, + base::TimeTicks dns_resolution_end_time, + bool use_dns_aliases, + std::set dns_aliases, + MultiplexedSessionCreationInitiator session_creation_initiator, + std::optional connection_management_config) { + AddRequest(request); + + if (FindAttempt(endpoint)) { + return ERR_IO_PENDING; + } + + std::unique_ptr attempt = + manager_->pool_->CreateSessionAttempt( + this, key_.session_key(), endpoint, cert_verify_flags, + dns_resolution_start_time, dns_resolution_end_time, use_dns_aliases, + std::move(dns_aliases), session_creation_initiator, + std::move(connection_management_config)); + QuicSessionAttempt* raw_attempt = attempt.get(); + auto [it, inserted] = attempts_.emplace(std::move(attempt)); + CHECK(inserted); + int rv = raw_attempt->Start(base::BindOnce( + &Job::OnAttemptComplete, base::Unretained(this), raw_attempt)); + if (rv != ERR_IO_PENDING) { + // If the attempt failed synchronously but there are other attempts, wait + // for them to complete. + if (rv != OK && attempts_.size() > 1) { + attempts_.erase(it); + return ERR_IO_PENDING; + } + OnAttemptComplete(raw_attempt, rv); + } + return rv; + } + + // Called by QuicSessionAttemptRequest to remove itself from the job. + void RemoveRequest(QuicSessionAttemptRequest* request) { + auto it = requests_.find(request); + CHECK(it != requests_.end()); + requests_.erase(it); + + if (requests_.empty()) { + manager_->OnJobComplete(this); + // `this` is deleted. + } + } + + void OnOriginFrameMatched(QuicChromiumClientSession* session) { + NotifyRequestsAndComplete(OK, session, NetErrorDetails()); + // `this` is deleted. + } + + // QuicSessionAttempt::Delegate implementation. + QuicSessionPool* GetQuicSessionPool() override { return manager_->pool_; } + const QuicSessionAliasKey& GetKey() override { return key_; } + const NetLogWithSource& GetNetLog() override { return net_log_; } + + private: + void OnAttemptComplete(QuicSessionAttempt* raw_attempt, int rv) { + auto it = attempts_.find(raw_attempt); + CHECK(it != attempts_.end()); + + NetErrorDetails error_details; + if (rv == OK) { + QuicChromiumClientSession* session = raw_attempt->session(); + attempts_.erase(it); + NotifyRequestsAndComplete(rv, session, std::move(error_details)); + return; + } + + raw_attempt->PopulateNetErrorDetails(&error_details); + attempts_.erase(it); + if (!attempts_.empty()) { + // Wait for other attempts to complete. + return; + } + + NotifyRequestsAndComplete(rv, /*session=*/nullptr, + std::move(error_details)); + } + + void AddRequest(QuicSessionAttemptRequest* request) { + auto [_, inserted] = requests_.insert(request); + CHECK(inserted); + } + + QuicSessionAttempt* FindAttempt(const QuicEndpoint& endpoint) { + auto it = std::ranges::find_if(attempts_, [&](const auto& attempt) { + return attempt->quic_version() == endpoint.quic_version && + attempt->ip_endpoint() == endpoint.ip_endpoint && + attempt->metadata() == endpoint.metadata; + }); + return it == attempts_.end() ? nullptr : it->get(); + } + + // Notifies all requests that the job is complete. + void NotifyRequests(int rv, + QuicChromiumClientSession* session, + NetErrorDetails error_details) { + // Cancel other attempts. + attempts_.clear(); + + while (!requests_.empty()) { + raw_ptr request = + requests_.extract(requests_.begin()).value(); + // Use ExtractAsDangling() because `request` may delete itself. + request.ExtractAsDangling()->Complete(rv, session, error_details); + } + CHECK(requests_.empty()); + } + + void NotifyRequestsAndComplete(int rv, + QuicChromiumClientSession* session, + NetErrorDetails error_details) { + NotifyRequests(rv, session, std::move(error_details)); + manager_->OnJobComplete(this); + // `this` is deleted. + } + + raw_ptr manager_; + QuicSessionAliasKey key_; + + NetLogWithSource net_log_; + + std::set> requests_; + + base::flat_set, base::UniquePtrComparator> + attempts_; +}; + +QuicSessionAttemptManager::QuicSessionAttemptManager(QuicSessionPool* pool) + : pool_(pool) {} + +QuicSessionAttemptManager::~QuicSessionAttemptManager() { + // Clear the active jobs, first moving out of the instance variable so that + // calls to RemoveRequest for any pending requests do not cause recursion. + base::flat_map> active_jobs = + std::move(active_jobs_); + active_jobs.clear(); +} + +std::unique_ptr +QuicSessionAttemptManager::CreateRequest(QuicSessionAliasKey key) { + return base::WrapUnique(new QuicSessionAttemptRequest(this, std::move(key))); +} + +int QuicSessionAttemptManager::RequestSession( + QuicSessionAttemptRequest* request, + QuicEndpoint endpoint, + int cert_verify_flags, + base::TimeTicks dns_resolution_start_time, + base::TimeTicks dns_resolution_end_time, + bool use_dns_aliases, + std::set dns_aliases, + MultiplexedSessionCreationInitiator session_creation_initiator, + std::optional connection_management_config, + const NetLogWithSource& net_log) { + auto it = active_jobs_.find(request->key_); + if (it == active_jobs_.end()) { + it = active_jobs_ + .try_emplace(request->key_, + std::make_unique(this, request->key_, net_log)) + .first; + } + + return it->second->MaybeAttemptEndpoint( + request, endpoint, cert_verify_flags, dns_resolution_start_time, + dns_resolution_end_time, use_dns_aliases, std::move(dns_aliases), + session_creation_initiator, std::move(connection_management_config)); +} + +void QuicSessionAttemptManager::RemoveRequest( + QuicSessionAttemptRequest* request) { + auto it = active_jobs_.find(request->key_); + if (it == active_jobs_.end()) { + return; + } + it->second->RemoveRequest(request); +} + +void QuicSessionAttemptManager::OnOriginFrame( + QuicChromiumClientSession* session) { + // Collect jobs that can be completed with `session` and then notify them + // later to avoid erasing jobs during the loop. + std::vector matched_jobs; + for (auto& [key, job] : active_jobs_) { + if (pool_->CanWaiveIpMatching(key.destination(), session) && + session->CanPool(key.session_key().host(), key.session_key())) { + matched_jobs.push_back(job.get()); + } + } + + for (auto job : matched_jobs) { + job->OnOriginFrameMatched(session); + // `job` was removed from `active_jobs_` and it was deleted. + } + matched_jobs.clear(); +} + +void QuicSessionAttemptManager::OnJobComplete(Job* job) { + auto it = active_jobs_.find(job->GetKey()); + CHECK(it != active_jobs_.end()); + active_jobs_.erase(it); +} + +} // namespace net diff --git a/naiveproxy/src/net/quic/quic_session_attempt_manager.h b/naiveproxy/src/net/quic/quic_session_attempt_manager.h new file mode 100644 index 0000000000..06f57a8be9 --- /dev/null +++ b/naiveproxy/src/net/quic/quic_session_attempt_manager.h @@ -0,0 +1,98 @@ +// Copyright 2025 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_QUIC_QUIC_SESSION_ATTEMPT_MANAGER_H_ +#define NET_QUIC_QUIC_SESSION_ATTEMPT_MANAGER_H_ + +#include +#include +#include +#include + +#include "base/containers/flat_map.h" +#include "base/memory/raw_ptr.h" +#include "base/time/time.h" +#include "net/base/net_export.h" +#include "net/base/reconnect_notifier.h" +#include "net/quic/quic_endpoint.h" +#include "net/quic/quic_session_alias_key.h" +#include "net/quic/quic_session_pool.h" + +namespace net { + +class QuicChromiumClientSession; +class QuicSessionAttemptRequest; +class NetLogWithSource; + +// Manages all in-flight QUIC session attempts. For each QuicSessionAliasKey +// that a client has requested, there can be at most one active +// QuicSessionAttemptManager::Job. A Job manages all attempts for the +// QuicSessionAliasKey (e.g. to different IP addresses) and all clients waiting +// for the result. +// +// The relationship between the manager, jobs, requests, and attempts is as +// follows: +// +// +-------------- QuicSessionAttemptManager -------------+ +// | | | +// Job Job Job +// (for Key1) (for Key2) (for KeyX) +// / \ / \ / \ +// Requests Attempts Requests Attempts Requests Attempts +// | | | | | | +// Request... Attempt... Request... Attempt... Request... Attempt... +// (client A) (endpoint 1) (client C) (endpoint 3) (client X) (endpoint X) +// (client B) (endpoint 2) (endpoint 4) +// +// Owned by the QuicSessionPool. +class NET_EXPORT_PRIVATE QuicSessionAttemptManager { + public: + explicit QuicSessionAttemptManager(QuicSessionPool* pool); + + ~QuicSessionAttemptManager(); + + // Creates a new QuicSessionAttemptRequest for the given key. + std::unique_ptr CreateRequest( + QuicSessionAliasKey key); + + // Called by QuicSessionAttemptRequest to request a session. See + // QuicSessionAttemptRequest for more details. + int RequestSession( + QuicSessionAttemptRequest* request, + QuicEndpoint endpoint, + int cert_verify_flags, + base::TimeTicks dns_resolution_start_time, + base::TimeTicks dns_resolution_end_time, + bool use_dns_aliases, + std::set dns_aliases, + MultiplexedSessionCreationInitiator session_creation_initiator, + std::optional connection_management_config, + const NetLogWithSource& net_log); + + // Called by QuicSessionAttemptRequest to remove itself from the manager. + void RemoveRequest(QuicSessionAttemptRequest* request); + + // Called when `session` received an HTTP/3 Origin frame. Checks if `session` + // can be used to satisfy any active jobs. All jobs that can be satisfied by + // `session` are completed successfully. + void OnOriginFrame(QuicChromiumClientSession* session); + + bool HasActiveJobForTesting(const QuicSessionAliasKey& key) const { + return active_jobs_.find(key) != active_jobs_.end(); + } + + private: + class Job; + + // Called by Job when the last request is completed. + void OnJobComplete(Job* job); + + const raw_ptr pool_; + + base::flat_map> active_jobs_; +}; + +} // namespace net + +#endif // NET_QUIC_QUIC_SESSION_ATTEMPT_MANAGER_H_ diff --git a/naiveproxy/src/net/quic/quic_session_attempt_request.cc b/naiveproxy/src/net/quic/quic_session_attempt_request.cc new file mode 100644 index 0000000000..12c7b0dfa7 --- /dev/null +++ b/naiveproxy/src/net/quic/quic_session_attempt_request.cc @@ -0,0 +1,70 @@ +// Copyright 2025 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/quic/quic_session_attempt_request.h" + +#include +#include +#include +#include + +#include "base/check.h" +#include "net/base/completion_once_callback.h" +#include "net/base/net_error_details.h" +#include "net/base/net_errors.h" +#include "net/quic/quic_session_attempt_manager.h" + +namespace net { + +QuicSessionAttemptRequest::QuicSessionAttemptRequest( + QuicSessionAttemptManager* manager, + QuicSessionAliasKey key) + : manager_(manager), key_(std::move(key)) {} + +QuicSessionAttemptRequest::~QuicSessionAttemptRequest() { + if (manager_ && callback_) { + manager_->RemoveRequest(this); + } +} + +int QuicSessionAttemptRequest::RequestSession( + QuicEndpoint endpoint, + int cert_verify_flags, + base::TimeTicks dns_resolution_start_time, + base::TimeTicks dns_resolution_end_time, + bool use_dns_aliases, + std::set dns_aliases, + MultiplexedSessionCreationInitiator session_creation_initiator, + std::optional connection_management_config, + const NetLogWithSource& net_log, + CompletionOnceCallback callback) { + int rv = manager_->RequestSession( + this, std::move(endpoint), cert_verify_flags, dns_resolution_start_time, + dns_resolution_end_time, use_dns_aliases, std::move(dns_aliases), + session_creation_initiator, std::move(connection_management_config), + net_log); + if (rv == ERR_IO_PENDING) { + CHECK(!completed_); + callback_ = std::move(callback); + } else { + CHECK(completed_); + } + return rv; +} + +void QuicSessionAttemptRequest::Complete(int rv, + QuicChromiumClientSession* session, + NetErrorDetails error_details) { + CHECK(!completed_); + completed_ = true; + session_ = session; + error_details_ = std::move(error_details); + + manager_ = nullptr; + if (callback_) { + std::move(callback_).Run(rv); + } +} + +} // namespace net diff --git a/naiveproxy/src/net/quic/quic_session_attempt_request.h b/naiveproxy/src/net/quic/quic_session_attempt_request.h new file mode 100644 index 0000000000..77e1cd51de --- /dev/null +++ b/naiveproxy/src/net/quic/quic_session_attempt_request.h @@ -0,0 +1,89 @@ +// Copyright 2025 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_QUIC_QUIC_SESSION_ATTEMPT_REQUEST_H_ +#define NET_QUIC_QUIC_SESSION_ATTEMPT_REQUEST_H_ + +#include +#include +#include + +#include "base/check.h" +#include "base/memory/raw_ptr.h" +#include "net/base/completion_once_callback.h" +#include "net/base/net_error_details.h" +#include "net/base/net_export.h" +#include "net/quic/quic_session_alias_key.h" +#include "net/quic/quic_session_pool.h" + +namespace net { + +class QuicSessionAttemptManager; + +// Represents a request to attempt creation of a new QUIC session. This class +// is owned by the creator of the request. If the request is still pending when +// the request is destroyed, it will be cancelled. +class NET_EXPORT_PRIVATE QuicSessionAttemptRequest { + public: + QuicSessionAttemptRequest(const QuicSessionAttemptRequest&) = delete; + QuicSessionAttemptRequest& operator=(const QuicSessionAttemptRequest&) = + delete; + + ~QuicSessionAttemptRequest(); + + // Requests a QUIC session. If the request is completed synchronously, returns + // the result. If the request is completed asynchronously, returns + // ERR_IO_PENDING and `callback` will be invoked later. See also + // `QuicSessionAttempt`. + int RequestSession( + QuicEndpoint endpoint, + int cert_verify_flags, + base::TimeTicks dns_resolution_start_time, + base::TimeTicks dns_resolution_end_time, + bool use_dns_aliases, + std::set dns_aliases, + MultiplexedSessionCreationInitiator session_creation_initiator, + std::optional connection_management_config, + const NetLogWithSource& net_log, + CompletionOnceCallback callback); + + const QuicSessionAliasKey& key() const { return key_; } + + // Returns the error details of the request. Populated only if the request is + // failed. Only valid to call after the request is completed. + const NetErrorDetails& error_details() const { + CHECK(completed_); + return error_details_; + } + + // Returns the session of the request. Can be nullptr if the request is + // failed. Only valid to call after the request is completed. + raw_ptr session() const { + CHECK(completed_); + return session_; + } + + private: + friend class QuicSessionAttemptManager; + + explicit QuicSessionAttemptRequest(QuicSessionAttemptManager* manager, + QuicSessionAliasKey key); + + void Complete(int rv, + QuicChromiumClientSession* session, + NetErrorDetails error_details); + + raw_ptr manager_; + const QuicSessionAliasKey key_; + + bool completed_ = false; + CompletionOnceCallback callback_; + + NetErrorDetails error_details_; + raw_ptr session_; +}; + +} // namespace net + +#endif // NET_QUIC_QUIC_SESSION_ATTEMPT_REQUEST_H_ diff --git a/naiveproxy/src/net/quic/quic_session_pool.cc b/naiveproxy/src/net/quic/quic_session_pool.cc index d8fa959bf3..fd239e0b51 100644 --- a/naiveproxy/src/net/quic/quic_session_pool.cc +++ b/naiveproxy/src/net/quic/quic_session_pool.cc @@ -29,6 +29,7 @@ #include "base/strings/stringprintf.h" #include "base/task/sequenced_task_runner.h" #include "base/task/single_thread_task_runner.h" +#include "base/trace_event/trace_event.h" #include "base/values.h" #include "crypto/openssl_util.h" #include "net/base/address_list.h" @@ -43,7 +44,6 @@ #include "net/base/reconnect_notifier.h" #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" @@ -64,6 +64,7 @@ #include "net/quic/quic_context.h" #include "net/quic/quic_crypto_client_stream_factory.h" #include "net/quic/quic_server_info.h" +#include "net/quic/quic_session_attempt_manager.h" #include "net/quic/quic_session_key.h" #include "net/quic/quic_session_pool_direct_job.h" #include "net/quic/quic_session_pool_job.h" @@ -520,23 +521,6 @@ void QuicSessionRequest::SetSession( session_ = std::move(session); } -QuicEndpoint::QuicEndpoint(quic::ParsedQuicVersion quic_version, - IPEndPoint ip_endpoint, - ConnectionEndpointMetadata metadata) - : quic_version(quic_version), - ip_endpoint(ip_endpoint), - metadata(metadata) {} - -QuicEndpoint::~QuicEndpoint() = default; - -base::Value::Dict QuicEndpoint::ToValue() const { - base::Value::Dict dict; - dict.Set("quic_version", quic::ParsedQuicVersionToString(quic_version)); - dict.Set("ip_endpoint", ip_endpoint.ToString()); - dict.Set("metadata", metadata.ToValue()); - return dict; -} - QuicSessionPool::QuicCryptoClientConfigOwner::QuicCryptoClientConfigOwner( std::unique_ptr proof_verifier, std::unique_ptr session_cache, @@ -673,7 +657,9 @@ QuicSessionPool::QuicSessionPool( quic_context->params()->skip_dns_with_origin_frame), ignore_ip_matching_when_finding_existing_sessions_( quic_context->params() - ->ignore_ip_matching_when_finding_existing_sessions) { + ->ignore_ip_matching_when_finding_existing_sessions), + session_attempt_manager_( + std::make_unique(this)) { DCHECK(transport_security_state_); DCHECK(http_server_properties_); if (params_.disable_tls_zero_rtt) { @@ -690,6 +676,10 @@ QuicSessionPool::~QuicSessionPool() { CloseAllSessions(ERR_ABORTED, quic::QUIC_CONNECTION_CANCELLED); all_sessions_.clear(); + // Reset session attempt manager to ensure there is no active crypto config + // map. + session_attempt_manager_.reset(); + // Clear the active jobs, first moving out of the instance variable so that // calls to CancelRequest for any pending requests do not cause recursion. JobMap active_jobs = std::move(active_jobs_); @@ -1638,7 +1628,6 @@ void QuicSessionPool::OnJobComplete( Job* job, std::optional proxy_connect_start_time, int rv) { - auto iter = active_jobs_.find(job->key().session_key()); if (proxy_connect_start_time) { HttpProxyConnectJob::EmitConnectLatency( NextProto::kProtoQUIC, ProxyServer::Scheme::SCHEME_QUIC, @@ -1647,7 +1636,16 @@ void QuicSessionPool::OnJobComplete( base::TimeTicks::Now() - *proxy_connect_start_time); } - CHECK(iter != active_jobs_.end()); + auto job_iter = active_jobs_.find(job->key().session_key()); + CHECK(job_iter != active_jobs_.end()); + CHECK_EQ(job_iter->second.get(), job); + // Remove the job so it doesn't get reused by any new requests that are + // added synchronously by QuicSessionRequest::OnRequestComplete() below. + std::unique_ptr completed_job = std::move(job_iter->second); + active_jobs_.erase(job_iter); + + job->set_is_deleting(); + if (rv == OK) { if (!has_quic_ever_worked_on_current_network_) { set_has_quic_ever_worked_on_current_network(true); @@ -1656,7 +1654,7 @@ void QuicSessionPool::OnJobComplete( auto session_it = active_sessions_.find(job->key().session_key()); CHECK(session_it != active_sessions_.end()); QuicChromiumClientSession* session = session_it->second; - for (QuicSessionRequest* request : iter->second->requests()) { + for (QuicSessionRequest* request : job->requests()) { // Do not notify |request| yet. request->SetSession(session->CreateHandle(job->key().destination())); } @@ -1664,7 +1662,7 @@ void QuicSessionPool::OnJobComplete( NotifyOnConnectionFailure(job->key().session_key()); } - for (QuicSessionRequest* request : iter->second->requests()) { + for (QuicSessionRequest* request : job->requests()) { // Even though we're invoking callbacks here, we don't need to worry // about |this| being deleted, because the pool is owned by the // profile which can not be deleted via callbacks. @@ -1673,7 +1671,6 @@ void QuicSessionPool::OnJobComplete( } request->OnRequestComplete(rv); } - active_jobs_.erase(iter); } bool QuicSessionPool::HasActiveSession( diff --git a/naiveproxy/src/net/quic/quic_session_pool.h b/naiveproxy/src/net/quic/quic_session_pool.h index bc2c0b10c2..2068d398fe 100644 --- a/naiveproxy/src/net/quic/quic_session_pool.h +++ b/naiveproxy/src/net/quic/quic_session_pool.h @@ -52,6 +52,7 @@ #include "net/quic/quic_connectivity_monitor.h" #include "net/quic/quic_context.h" #include "net/quic/quic_crypto_client_config_handle.h" +#include "net/quic/quic_endpoint.h" #include "net/quic/quic_proxy_datagram_client_socket.h" #include "net/quic/quic_session_alias_key.h" #include "net/quic/quic_session_attempt.h" @@ -69,10 +70,6 @@ #include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h" #include "url/scheme_host_port.h" -namespace base { -class Value; -} // namespace base - namespace quic { class QuicAlarmFactory; class QuicClock; @@ -96,6 +93,7 @@ class QuicChromiumConnectionHelper; class QuicCryptoClientStreamFactory; class QuicServerInfo; class QuicSessionPool; +class QuicSessionAttemptManager; class QuicContext; class SCTAuditingDelegate; class SocketPerformanceWatcherFactory; @@ -300,21 +298,6 @@ class NET_EXPORT_PRIVATE QuicSessionRequest { CompletionOnceCallback create_session_callback_; }; -// Represents a single QUIC endpoint and the information necessary to attempt -// a QUIC session. -struct NET_EXPORT_PRIVATE QuicEndpoint { - QuicEndpoint(quic::ParsedQuicVersion quic_version, - IPEndPoint ip_endpoint, - ConnectionEndpointMetadata metadata); - ~QuicEndpoint(); - - quic::ParsedQuicVersion quic_version = quic::ParsedQuicVersion::Unsupported(); - IPEndPoint ip_endpoint; - ConnectionEndpointMetadata metadata; - - base::Value::Dict ToValue() const; -}; - // Manages a pool of QuicChromiumClientSessions. class NET_EXPORT_PRIVATE QuicSessionPool : public NetworkChangeNotifier::IPAddressObserver, @@ -554,6 +537,10 @@ class NET_EXPORT_PRIVATE QuicSessionPool return host_resolver_->IsHappyEyeballsV3Enabled(); } + QuicSessionAttemptManager* session_attempt_manager() { + return session_attempt_manager_.get(); + } + struct QuicCryptoClientConfigKey; private: @@ -563,6 +550,7 @@ class NET_EXPORT_PRIVATE QuicSessionPool class QuicCryptoClientConfigOwner; class CryptoClientConfigHandle; friend class QuicSessionAttempt; + friend class QuicSessionAttemptManager; friend class MockQuicSessionPool; friend class test::QuicSessionPoolPeer; @@ -933,6 +921,8 @@ class NET_EXPORT_PRIVATE QuicSessionPool quic::DeterministicConnectionIdGenerator connection_id_generator_{ quic::kQuicDefaultConnectionIdLength}; + std::unique_ptr session_attempt_manager_; + std::optional time_delay_for_waiting_job_for_testing_; base::WeakPtrFactory weak_factory_{this}; @@ -986,15 +976,13 @@ class QuicSessionPool::QuicCryptoClientConfigOwner { const raw_ptr quic_session_pool_; }; -// Key for QuicCryptoClienConfigOwners within a session pool.k +// Key for QuicCryptoClienConfigOwners within a session pool. struct NET_EXPORT_PRIVATE QuicSessionPool::QuicCryptoClientConfigKey { QuicCryptoClientConfigKey() = default; explicit QuicCryptoClientConfigKey(const QuicSessionKey& session_key) : network_anonymization_key(session_key.network_anonymization_key()), proxy_chain(session_key.proxy_chain()), session_usage(session_key.session_usage()) {} - explicit QuicCryptoClientConfigKey(const NetworkAnonymizationKey& nak) - : network_anonymization_key(nak) {} bool operator==(const QuicCryptoClientConfigKey& other) const; bool operator<(const QuicCryptoClientConfigKey& other) const; 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 5351b016c8..47bcf04b21 100644 --- a/naiveproxy/src/net/quic/quic_session_pool_direct_job.cc +++ b/naiveproxy/src/net/quic/quic_session_pool_direct_job.cc @@ -5,12 +5,12 @@ #include "net/quic/quic_session_pool_direct_job.h" #include "base/memory/weak_ptr.h" +#include "base/trace_event/trace_event.h" #include "net/base/completion_once_callback.h" #include "net/base/network_change_notifier.h" #include "net/base/network_handle.h" #include "net/base/request_priority.h" #include "net/base/trace_constants.h" -#include "net/base/tracing.h" #include "net/dns/host_resolver.h" #include "net/dns/public/host_resolver_results.h" #include "net/log/net_log_with_source.h" @@ -158,17 +158,17 @@ int QuicSessionPool::DirectJob::DoResolveHostComplete(int rv) { // Inform the pool of this resolution, which will set up // a session alias, if possible. const bool svcb_optional = - IsSvcbOptional(*resolve_host_request_->GetEndpointResults()); - for (const auto& endpoint : *resolve_host_request_->GetEndpointResults()) { + IsSvcbOptional(resolve_host_request_->GetEndpointResults()); + for (const auto& endpoint : resolve_host_request_->GetEndpointResults()) { // Only consider endpoints that would have been eligible for QUIC. quic::ParsedQuicVersion endpoint_quic_version = pool_->SelectQuicVersion( quic_version_, endpoint.metadata, svcb_optional); if (!endpoint_quic_version.IsKnown()) { continue; } - if (pool_->HasMatchingIpSession( - key_, endpoint.ip_endpoints, - *resolve_host_request_->GetDnsAliasResults(), use_dns_aliases_)) { + if (pool_->HasMatchingIpSession(key_, endpoint.ip_endpoints, + resolve_host_request_->GetDnsAliasResults(), + use_dns_aliases_)) { LogConnectionIpPooling(true); return OK; } @@ -181,12 +181,12 @@ int QuicSessionPool::DirectJob::DoAttemptSession() { // TODO(crbug.com/40256842): This logic only knows how to try one // endpoint result. bool svcb_optional = - IsSvcbOptional(*resolve_host_request_->GetEndpointResults()); + IsSvcbOptional(resolve_host_request_->GetEndpointResults()); bool found = false; HostResolverEndpointResult endpoint_result; quic::ParsedQuicVersion quic_version_used = quic::ParsedQuicVersion::Unsupported(); - for (const auto& candidate : *resolve_host_request_->GetEndpointResults()) { + for (const auto& candidate : resolve_host_request_->GetEndpointResults()) { quic::ParsedQuicVersion endpoint_quic_version = pool_->SelectQuicVersion( quic_version_, candidate.metadata, svcb_optional); if (endpoint_quic_version.IsKnown()) { @@ -201,9 +201,8 @@ int QuicSessionPool::DirectJob::DoAttemptSession() { } std::set dns_aliases = - use_dns_aliases_ && resolve_host_request_->GetDnsAliasResults() - ? *resolve_host_request_->GetDnsAliasResults() - : std::set(); + use_dns_aliases_ ? resolve_host_request_->GetDnsAliasResults() + : std::set(); // Passing an empty `crypto_client_config_handle` is safe because this job // already owns a handle. session_attempt_ = std::make_unique( @@ -243,13 +242,13 @@ void QuicSessionPool::DirectJob::OnSessionAttemptComplete(int rv) { bool QuicSessionPool::DirectJob::IsSvcbOptional( base::span results) const { // If SVCB/HTTPS resolution succeeded, the client supports ECH, and all - // routes support ECH, disable the A/AAAA fallback. See Section 10.1 of - // draft-ietf-dnsop-svcb-https-11. + // alternative endpoints support ECH, disable the A/AAAA fallback. See + // Section 5.1 of draft-ietf-tls-svcb-ech-08. if (!pool_->ssl_config_service_->GetSSLContextConfig().ech_enabled) { return true; // ECH is not supported for this request. } - return !HostResolver::AllProtocolEndpointsHaveEch(results); + return !HostResolver::AllAlternativeEndpointsHaveEch(results); } } // namespace net diff --git a/naiveproxy/src/net/quic/quic_session_pool_job.cc b/naiveproxy/src/net/quic/quic_session_pool_job.cc index 124de34d0b..ea69aa88b2 100644 --- a/naiveproxy/src/net/quic/quic_session_pool_job.cc +++ b/naiveproxy/src/net/quic/quic_session_pool_job.cc @@ -4,14 +4,15 @@ #include "net/quic/quic_session_pool_job.h" +#include "base/debug/dump_without_crashing.h" #include "base/memory/weak_ptr.h" +#include "base/trace_event/trace_event.h" #include "net/base/completion_once_callback.h" #include "net/base/network_change_notifier.h" #include "net/base/network_handle.h" #include "net/base/proxy_chain.h" #include "net/base/request_priority.h" #include "net/base/trace_constants.h" -#include "net/base/tracing.h" #include "net/dns/host_resolver.h" #include "net/log/net_log_with_source.h" #include "net/quic/address_utils.h" @@ -60,6 +61,13 @@ QuicSessionPool::Job::~Job() { } void QuicSessionPool::Job::AddRequest(QuicSessionRequest* request) { + // We suspect that requests are being added to jobs that are being deleted + // which would leave the requests orphaned. + // TODO(crbug.com/404586727): Remove once we confirm the crash no longer + // happens. + if (is_deleting_) { + base::debug::DumpWithoutCrashing(); + } request->AddedToJob(); requests_.insert(request); SetRequestExpectations(request); diff --git a/naiveproxy/src/net/quic/quic_session_pool_job.h b/naiveproxy/src/net/quic/quic_session_pool_job.h index c7d7132f20..65154b9b83 100644 --- a/naiveproxy/src/net/quic/quic_session_pool_job.h +++ b/naiveproxy/src/net/quic/quic_session_pool_job.h @@ -71,6 +71,10 @@ class QuicSessionPool::Job : public QuicSessionAttempt::Delegate { void AssociateWithNetLogSource( const NetLogWithSource& http_stream_job_net_log) const; + // TODO(crbug.com/404586727): Remove once we confirm the crash no longer + // happens. + void set_is_deleting() { is_deleting_ = true; } + // QuicSessionAttempt::Delegate implementation. QuicSessionPool* GetQuicSessionPool() override; const QuicSessionAliasKey& GetKey() override; @@ -93,6 +97,9 @@ class QuicSessionPool::Job : public QuicSessionAttempt::Delegate { RequestPriority priority_; const NetLogWithSource net_log_; std::set> requests_; + + private: + bool is_deleting_ = false; }; } // namespace net diff --git a/naiveproxy/src/net/quic/quic_session_pool_proxy_job.cc b/naiveproxy/src/net/quic/quic_session_pool_proxy_job.cc index 0452d1f1fb..1ba7016c35 100644 --- a/naiveproxy/src/net/quic/quic_session_pool_proxy_job.cc +++ b/naiveproxy/src/net/quic/quic_session_pool_proxy_job.cc @@ -5,12 +5,12 @@ #include "net/quic/quic_session_pool_proxy_job.h" #include "base/memory/weak_ptr.h" +#include "base/trace_event/trace_event.h" #include "net/base/completion_once_callback.h" #include "net/base/network_change_notifier.h" #include "net/base/network_handle.h" #include "net/base/request_priority.h" #include "net/base/trace_constants.h" -#include "net/base/tracing.h" #include "net/log/net_log_with_source.h" #include "net/quic/address_utils.h" #include "net/quic/quic_context.h" 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 e28caaebaa..73e98cc23a 100644 --- a/naiveproxy/src/net/quic/quic_session_pool_test_base.cc +++ b/naiveproxy/src/net/quic/quic_session_pool_test_base.cc @@ -129,7 +129,7 @@ QuicSessionPoolTestBase::RequestBuilder::RequestBuilder( request(pool) {} QuicSessionPoolTestBase::RequestBuilder::RequestBuilder( QuicSessionPoolTestBase* test) - : RequestBuilder(test, test->factory_.get()) {} + : RequestBuilder(test, test->pool_.get()) {} QuicSessionPoolTestBase::RequestBuilder::~RequestBuilder() = default; int QuicSessionPoolTestBase::RequestBuilder::CallRequest() { @@ -189,8 +189,8 @@ QuicSessionPoolTestBase::QuicSessionPoolTestBase( QuicSessionPoolTestBase::~QuicSessionPoolTestBase() = default; void QuicSessionPoolTestBase::Initialize() { - DCHECK(!factory_); - factory_ = std::make_unique( + DCHECK(!pool_); + pool_ = std::make_unique( net_log_.net_log(), host_resolver_.get(), &ssl_config_service_, socket_factory_.get(), http_server_properties_.get(), cert_verifier_.get(), &transport_security_state_, proxy_delegate_.get(), @@ -236,7 +236,7 @@ bool QuicSessionPoolTestBase::HasActiveSession( quic::QuicServerId server_id(scheme_host_port.host(), scheme_host_port.port()); return QuicSessionPoolPeer::HasActiveSession( - factory_.get(), server_id, privacy_mode, network_anonymization_key, + pool_.get(), server_id, privacy_mode, network_anonymization_key, proxy_chain, session_usage, require_dns_https_alpn); } @@ -246,8 +246,8 @@ bool QuicSessionPoolTestBase::HasActiveJob( bool require_dns_https_alpn) { quic::QuicServerId server_id(scheme_host_port.host(), scheme_host_port.port()); - return QuicSessionPoolPeer::HasActiveJob( - factory_.get(), server_id, privacy_mode, require_dns_https_alpn); + return QuicSessionPoolPeer::HasActiveJob(pool_.get(), server_id, privacy_mode, + require_dns_https_alpn); } // Get the pending, not activated session, if there is only one session alive. @@ -256,7 +256,7 @@ QuicChromiumClientSession* QuicSessionPoolTestBase::GetPendingSession( quic::QuicServerId server_id(scheme_host_port.host(), scheme_host_port.port()); return QuicSessionPoolPeer::GetPendingSession( - factory_.get(), server_id, PRIVACY_MODE_DISABLED, scheme_host_port); + pool_.get(), server_id, PRIVACY_MODE_DISABLED, scheme_host_port); } QuicChromiumClientSession* QuicSessionPoolTestBase::GetActiveSession( @@ -269,7 +269,7 @@ QuicChromiumClientSession* QuicSessionPoolTestBase::GetActiveSession( quic::QuicServerId server_id(scheme_host_port.host(), scheme_host_port.port()); return QuicSessionPoolPeer::GetActiveSession( - factory_.get(), server_id, privacy_mode, network_anonymization_key, + pool_.get(), server_id, privacy_mode, network_anonymization_key, proxy_chain, session_usage, require_dns_https_alpn); } @@ -313,7 +313,7 @@ int QuicSessionPoolTestBase::GetSourcePortForNewSessionInner( session->connection()->OnGoAwayFrame(goaway); } - factory_->OnSessionClosed(session); + pool_->OnSessionClosed(session); EXPECT_FALSE(HasActiveSession(destination)); socket_data.ExpectAllReadDataConsumed(); socket_data.ExpectAllWriteDataConsumed(); @@ -482,10 +482,10 @@ QuicSessionPoolTestBase::ConstructAckPacket( test::QuicTestPacketMaker& packet_maker, uint64_t packet_number, uint64_t packet_num_received, - uint64_t smallest_received, - uint64_t largest_received) { + uint64_t largest_received, + uint64_t smallest_received) { return packet_maker.Packet(packet_number) - .AddAckFrame(packet_num_received, smallest_received, largest_received) + .AddAckFrame(packet_num_received, largest_received, smallest_received) .Build(); } diff --git a/naiveproxy/src/net/quic/quic_session_pool_test_base.h b/naiveproxy/src/net/quic/quic_session_pool_test_base.h index 81f0a5d13e..4bb047fa37 100644 --- a/naiveproxy/src/net/quic/quic_session_pool_test_base.h +++ b/naiveproxy/src/net/quic/quic_session_pool_test_base.h @@ -244,8 +244,8 @@ class QuicSessionPoolTestBase : public WithTaskEnvironment { test::QuicTestPacketMaker& packet_maker, uint64_t packet_number, uint64_t packet_num_received, - uint64_t smallest_received, - uint64_t largest_received); + uint64_t largest_received, + uint64_t smallest_received); std::string ConstructDataHeader(size_t body_len); std::unique_ptr ConstructServerDataPacket( @@ -288,7 +288,7 @@ class QuicSessionPoolTestBase : public WithTaskEnvironment { std::unique_ptr proxy_delegate_; std::unique_ptr scoped_mock_network_change_notifier_; - std::unique_ptr factory_; + std::unique_ptr pool_; NetLogWithSource net_log_; TestCompletionCallback callback_; diff --git a/naiveproxy/src/net/quic/quic_socket_data_provider.cc b/naiveproxy/src/net/quic/quic_socket_data_provider.cc index 8299cad885..622e98c65e 100644 --- a/naiveproxy/src/net/quic/quic_socket_data_provider.cc +++ b/naiveproxy/src/net/quic/quic_socket_data_provider.cc @@ -109,7 +109,7 @@ class HttpStreamPrinter : public Http3DebugVisitor { } void OnHeadersDecoded(QuicStreamId stream_id, - QuicHeaderList headers) override { + const QuicHeaderList& headers) override { if (output_) { *output_ << "OnHeadersDecoded: " << stream_id << ", " << "received: " << headers.DebugString() << "\n"; diff --git a/naiveproxy/src/net/quic/quic_test_packet_maker.cc b/naiveproxy/src/net/quic/quic_test_packet_maker.cc index daedc261fb..3336b9c889 100644 --- a/naiveproxy/src/net/quic/quic_test_packet_maker.cc +++ b/naiveproxy/src/net/quic/quic_test_packet_maker.cc @@ -2,16 +2,12 @@ // 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 "net/quic/quic_test_packet_maker.h" #include #include +#include "base/compiler_specific.h" #include "base/functional/callback.h" #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" @@ -131,7 +127,7 @@ void QuicTestPacketMaker::ConnectionState::Reset() { QuicTestPacketMaker::QuicTestPacketMaker(quic::ParsedQuicVersion version, quic::QuicConnectionId connection_id, const quic::QuicClock* clock, - const std::string& host, + std::string_view host, quic::Perspective perspective, bool client_priority_uses_incremental, bool use_priority_header) @@ -402,7 +398,7 @@ void QuicTestPacketMaker::RemoveSavedStreamFrames( it->stream_frame.stream_id == stream_id) { it = kv.second.erase(it); } else { - ++it; + UNSAFE_TODO(++it); } } } diff --git a/naiveproxy/src/net/quic/quic_test_packet_maker.h b/naiveproxy/src/net/quic/quic_test_packet_maker.h index c0a95162a8..a7f60087c1 100644 --- a/naiveproxy/src/net/quic/quic_test_packet_maker.h +++ b/naiveproxy/src/net/quic/quic_test_packet_maker.h @@ -68,7 +68,7 @@ class QuicTestPacketMaker { QuicTestPacketMaker(quic::ParsedQuicVersion version, quic::QuicConnectionId connection_id, const quic::QuicClock* clock, - const std::string& host, + std::string_view host, quic::Perspective perspective, bool client_priority_uses_incremental = false, bool use_priority_header = false); diff --git a/naiveproxy/src/net/reporting/reporting_cache_impl.h b/naiveproxy/src/net/reporting/reporting_cache_impl.h index 879ce91e3b..ba81d1b903 100644 --- a/naiveproxy/src/net/reporting/reporting_cache_impl.h +++ b/naiveproxy/src/net/reporting/reporting_cache_impl.h @@ -10,7 +10,6 @@ #include #include #include -#include #include #include diff --git a/naiveproxy/src/net/server/web_socket_encoder.cc b/naiveproxy/src/net/server/web_socket_encoder.cc index f10527acca..569dc3587c 100644 --- a/naiveproxy/src/net/server/web_socket_encoder.cc +++ b/naiveproxy/src/net/server/web_socket_encoder.cc @@ -2,22 +2,20 @@ // 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 "net/server/web_socket_encoder.h" +#include #include #include #include #include "base/check.h" +#include "base/containers/extend.h" #include "base/containers/span.h" #include "base/memory/ptr_util.h" #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_view_util.h" #include "net/base/io_buffer.h" #include "net/base/net_export.h" #include "net/websockets/websocket_deflate_parameters.h" @@ -37,13 +35,13 @@ const int kInflaterChunkSize = 16 * 1024; // Constants for hybi-10 frame format. -const unsigned char kFinalBit = 0x80; -const unsigned char kReserved1Bit = 0x40; -const unsigned char kReserved2Bit = 0x20; -const unsigned char kReserved3Bit = 0x10; -const unsigned char kOpCodeMask = 0xF; -const unsigned char kMaskBit = 0x80; -const unsigned char kPayloadLengthMask = 0x7F; +const uint8_t kFinalBit = 0x80; +const uint8_t kReserved1Bit = 0x40; +const uint8_t kReserved2Bit = 0x20; +const uint8_t kReserved3Bit = 0x10; +const uint8_t kOpCodeMask = 0xF; +const uint8_t kMaskBit = 0x80; +const uint8_t kPayloadLengthMask = 0x7F; const size_t kMaxSingleBytePayloadLength = 125; const size_t kTwoBytePayloadLengthField = 126; @@ -55,16 +53,13 @@ WebSocketParseResult DecodeFrameHybi17(std::string_view frame, int* bytes_consumed, std::string* output, bool* compressed) { - size_t data_length = frame.length(); - if (data_length < 2) + if (frame.size() < 2) { return WebSocketParseResult::FRAME_INCOMPLETE; + } - const char* buffer_begin = const_cast(frame.data()); - const char* p = buffer_begin; - const char* buffer_end = p + data_length; - - unsigned char first_byte = *p++; - unsigned char second_byte = *p++; + uint8_t first_byte = frame[0]; + uint8_t second_byte = frame[1]; + std::string_view remaining = frame.substr(2); bool final = (first_byte & kFinalBit) != 0; bool reserved1 = (first_byte & kReserved1Bit) != 0; @@ -101,20 +96,22 @@ WebSocketParseResult DecodeFrameHybi17(std::string_view frame, uint64_t payload_length64 = second_byte & kPayloadLengthMask; if (payload_length64 > kMaxSingleBytePayloadLength) { - int extended_payload_length_size; + size_t extended_payload_length_size; if (payload_length64 == kTwoBytePayloadLengthField) { extended_payload_length_size = 2; } else { DCHECK(payload_length64 == kEightBytePayloadLengthField); extended_payload_length_size = 8; } - if (buffer_end - p < extended_payload_length_size) + if (remaining.size() < extended_payload_length_size) { return WebSocketParseResult::FRAME_INCOMPLETE; - payload_length64 = 0; - for (int i = 0; i < extended_payload_length_size; ++i) { - payload_length64 <<= 8; - payload_length64 |= static_cast(*p++); } + payload_length64 = 0; + for (size_t i = 0; i < extended_payload_length_size; ++i) { + payload_length64 <<= 8; + payload_length64 |= static_cast(remaining[i]); + } + remaining.remove_prefix(extended_payload_length_size); } size_t actual_masking_key_length = masked ? kMaskingKeyWidthInBytes : 0; @@ -128,21 +125,25 @@ WebSocketParseResult DecodeFrameHybi17(std::string_view frame, size_t payload_length = static_cast(payload_length64); size_t total_length = actual_masking_key_length + payload_length; - if (static_cast(buffer_end - p) < total_length) + if (remaining.size() < total_length) { return WebSocketParseResult::FRAME_INCOMPLETE; + } if (masked) { output->resize(payload_length); - const char* masking_key = p; - char* payload = const_cast(p + kMaskingKeyWidthInBytes); - for (size_t i = 0; i < payload_length; ++i) // Unmask the payload. - (*output)[i] = payload[i] ^ masking_key[i % kMaskingKeyWidthInBytes]; + std::string_view masking_key = remaining.substr(0, kMaskingKeyWidthInBytes); + std::string_view payload_data = + remaining.substr(kMaskingKeyWidthInBytes, payload_length); + for (size_t i = 0; i < payload_length; ++i) { // Unmask the payload. + (*output)[i] = payload_data[i] ^ masking_key[i % kMaskingKeyWidthInBytes]; + } + remaining.remove_prefix(total_length); } else { - output->assign(p, p + payload_length); + output->assign(remaining.data(), payload_length); + remaining.remove_prefix(payload_length); } - size_t pos = p + actual_masking_key_length + payload_length - buffer_begin; - *bytes_consumed = pos; + *bytes_consumed = frame.size() - remaining.size(); if (op_code == WebSocketFrameHeader::OpCodeEnum::kOpCodePing) return WebSocketParseResult::FRAME_PING; @@ -176,26 +177,26 @@ void EncodeFrameHybi17(std::string_view message, frame.push_back(data_length & 0xFF); } else { frame.push_back(kEightBytePayloadLengthField | mask_key_bit); - char extended_payload_length[8]; + std::array extended_payload_length; size_t remaining = data_length; // Fill the length into extended_payload_length in the network byte order. for (int i = 0; i < 8; ++i) { extended_payload_length[7 - i] = remaining & 0xFF; remaining >>= 8; } - frame.insert(frame.end(), extended_payload_length, - extended_payload_length + 8); + base::Extend(frame, extended_payload_length); DCHECK(!remaining); } - const char* data = const_cast(message.data()); if (masking_key != 0) { - const char* mask_bytes = reinterpret_cast(&masking_key); - frame.insert(frame.end(), mask_bytes, mask_bytes + 4); - for (size_t i = 0; i < data_length; ++i) // Mask the payload. - frame.push_back(data[i] ^ mask_bytes[i % kMaskingKeyWidthInBytes]); + std::string_view mask_bytes(reinterpret_cast(&masking_key), + kMaskingKeyWidthInBytes); + base::Extend(frame, mask_bytes); + for (size_t i = 0; i < data_length; ++i) { // Mask the payload. + frame.push_back(message[i] ^ mask_bytes[i % kMaskingKeyWidthInBytes]); + } } else { - frame.insert(frame.end(), data, data + data_length); + base::Extend(frame, message); } *output = std::string(frame.data(), frame.size()); } @@ -382,7 +383,7 @@ bool WebSocketEncoder::Inflate(std::string* message) { inflater_->GetOutput(inflater_->CurrentOutputSize()); if (!chunk.get()) return false; - output.insert(output.end(), chunk->data(), chunk->data() + chunk->size()); + base::Extend(output, chunk->span()); } *message = @@ -403,7 +404,7 @@ bool WebSocketEncoder::Deflate(std::string_view message, std::string* output) { deflater_->GetOutput(deflater_->CurrentOutputSize()); if (!buffer.get()) return false; - *output = std::string(buffer->data(), buffer->size()); + *output = std::string(base::as_string_view(buffer->span())); return true; } diff --git a/naiveproxy/src/net/socket/client_socket_factory.cc b/naiveproxy/src/net/socket/client_socket_factory.cc index 89a154fd68..c53d98d5bb 100644 --- a/naiveproxy/src/net/socket/client_socket_factory.cc +++ b/naiveproxy/src/net/socket/client_socket_factory.cc @@ -6,7 +6,7 @@ #include -#include "base/lazy_instance.h" +#include "base/no_destructor.h" #include "build/build_config.h" #include "net/socket/ssl_client_socket.h" #include "net/socket/tcp_client_socket.h" @@ -53,14 +53,12 @@ class DefaultClientSocketFactory : public ClientSocketFactory { } }; -static base::LazyInstance::Leaky - g_default_client_socket_factory = LAZY_INSTANCE_INITIALIZER; - } // namespace // static ClientSocketFactory* ClientSocketFactory::GetDefaultFactory() { - return g_default_client_socket_factory.Pointer(); + static base::NoDestructor factory; + return factory.get(); } } // namespace net diff --git a/naiveproxy/src/net/socket/client_socket_handle.cc b/naiveproxy/src/net/socket/client_socket_handle.cc index a80e6e2691..02990111b8 100644 --- a/naiveproxy/src/net/socket/client_socket_handle.cc +++ b/naiveproxy/src/net/socket/client_socket_handle.cc @@ -11,9 +11,9 @@ #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/notreached.h" +#include "base/trace_event/trace_event.h" #include "net/base/net_errors.h" #include "net/base/trace_constants.h" -#include "net/base/tracing.h" #include "net/log/net_log_event_type.h" #include "net/socket/client_socket_pool.h" #include "net/socket/connect_job.h" diff --git a/naiveproxy/src/net/socket/connect_job.cc b/naiveproxy/src/net/socket/connect_job.cc index f63160e8f2..d3593ef5d1 100644 --- a/naiveproxy/src/net/socket/connect_job.cc +++ b/naiveproxy/src/net/socket/connect_job.cc @@ -7,10 +7,10 @@ #include #include +#include "base/trace_event/trace_event.h" #include "net/base/connection_endpoint_metadata.h" #include "net/base/net_errors.h" #include "net/base/trace_constants.h" -#include "net/base/tracing.h" #include "net/dns/public/host_resolver_results.h" #include "net/dns/public/secure_dns_policy.h" #include "net/http/http_auth_controller.h" @@ -104,7 +104,7 @@ ConnectJob::~ConnectJob() { // Log end of Connect event if ConnectJob was still in-progress when // destroyed. if (delegate_) { - LogConnectCompletion(ERR_ABORTED); + StopTimerAndLogConnectCompletion(ERR_ABORTED); } if (top_level_job_) { net_log().EndEvent(NetLogEventType::CONNECT_JOB); @@ -130,7 +130,7 @@ int ConnectJob::Connect() { int rv = ConnectInternal(); if (rv != ERR_IO_PENDING) { - LogConnectCompletion(rv); + StopTimerAndLogConnectCompletion(rv); delegate_ = nullptr; } @@ -177,7 +177,7 @@ void ConnectJob::NotifyDelegateOfCompletion(int rv) { Delegate* delegate = delegate_; delegate_ = nullptr; - LogConnectCompletion(rv); + StopTimerAndLogConnectCompletion(rv); delegate->OnConnectJobComplete(rv, this); } @@ -210,7 +210,11 @@ void ConnectJob::LogConnectStart() { net_log().BeginEvent(net_log_connect_event_type_); } -void ConnectJob::LogConnectCompletion(int net_error) { +void ConnectJob::StopTimerAndLogConnectCompletion(int net_error) { + // Stop the timer on completion, if it's still running. ConnectJobs are + // generally deleted immediately, anyways, but best to be safe. + timer_.Stop(); + connect_timing_.connect_end = base::TimeTicks::Now(); net_log().EndEventWithNetErrorCode(net_log_connect_event_type_, net_error); } diff --git a/naiveproxy/src/net/socket/connect_job.h b/naiveproxy/src/net/socket/connect_job.h index 22441463ff..4fde5e963a 100644 --- a/naiveproxy/src/net/socket/connect_job.h +++ b/naiveproxy/src/net/socket/connect_job.h @@ -229,10 +229,6 @@ class NET_EXPORT_PRIVATE ConnectJob { // |delegate_| via OnConnectJobComplete. In both asynchronous and synchronous // completion, ReleaseSocket() can be called to acquire the connected socket // if it succeeded. - // - // On completion, the ConnectJob must be destroyed synchronously, since it - // doesn't bother to stop its timer when complete. - // TODO(mmenke): Can that be fixed? int Connect(); // Returns the current LoadState of the ConnectJob. Each ConnectJob class must @@ -342,7 +338,7 @@ class NET_EXPORT_PRIVATE ConnectJob { virtual void ChangePriorityInternal(RequestPriority priority) = 0; void LogConnectStart(); - void LogConnectCompletion(int net_error); + void StopTimerAndLogConnectCompletion(int net_error); // Alerts the delegate that the ConnectJob has timed out. void OnTimeout(); diff --git a/naiveproxy/src/net/socket/socket_posix.cc b/naiveproxy/src/net/socket/socket_posix.cc index e749ea96d6..f5bfb7a52a 100644 --- a/naiveproxy/src/net/socket/socket_posix.cc +++ b/naiveproxy/src/net/socket/socket_posix.cc @@ -19,24 +19,123 @@ #include "base/logging.h" #include "base/posix/eintr_wrapper.h" #include "base/task/current_thread.h" +#include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "net/base/io_buffer.h" #include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "net/base/sockaddr_storage.h" #include "net/base/trace_constants.h" -#include "net/base/tracing.h" #include "net/traffic_annotation/network_traffic_annotation.h" +// TODO(crbug.com/40064248): Remove this once sufficient information is +// collected. +#include "base/debug/crash_logging.h" + #if BUILDFLAG(IS_FUCHSIA) #include #include #endif // BUILDFLAG(IS_FUCHSIA) +#if defined(DEBUG_CRBUG_40064248_STATISTICS) + +// TODO(crbug.com/40064248): Remove this once the crash is resolved. + +#if BUILDFLAG(IS_APPLE) +#include +#include +#include +#include +#endif // BUILDFLAG(IS_APPLE) + +#include "base/no_destructor.h" +#include "base/strings/stringprintf.h" +#include "base/synchronization/lock.h" + +#endif // DEBUG_CRBUG_40064248_STATISTICS + namespace net { namespace { +#if defined(DEBUG_CRBUG_40064248_STATISTICS) + +// TODO(crbug.com/40064248): Remove this once the crash is resolved. + +#if BUILDFLAG(IS_APPLE) + +timespec TimespecSubtract(const timespec& minuend, const timespec& subtrahend) { + constexpr int kNanosecondsPerSecond = 1e9; + + timespec difference{ + .tv_sec = minuend.tv_sec - subtrahend.tv_sec, + .tv_nsec = minuend.tv_nsec - subtrahend.tv_nsec, + }; + if (difference.tv_nsec < 0) { + --difference.tv_sec; + difference.tv_nsec += kNanosecondsPerSecond; + } + return difference; +} + +// Returns the start time of the process, on the CLOCK_MONOTONIC_RAW time base. +timespec ProcessStartTimeMonotonic() { + timespec now_real; + if (clock_gettime(CLOCK_REALTIME, &now_real) != 0) { + return {.tv_sec = -1, .tv_nsec = -1 - errno}; + } + + timespec now_monotonic; + if (clock_gettime(CLOCK_MONOTONIC_RAW, &now_monotonic) != 0) { + return {.tv_sec = -2, .tv_nsec = -1 - errno}; + } + + timespec monotonic_real_offset(TimespecSubtract(now_real, now_monotonic)); + if (monotonic_real_offset.tv_sec < 0) { + return {.tv_sec = -3, .tv_nsec = -1}; + } + + kinfo_proc kern_proc_info; + int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()}; + size_t len = sizeof(kern_proc_info); + if (sysctl(mib, std::size(mib), &kern_proc_info, &len, nullptr, 0) != 0) { + return {.tv_sec = -4, .tv_nsec = -1 - errno}; + } + + timespec start_real; + TIMEVAL_TO_TIMESPEC(&kern_proc_info.kp_proc.p_starttime, &start_real); + + return TimespecSubtract(start_real, monotonic_real_offset); +} + +#endif // BUILDFLAG(IS_APPLE) + +// Returns a string representation of `time`, taken relative to `start_time`. +// The times must be on the same timebase, such as CLOCK_MONOTONIC_RAW. +std::string ProcessTimeString(const timespec& time, + const timespec& start_time) { + if (time.tv_sec == -1 && time.tv_nsec < 0) { + return base::StringPrintf("(time_errno=%d)", -1 - time.tv_nsec); + } + + std::string s; + timespec print_time; + if (start_time.tv_sec <= -1 && start_time.tv_sec >= -4 && + start_time.tv_nsec < 0) { + s.assign(base::StringPrintf("(start_time_errno=%d,%d)", -start_time.tv_sec, + -1 - start_time.tv_nsec)); + print_time = time; + } else { + print_time = TimespecSubtract(time, start_time); + } + + base::StringAppendF(&s, "%d.%09d", print_time.tv_sec, print_time.tv_nsec); + + return s; +} + +#endif // DEBUG_CRBUG_40064248_STATISTICS + int MapAcceptError(int os_error) { switch (os_error) { // If the client aborts the connection before the server calls accept, @@ -527,17 +626,67 @@ int SocketPosix::DoWrite(IOBuffer* buf, int buf_len) { buf_len, flags); base::debug::Alias(debug3); - int rv = HANDLE_EINTR(send(socket_fd_, buf->data(), buf_len, flags)); + ssize_t send_rv = HANDLE_EINTR(send(socket_fd_, buf->data(), buf_len, flags)); + int send_errno = errno; +#if defined(DEBUG_CRBUG_40064248_STATISTICS) // TODO(crbug.com/40064248): Remove this once the crash is resolved. - char debug4[64]; - snprintf(debug4, sizeof(debug4), "rv=%d,errno=%d", rv, rv < 0 ? errno : 0); - base::debug::Alias(debug4); - if (rv >= 0) { - CHECK_LE(rv, buf_len); + // Do this once, as close to process start as is reasonably practical, + // because the OS records the start time on the CLOCK_REALTIME timebase, + // which can only drift (or even move backwards) relative to the + // CLOCK_MONOTONIC_RAW timebase as time elapses. + static timespec start_time(ProcessStartTimeMonotonic()); + + timespec now; + if (clock_gettime(CLOCK_MONOTONIC_RAW, &now) != 0) { + now.tv_sec = -1; + now.tv_nsec = -errno; } - return rv >= 0 ? rv : MapSystemError(errno); + + static Statistics g_statistics; + + // A single SocketPosix shouldn’t have DoWrite called on more than one thread, + // checked by its thread_checker_. Thus, access to its own statistics_ need + // not be thread-safe. It’s less certain that access to the global + // g_statistics can afford to not be thread-safe, because it’s conceivable + // (although unlikely) that different SocketPosix objects operate on different + // threads. Use a mutex to protect g_statistics and, incidentally, all + // SocketPosix::statistics_ objects. The mutex is not likely to be contended, + // and in any case, the critical section executes quickly. + static base::NoDestructor statistics_lock; + base::ReleasableAutoLock statistics_auto_lock(statistics_lock.get()); + + statistics_.Update(socket_fd_, send_rv, send_errno, now); + g_statistics.Update(socket_fd_, send_rv, send_errno, now); +#endif // DEBUG_CRBUG_40064248_STATISTICS + + if (send_rv >= 0) { + if (send_rv > buf_len) { + // TODO(crbug.com/40064248): Remove this once the crash is resolved. + char debug4[64]; + snprintf(debug4, sizeof(debug4), "send_rv=%zd,send_errno=%d", send_rv, + send_rv < 0 ? send_errno : 0); + base::debug::Alias(debug4); + +#if defined(DEBUG_CRBUG_40064248_STATISTICS) + char debug5[4096]; + snprintf(debug5, sizeof(debug5), "statistics_={%s},g_statistics={%s}", + statistics_.DebugInfo(start_time).c_str(), + g_statistics.DebugInfo(start_time).c_str()); + base::debug::Alias(debug5); + statistics_auto_lock.Release(); +#endif // DEBUG_CRBUG_40064248_STATISTICS + + // This duplicates the CHECK_LE below. Keep it here so that the aliased + // debug buffers are in scope when the process crashes. + CHECK_LE(send_rv, buf_len); + } + + CHECK_LE(send_rv, buf_len); + } + + return send_rv >= 0 ? send_rv : MapSystemError(send_errno); } void SocketPosix::WriteCompleted() { @@ -593,4 +742,145 @@ void SocketPosix::StopWatchingAndCleanUp(bool close_socket) { peer_address_.reset(); } +#if defined(DEBUG_CRBUG_40064248_STATISTICS) + +// TODO(crbug.com/40064248): Remove this once the crash is resolved. + +SocketPosix::Statistics::Statistics() = default; + +void SocketPosix::Statistics::Update(const int socket_fd, + const ssize_t send_rv, + const int send_errno, + const timespec& now) { + if (send_rv < 0) { + if (sends_error_++ == 0) { + first_send_errno_ = send_errno; + first_send_error_time_ = now; + } + last_send_errno_ = send_errno; + last_send_error_time_ = now; + if (sends_error_consecutive_++ == 0) { + first_send_error_consecutive_time_ = now; + } + + sends_suspicious_consecutive_ = 0; + send_bytes_suspicious_consecutive_ = 0; + first_send_suspicious_consecutive_time_ = {}; + } else { + // Suspicious return values for `send` are those that are produced when the + // `sendto` system call returns from the kernel to user space without + // setting the return value register, leaving whatever contents had + // previously been there on the call into the kernel. The return value + // register is x0 on arm64 and rax on x86-64. When the `sendto` system call + // is made, user space places the first argument, the file descriptor + // number, in r0 (thus x0) on arm64, and the UNIX system call class (2) and + // `sendto` system call number (133) in eax (thus rax) on x86_64. + // + // A suspicious return isn’t necessarily a problem: it’s possible that only + // that many bytes were sent (or consumed from the buffer and queued to be + // sent). But it could also be an indication of https://crbug.com/40064248 + // occurring before it’s unambiguously detectable as a bug. + // + // Suspicious returns become unambiguously detectable when they exceed the + // size of the buffer passed to `send`. + // + // This classifies returns into suspicious and not-suspicious, so that the + // extent of the bug can be understood better. +#if BUILDFLAG(IS_APPLE) +#if defined(ARCH_CPU_ARM64) + const ssize_t suspicious_rv = socket_fd; +#elif defined(ARCH_CPU_X86_FAMILY) + // Definitions from xnu osfmk/mach/i386/syscall_sw.h, as used in its + // SYSCALL_CONSTRUCT_UNIX. + constexpr uint32_t SYSCALL_CLASS_SHIFT = 24; + constexpr uint32_t SYSCALL_CLASS_MASK = 0xff << SYSCALL_CLASS_SHIFT; + constexpr uint32_t SYSCALL_NUMBER_MASK = ~SYSCALL_CLASS_MASK; + constexpr uint32_t SYSCALL_CLASS_UNIX = 2; + + const ssize_t suspicious_rv = + ((SYSCALL_CLASS_UNIX << SYSCALL_CLASS_SHIFT) & SYSCALL_CLASS_MASK) | + (SYS_sendto & SYSCALL_NUMBER_MASK); // ((2 << 24) | 133) = 0x2000085 +#endif +#endif // BUILDFLAG(IS_APPLE) + const bool suspicious = send_rv == suspicious_rv; + + if (!suspicious) { + if (sends_ok_++ == 0) { + first_send_ok_time_ = now; + } + send_bytes_ok_ += send_rv; + last_send_ok_time_ = now; + + sends_suspicious_consecutive_ = 0; + send_bytes_suspicious_consecutive_ = 0; + first_send_suspicious_consecutive_time_ = {}; + } else { + if (sends_suspicious_++ == 0) { + first_send_suspicious_time_ = now; + } + send_bytes_suspicious_ += send_rv; + last_send_suspicious_time_ = now; + + if (sends_suspicious_consecutive_++ == 0) { + first_send_suspicious_consecutive_time_ = now; + } + send_bytes_suspicious_consecutive_ += send_rv; + } + + sends_error_consecutive_ = 0; + first_send_error_consecutive_time_ = {}; + } +} + +std::string SocketPosix::Statistics::DebugInfo( + const timespec& start_time) const { + std::string s(base::StringPrintf( + "sends_ok_=%u,sends_suspicious_=%u,sends_suspicious_consecutive_=%u," + "sends_error_=%u,sends_error_consecutive_=%u,send_bytes_ok_=%u," + "send_bytes_suspicious_=%u,send_bytes_suspicious_consecutive_=%u", + sends_ok_, sends_suspicious_, sends_suspicious_consecutive_, sends_error_, + sends_error_consecutive_, send_bytes_ok_, send_bytes_suspicious_, + send_bytes_suspicious_consecutive_)); + + if (sends_ok_) { + base::StringAppendF(&s, ",first_send_ok_time_=%s,last_send_ok_time_=%s", + ProcessTimeString(first_send_ok_time_, start_time), + ProcessTimeString(last_send_ok_time_, start_time)); + } + + if (sends_suspicious_) { + base::StringAppendF( + &s, ",first_send_suspicious_time_=%s,last_send_suspicious_time_=%s", + ProcessTimeString(first_send_suspicious_time_, start_time), + ProcessTimeString(last_send_suspicious_time_, start_time)); + + if (sends_suspicious_consecutive_) { + base::StringAppendF( + &s, ",first_send_suspicious_consecutive_time_=%s", + ProcessTimeString(first_send_suspicious_consecutive_time_, + start_time)); + } + } + + if (sends_error_) { + base::StringAppendF( + &s, + ",first_send_errno_=%d,last_send_errno_=%d,first_send_error_time_=%s," + "last_send_error_time_=%s", + first_send_errno_, last_send_errno_, + ProcessTimeString(first_send_error_time_, start_time), + ProcessTimeString(last_send_error_time_, start_time)); + + if (sends_error_consecutive_) { + base::StringAppendF( + &s, ",first_send_error_consecutive_time_=%s", + ProcessTimeString(first_send_error_consecutive_time_, start_time)); + } + } + + return s; +} + +#endif // DEBUG_CRBUG_40064248_STATISTICS + } // namespace net diff --git a/naiveproxy/src/net/socket/socket_posix.h b/naiveproxy/src/net/socket/socket_posix.h index f7155cab06..3c7c22cb3f 100644 --- a/naiveproxy/src/net/socket/socket_posix.h +++ b/naiveproxy/src/net/socket/socket_posix.h @@ -17,6 +17,15 @@ #include "net/socket/socket_descriptor.h" #include "net/traffic_annotation/network_traffic_annotation.h" +#if BUILDFLAG(IS_MAC) +#define DEBUG_CRBUG_40064248_STATISTICS 1 +#include +#include +#include + +#include +#endif // BUILDFLAG(IS_MAC) + namespace net { class IOBuffer; @@ -107,6 +116,51 @@ class NET_EXPORT_PRIVATE SocketPosix SocketDescriptor socket_fd() const { return socket_fd_; } private: +#if defined(DEBUG_CRBUG_40064248_STATISTICS) + // TODO(crbug.com/40064248): Remove this once the crash is resolved. + class Statistics { + public: + Statistics(); + + // Update statistics with the result of a send. + void Update(int socket_fd, + ssize_t send_rv, + int send_errno, + const timespec& now); + + // Return a string form of the collected statistics. Times are represented + // relative to start_time, if possible. + std::string DebugInfo(const timespec& start_time) const; + + private: + // *_errno_ and other *_error_* members track `send` reporting an error by + // returning -1. They don’t track the occurrence of + // https://crbug.com/40064248. *_suspicious_* tracks possible occurrences of + // that bug, and a CHECK failure records a definite occurrence. + int first_send_errno_ = 0; + int last_send_errno_ = 0; + + uint64_t sends_ok_ = 0; + uint64_t sends_suspicious_ = 0; + uint64_t sends_suspicious_consecutive_ = 0; + uint64_t sends_error_ = 0; + uint64_t sends_error_consecutive_ = 0; + uint64_t send_bytes_ok_ = 0; + uint64_t send_bytes_suspicious_ = 0; + uint64_t send_bytes_suspicious_consecutive_ = 0; + + // Times are recorded relative to CLOCK_MONOTONIC_RAW. + timespec first_send_ok_time_ = {}; + timespec last_send_ok_time_ = {}; + timespec first_send_suspicious_time_ = {}; + timespec last_send_suspicious_time_ = {}; + timespec first_send_suspicious_consecutive_time_ = {}; + timespec first_send_error_time_ = {}; + timespec last_send_error_time_ = {}; + timespec first_send_error_consecutive_time_ = {}; + }; +#endif // DEBUG_CRBUG_40064248_STATISTICS + // base::MessagePumpForIO::FdWatcher methods. void OnFileCanReadWithoutBlocking(int fd) override; void OnFileCanWriteWithoutBlocking(int fd) override; @@ -156,6 +210,10 @@ class NET_EXPORT_PRIVATE SocketPosix std::unique_ptr peer_address_; base::ThreadChecker thread_checker_; + +#if defined(DEBUG_CRBUG_40064248_STATISTICS) + Statistics statistics_; +#endif // DEBUG_CRBUG_40064248_STATISTICS }; } // namespace net diff --git a/naiveproxy/src/net/socket/socket_test_util.cc b/naiveproxy/src/net/socket/socket_test_util.cc index 0d3a8a3036..aa41c05a5c 100644 --- a/naiveproxy/src/net/socket/socket_test_util.cc +++ b/naiveproxy/src/net/socket/socket_test_util.cc @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -2268,30 +2269,38 @@ MockTaggingClientSocketFactory::CreateDatagramClientSocket( const char kSOCKS4TestHost[] = "127.0.0.1"; const int kSOCKS4TestPort = 80; -const char kSOCKS4OkRequestLocalHostPort80[] = {0x04, 0x01, 0x00, 0x50, 127, - 0, 0, 1, 0}; -const int kSOCKS4OkRequestLocalHostPort80Length = - std::size(kSOCKS4OkRequestLocalHostPort80); +constexpr auto kSOCKS4OkRequestLocalHostPort80Data = + std::to_array({0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0}); +const std::string_view kSOCKS4OkRequestLocalHostPort80( + kSOCKS4OkRequestLocalHostPort80Data.begin(), + kSOCKS4OkRequestLocalHostPort80Data.end()); -const char kSOCKS4OkReply[] = {0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0}; -const int kSOCKS4OkReplyLength = std::size(kSOCKS4OkReply); +constexpr auto kSOCKS4OkReplyData = + std::to_array({0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0}); +const std::string_view kSOCKS4OkReply(kSOCKS4OkReplyData.begin(), + kSOCKS4OkReplyData.end()); const char kSOCKS5TestHost[] = "host"; const int kSOCKS5TestPort = 80; -const char kSOCKS5GreetRequest[] = {0x05, 0x01, 0x00}; -const int kSOCKS5GreetRequestLength = std::size(kSOCKS5GreetRequest); +constexpr auto kSOCKS5GreetRequestData = + std::to_array({0x05, 0x01, 0x00}); +const std::string_view kSOCKS5GreetRequest(kSOCKS5GreetRequestData.begin(), + kSOCKS5GreetRequestData.end()); -const char kSOCKS5GreetResponse[] = {0x05, 0x00}; -const int kSOCKS5GreetResponseLength = std::size(kSOCKS5GreetResponse); +constexpr auto kSOCKS5GreetResponseData = std::to_array({0x05, 0x00}); +const std::string_view kSOCKS5GreetResponse(kSOCKS5GreetResponseData.begin(), + kSOCKS5GreetResponseData.end()); -const char kSOCKS5OkRequest[] = {0x05, 0x01, 0x00, 0x03, 0x04, 'h', - 'o', 's', 't', 0x00, 0x50}; -const int kSOCKS5OkRequestLength = std::size(kSOCKS5OkRequest); +constexpr auto kSOCKS5OkRequestData = std::to_array( + {0x05, 0x01, 0x00, 0x03, 0x04, 'h', 'o', 's', 't', 0x00, 0x50}); +const std::string_view kSOCKS5OkRequest(kSOCKS5OkRequestData.begin(), + kSOCKS5OkRequestData.end()); -const char kSOCKS5OkResponse[] = {0x05, 0x00, 0x00, 0x01, 127, - 0, 0, 1, 0x00, 0x50}; -const int kSOCKS5OkResponseLength = std::size(kSOCKS5OkResponse); +constexpr auto kSOCKS5OkResponseData = + std::to_array({0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50}); +const std::string_view kSOCKS5OkResponse(kSOCKS5OkResponseData.begin(), + kSOCKS5OkResponseData.end()); int64_t CountReadBytes(base::span reads) { int64_t total = 0; diff --git a/naiveproxy/src/net/socket/socket_test_util.h b/naiveproxy/src/net/socket/socket_test_util.h index fa2e045778..c15cd5d299 100644 --- a/naiveproxy/src/net/socket/socket_test_util.h +++ b/naiveproxy/src/net/socket/socket_test_util.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -189,19 +190,63 @@ struct MockReadWrite { // string_views. class ToStringView { public: + // This class requires the use of implicit constructors to canonicalize the + // different possible argument types. + // NOLINTNEXTLINE(google-explicit-constructor) ToStringView(std::string_view data) : data_(data) {} - ToStringView(const char* data) : data_(data) {} + + // String overloads are needed to disambiguate which constructor to call + // when a string is passed. + + // NOLINTNEXTLINE(google-explicit-constructor) + ToStringView(std::string& data) : data_(data) {} + // NOLINTNEXTLINE(google-explicit-constructor) + ToStringView(const std::string& data) : data_(data) {} + + // Reject rvalue strings. + // NOLINTNEXTLINE(google-explicit-constructor) + ToStringView(std::string&&) = delete; + + // Accept string constants. This will also accidentally accept char arrays, + // but since it obeys the length, it should always be safe as long as the + // lifetime of the char array is long enough. + template + // NOLINTNEXTLINE(google-explicit-constructor) + ToStringView(const char (&data)[N]) : data_(data, N - 1) { + // Verify this doesn't accidentally truncate a char array that didn't have + // a nul-terminator. + CHECK_EQ(data[N - 1], '\0'); + + // This CHECK ensures that this constructor is not accidentally used when + // matching an embedded nul byte was not intended. If you want to match an + // embedded nul byte, the preferred method is to pass a std::array. + CHECK(std::ranges::none_of(data_, [](char c) { return c == '\0'; })); + } // The template parameter is not strictly necessary, but it allows // `MockReadWrite(base::span(array))` to work, instead of having to use // `MockReadWrite(base::span(array))`. template + // NOLINTNEXTLINE(google-explicit-constructor) ToStringView(base::span data) : data_(base::as_string_view(data)) {} template + // NOLINTNEXTLINE(google-explicit-constructor) ToStringView(base::span data) : data_(base::as_string_view(data)) {} + // Non-const versions so callers don't have to write extra code to handle + // mutable input. + template + // NOLINTNEXTLINE(google-explicit-constructor) + ToStringView(base::span data) + : data_(base::as_string_view(data)) {} + template + // NOLINTNEXTLINE(google-explicit-constructor) + ToStringView(base::span data) + : data_(base::as_string_view(data)) {} + ~ToStringView() = default; explicit operator std::string_view() const { return data_; } @@ -235,39 +280,14 @@ struct MockReadWrite { explicit MockReadWrite(ToStringView data) : mode(ASYNC), result(0), data(data), sequence_number(0), tos(0) {} - // Read/write success. Doesn't take a string_view so that it can be used with - // c-strings with embedded nulls. - MockReadWrite(IoMode io_mode, const char* data, int data_len) - : mode(io_mode), - result(0), - data(data, data_len), - sequence_number(0), - tos(0) {} + // This unsafe constructor used to exist. Explicitly delete it to prevent + // accidental usage of the 5-argument constructor below. + MockReadWrite(IoMode io_mode, const char* data, int data_len) = delete; // Read/write success with sequence information. MockReadWrite(IoMode io_mode, int seq, ToStringView data) : mode(io_mode), result(0), data(data), sequence_number(seq), tos(0) {} - // Read/write success with sequence information. - MockReadWrite(IoMode io_mode, const char* data, int data_len, int seq) - : mode(io_mode), - result(0), - data(data, data_len), - sequence_number(seq), - tos(0) {} - - // Read/write success with sequence and TOS information. - MockReadWrite(IoMode io_mode, - const char* data, - int data_len, - int seq, - uint8_t tos_byte) - : mode(io_mode), - result(0), - data(data, data_len), - sequence_number(seq), - tos(tos_byte) {} - // Read/write that defaults to success, with optional sequence and TOS // information. MockReadWrite(IoMode io_mode, @@ -1480,11 +1500,9 @@ extern const int kSOCKS4TestPort; // Constants for a successful SOCKS v4 handshake (connecting to kSOCKS4TestHost // on port kSOCKS4TestPort, for the request). -extern const char kSOCKS4OkRequestLocalHostPort80[]; -extern const int kSOCKS4OkRequestLocalHostPort80Length; +extern const std::string_view kSOCKS4OkRequestLocalHostPort80; -extern const char kSOCKS4OkReply[]; -extern const int kSOCKS4OkReplyLength; +extern const std::string_view kSOCKS4OkReply; // Host / port used for SOCKS5 test strings. extern const char kSOCKS5TestHost[]; @@ -1492,17 +1510,13 @@ extern const int kSOCKS5TestPort; // Constants for a successful SOCKS v5 handshake (connecting to kSOCKS5TestHost // on port kSOCKS5TestPort, for the request).. -extern const char kSOCKS5GreetRequest[]; -extern const int kSOCKS5GreetRequestLength; +extern const std::string_view kSOCKS5GreetRequest; -extern const char kSOCKS5GreetResponse[]; -extern const int kSOCKS5GreetResponseLength; +extern const std::string_view kSOCKS5GreetResponse; -extern const char kSOCKS5OkRequest[]; -extern const int kSOCKS5OkRequestLength; +extern const std::string_view kSOCKS5OkRequest; -extern const char kSOCKS5OkResponse[]; -extern const int kSOCKS5OkResponseLength; +extern const std::string_view kSOCKS5OkResponse; // Helper function to get the total data size of the MockReads in |reads|. int64_t CountReadBytes(base::span reads); diff --git a/naiveproxy/src/net/socket/socks5_client_socket.cc b/naiveproxy/src/net/socket/socks5_client_socket.cc index a908a11fa6..3eeeb7e204 100644 --- a/naiveproxy/src/net/socket/socks5_client_socket.cc +++ b/naiveproxy/src/net/socket/socks5_client_socket.cc @@ -16,9 +16,9 @@ #include "base/numerics/byte_conversions.h" #include "base/numerics/safe_conversions.h" #include "base/strings/string_util.h" +#include "base/trace_event/trace_event.h" #include "net/base/io_buffer.h" #include "net/base/sys_addrinfo.h" -#include "net/base/tracing.h" #include "net/log/net_log.h" #include "net/log/net_log_event_type.h" #include "net/traffic_annotation/network_traffic_annotation.h" diff --git a/naiveproxy/src/net/socket/socks_client_socket.cc b/naiveproxy/src/net/socket/socks_client_socket.cc index 8f7ce54caa..ea1b984590 100644 --- a/naiveproxy/src/net/socket/socks_client_socket.cc +++ b/naiveproxy/src/net/socket/socks_client_socket.cc @@ -315,10 +315,9 @@ std::vector SOCKSClientSocket::BuildHandshakeWriteBuffer() const { request.command = kSOCKSStreamRequest; request.nw_port = base::HostToNet16(destination_.port()); - DCHECK(resolve_host_request_->GetAddressResults() && - !resolve_host_request_->GetAddressResults()->empty()); + DCHECK(!resolve_host_request_->GetAddressResults().empty()); const IPEndPoint& endpoint = - resolve_host_request_->GetAddressResults()->front(); + resolve_host_request_->GetAddressResults().front(); // We disabled IPv6 results when resolving the hostname, so none of the // results in the list will be IPv6. diff --git a/naiveproxy/src/net/socket/ssl_client_socket_impl.cc b/naiveproxy/src/net/socket/ssl_client_socket_impl.cc index 563823cf7a..b5a8d4ef53 100644 --- a/naiveproxy/src/net/socket/ssl_client_socket_impl.cc +++ b/naiveproxy/src/net/socket/ssl_client_socket_impl.cc @@ -31,6 +31,7 @@ #include "base/strings/string_view_util.h" #include "base/synchronization/lock.h" #include "base/task/sequenced_task_runner.h" +#include "base/trace_event/trace_event.h" #include "base/values.h" #include "build/build_config.h" #include "crypto/openssl_util.h" @@ -40,7 +41,6 @@ #include "net/base/net_errors.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "net/base/trace_constants.h" -#include "net/base/tracing.h" #include "net/base/url_util.h" #include "net/cert/cert_status_flags.h" #include "net/cert/cert_verifier.h" @@ -53,6 +53,7 @@ #include "net/log/net_log_event_type.h" #include "net/log/net_log_values.h" #include "net/ssl/cert_compression.h" +#include "net/ssl/openssl_ssl_util.h" #include "net/ssl/ssl_cert_request_info.h" #include "net/ssl/ssl_cipher_suite_names.h" #include "net/ssl/ssl_connection_status_flags.h" @@ -1535,11 +1536,8 @@ int SSLClientSocketImpl::ClientCertRequestCallback(SSL* ssl) { return -1; } - if (!SetSSLChainAndKey(ssl_.get(), client_cert_.get(), nullptr, - &SSLContext::kPrivateKeyMethod)) { - OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_CERT_BAD_FORMAT); - return -1; - } + std::vector cert_chain = + GetCertChainRawVector(*client_cert_); std::vector preferences = client_private_key_->GetAlgorithmPreferences(); @@ -1549,8 +1547,16 @@ int SSLClientSocketImpl::ClientCertRequestCallback(SSL* ssl) { if (base::Contains(preferences, SSL_SIGN_RSA_PKCS1_SHA256)) { preferences.push_back(SSL_SIGN_RSA_PKCS1_SHA256_LEGACY); } - SSL_set_signing_algorithm_prefs(ssl_.get(), preferences.data(), - preferences.size()); + + if (!ConfigureSSLCredential( + ssl_.get(), ConfigureSSLCredentialParams{ + .cert_chain = cert_chain, + .private_key = &SSLContext::kPrivateKeyMethod, + .signing_algorithm_prefs = preferences, + })) { + OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_CERT_BAD_FORMAT); + return -1; + } net_log_.AddEventWithIntParams( NetLogEventType::SSL_CLIENT_CERT_PROVIDED, "cert_count", diff --git a/naiveproxy/src/net/socket/ssl_connect_job.cc b/naiveproxy/src/net/socket/ssl_connect_job.cc index 325495bdd1..56773ecc0d 100644 --- a/naiveproxy/src/net/socket/ssl_connect_job.cc +++ b/naiveproxy/src/net/socket/ssl_connect_job.cc @@ -13,12 +13,12 @@ #include "base/feature_list.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" +#include "base/trace_event/trace_event.h" #include "net/base/connection_endpoint_metadata.h" #include "net/base/features.h" #include "net/base/host_port_pair.h" #include "net/base/net_errors.h" #include "net/base/trace_constants.h" -#include "net/base/tracing.h" #include "net/base/url_util.h" #include "net/cert/x509_util.h" #include "net/http/http_proxy_connect_job.h" diff --git a/naiveproxy/src/net/socket/ssl_server_socket_impl.cc b/naiveproxy/src/net/socket/ssl_server_socket_impl.cc index 38a7cea85f..0e4ef3efd3 100644 --- a/naiveproxy/src/net/socket/ssl_server_socket_impl.cc +++ b/naiveproxy/src/net/socket/ssl_server_socket_impl.cc @@ -829,13 +829,17 @@ int SSLServerContextImpl::SocketImpl::Init() { signing_algorithm_prefs = context_->private_key_->GetAlgorithmPreferences(); } - const SSL_PRIVATE_KEY_METHOD* custom_key = nullptr; - if (context_->pkey_) { - DCHECK(!context_->private_key_); - } else { - DCHECK(context_->private_key_); - custom_key = &kPrivateKeyMethod; - } + ConfigureSSLCredentialParams params{ + .private_key = context_->pkey_ + ? ConfigureSSLCredentialParams::PrivateKeyVariant( + context_->pkey_.get()) + : ConfigureSSLCredentialParams::PrivateKeyVariant( + &kPrivateKeyMethod), + .signing_algorithm_prefs = signing_algorithm_prefs, + .ocsp_response = context_->ssl_server_config_.ocsp_response, + .signed_cert_timestamp_list = + context_->ssl_server_config_.signed_cert_timestamp_list, + }; // If a Trust Anchor ID for the intermediate certificate was provided, // configure an alternative, shorter chain that omits the intermediate. @@ -844,24 +848,24 @@ int SSLServerContextImpl::SocketImpl::Init() { // ID for a single intermediate certificate. DCHECK_EQ(context_->cert_chain_.size(), 2u); - std::vector> elided_chain; - elided_chain.emplace_back(bssl::UpRef(context_->cert_chain_[0])); + std::vector elided_chain = {context_->cert_chain_[0].get()}; - if (!ConfigureSSLCredential( - ssl_.get(), elided_chain, context_->pkey_.get(), custom_key, - signing_algorithm_prefs, context_->ssl_server_config_.ocsp_response, - context_->ssl_server_config_.signed_cert_timestamp_list, - context_->ssl_server_config_.intermediate_trust_anchor_id)) { + ConfigureSSLCredentialParams params_with_trust_anchor_id = params; + params_with_trust_anchor_id.cert_chain = elided_chain; + params_with_trust_anchor_id.trust_anchor_id = + context_->ssl_server_config_.intermediate_trust_anchor_id; + + if (!ConfigureSSLCredential(ssl_.get(), params_with_trust_anchor_id)) { return ERR_UNEXPECTED; } } // Set the full (un-elided) certificate chain and private key. - if (!ConfigureSSLCredential( - ssl_.get(), context_->cert_chain_, context_->pkey_.get(), custom_key, - signing_algorithm_prefs, context_->ssl_server_config_.ocsp_response, - context_->ssl_server_config_.signed_cert_timestamp_list, - /*trust_anchor_id=*/{})) { + std::vector chain_raw = + GetCertChainRawVector(context_->cert_chain_); + params.cert_chain = chain_raw; + + if (!ConfigureSSLCredential(ssl_.get(), params)) { return ERR_UNEXPECTED; } diff --git a/naiveproxy/src/net/socket/stream_attempt.h b/naiveproxy/src/net/socket/stream_attempt.h index 36766bbb3f..b3bc407bcb 100644 --- a/naiveproxy/src/net/socket/stream_attempt.h +++ b/naiveproxy/src/net/socket/stream_attempt.h @@ -9,13 +9,13 @@ #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" +#include "base/trace_event/trace_event.h" #include "base/values.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/base/tracing.h" #include "net/log/net_log_event_type.h" #include "net/log/net_log_with_source.h" #include "net/socket/stream_socket_close_reason.h" diff --git a/naiveproxy/src/net/socket/stream_socket_close_reason.cc b/naiveproxy/src/net/socket/stream_socket_close_reason.cc index 29410abd14..fda94519f0 100644 --- a/naiveproxy/src/net/socket/stream_socket_close_reason.cc +++ b/naiveproxy/src/net/socket/stream_socket_close_reason.cc @@ -31,6 +31,8 @@ std::string_view StreamSocketCloseReasonToString( return "UsingExistingQuicSession"; case StreamSocketCloseReason::kAbort: return "Abort"; + case StreamSocketCloseReason::kAttemptManagerDraining: + return "AttemptManagerDraining"; } } diff --git a/naiveproxy/src/net/socket/stream_socket_close_reason.h b/naiveproxy/src/net/socket/stream_socket_close_reason.h index 39ba86acce..58b90cba33 100644 --- a/naiveproxy/src/net/socket/stream_socket_close_reason.h +++ b/naiveproxy/src/net/socket/stream_socket_close_reason.h @@ -25,7 +25,8 @@ enum class StreamSocketCloseReason { kUsingExistingSpdySession = 7, kUsingExistingQuicSession = 8, kAbort = 9, - kMaxValue = kAbort, + kAttemptManagerDraining = 10, + kMaxValue = kAttemptManagerDraining, }; // LINT.ThenChange(//tools/metrics/histograms/metadata/net/enums.xml:StreamSocketCloseReason) diff --git a/naiveproxy/src/net/socket/tcp_socket_posix.cc b/naiveproxy/src/net/socket/tcp_socket_posix.cc index 30146638f4..28147c2633 100644 --- a/naiveproxy/src/net/socket/tcp_socket_posix.cc +++ b/naiveproxy/src/net/socket/tcp_socket_posix.cc @@ -23,6 +23,7 @@ #include "base/posix/eintr_wrapper.h" #include "base/strings/string_number_conversions.h" #include "base/time/time.h" +#include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "net/base/address_list.h" #include "net/base/io_buffer.h" @@ -32,7 +33,6 @@ #include "net/base/network_change_notifier.h" #include "net/base/sockaddr_storage.h" #include "net/base/sys_addrinfo.h" -#include "net/base/tracing.h" #include "net/http/http_util.h" #include "net/log/net_log.h" #include "net/log/net_log_event_type.h" diff --git a/naiveproxy/src/net/socket/tcp_stream_attempt.cc b/naiveproxy/src/net/socket/tcp_stream_attempt.cc index f16bb9fc2b..6b786a184b 100644 --- a/naiveproxy/src/net/socket/tcp_stream_attempt.cc +++ b/naiveproxy/src/net/socket/tcp_stream_attempt.cc @@ -9,10 +9,10 @@ #include "base/time/time.h" #include "base/timer/timer.h" +#include "base/trace_event/trace_event.h" #include "base/values.h" #include "net/base/address_list.h" #include "net/base/net_errors.h" -#include "net/base/tracing.h" #include "net/socket/client_socket_factory.h" #include "net/socket/socket_performance_watcher.h" #include "net/socket/socket_performance_watcher_factory.h" diff --git a/naiveproxy/src/net/socket/tls_stream_attempt.cc b/naiveproxy/src/net/socket/tls_stream_attempt.cc index ff4cdcf12e..b7aab6c1a0 100644 --- a/naiveproxy/src/net/socket/tls_stream_attempt.cc +++ b/naiveproxy/src/net/socket/tls_stream_attempt.cc @@ -9,12 +9,12 @@ #include #include "base/memory/scoped_refptr.h" +#include "base/trace_event/trace_event.h" #include "base/values.h" #include "net/base/completion_once_callback.h" #include "net/base/features.h" #include "net/base/host_port_pair.h" #include "net/base/net_errors.h" -#include "net/base/tracing.h" #include "net/socket/client_socket_factory.h" #include "net/socket/tcp_stream_attempt.h" #include "net/ssl/ssl_cert_request_info.h" diff --git a/naiveproxy/src/net/socket/transport_connect_job.cc b/naiveproxy/src/net/socket/transport_connect_job.cc index 8310b2efcd..ee8970f667 100644 --- a/naiveproxy/src/net/socket/transport_connect_job.cc +++ b/naiveproxy/src/net/socket/transport_connect_job.cc @@ -10,6 +10,7 @@ #include #include "base/check_op.h" +#include "base/containers/to_vector.h" #include "base/feature_list.h" #include "base/functional/bind.h" #include "base/location.h" @@ -18,12 +19,12 @@ #include "base/notreached.h" #include "base/task/single_thread_task_runner.h" #include "base/time/time.h" +#include "base/trace_event/trace_event.h" #include "net/base/features.h" #include "net/base/host_port_pair.h" #include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "net/base/trace_constants.h" -#include "net/base/tracing.h" #include "net/dns/public/host_resolver_results.h" #include "net/dns/public/secure_dns_policy.h" #include "net/log/net_log_event_type.h" @@ -284,10 +285,6 @@ int TransportConnectJob::DoResolveHostComplete(int result) { return result; } - DCHECK(request_->GetAddressResults()); - DCHECK(request_->GetDnsAliasResults()); - DCHECK(request_->GetEndpointResults()); - // Invoke callback. If it indicates |this| may be slated for deletion, then // only continue after a PostTask. next_state_ = STATE_RESOLVE_HOST_CALLBACK_COMPLETE; @@ -295,7 +292,8 @@ int TransportConnectJob::DoResolveHostComplete(int result) { OnHostResolutionCallbackResult callback_result = params_->host_resolution_callback().Run( ToLegacyDestinationEndpoint(params_->destination()), - *request_->GetEndpointResults(), *request_->GetDnsAliasResults()); + base::ToVector(request_->GetEndpointResults()), + request_->GetDnsAliasResults()); if (callback_result == OnHostResolutionCallbackResult::kMayBeDeletedAsync) { base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( FROM_HERE, base::BindOnce(&TransportConnectJob::OnIOComplete, @@ -308,7 +306,7 @@ int TransportConnectJob::DoResolveHostComplete(int result) { } int TransportConnectJob::DoResolveHostCallbackComplete() { - const auto& unfiltered_results = *request_->GetEndpointResults(); + auto unfiltered_results = request_->GetEndpointResults(); bool svcb_optional = IsSvcbOptional(unfiltered_results); std::set ip_endpoints_seen; for (const auto& result : unfiltered_results) { @@ -333,7 +331,7 @@ int TransportConnectJob::DoResolveHostCallbackComplete() { endpoint_results_.push_back(std::move(new_result)); } } - dns_aliases_ = *request_->GetDnsAliasResults(); + dns_aliases_ = request_->GetDnsAliasResults(); // No need to retain `request_` beyond this point. request_.reset(); @@ -526,8 +524,8 @@ void TransportConnectJob::ChangePriorityInternal(RequestPriority priority) { bool TransportConnectJob::IsSvcbOptional( base::span results) const { // If SVCB/HTTPS resolution succeeded, the client supports ECH, and all routes - // support ECH, disable the A/AAAA fallback. See Section 10.1 of - // draft-ietf-dnsop-svcb-https-08. + // support ECH, disable the A/AAAA fallback. See Section 5.1 of + // draft-ietf-tls-svcb-ech-08. auto* scheme_host_port = std::get_if(¶ms_->destination()); @@ -540,26 +538,25 @@ bool TransportConnectJob::IsSvcbOptional( return true; // ECH is not supported for this request. } - return !HostResolver::AllProtocolEndpointsHaveEch(results); + return !HostResolver::AllAlternativeEndpointsHaveEch(results); } bool TransportConnectJob::IsEndpointResultUsable( const HostResolverEndpointResult& result, bool svcb_optional) const { - // A `HostResolverEndpointResult` with no ALPN protocols is the fallback - // A/AAAA route. This is always compatible. We assume the ALPN-less option is - // TCP-based. - if (result.metadata.supported_protocol_alpns.empty()) { - // See draft-ietf-dnsop-svcb-https-08, Section 3. + // We assume the authority endpoint (i.e. not from SVCB/HTTPS) is TCP-based, + // so an authority endpoint. + if (!result.metadata.IsAlternative()) { + // See RFC 9460, Section 3. return svcb_optional; } - // See draft-ietf-dnsop-svcb-https-08, Section 7.1.2. Routes are usable if - // there is an overlap between the route's ALPN protocols and the configured - // ones. This ensures we do not, e.g., connect to a QUIC-only route with TCP. + // See RFC 9460, Section 7.1.2. Alternative endpoints are usable if there is + // an overlap between the endpoint's ALPN protocols and the configured ones. + // This ensures we do not, e.g., connect to a QUIC-only endpoint with TCP. // Note that, if `params_` did not specify any ALPN protocols, no - // SVCB/HTTPS-based routes will match and we will effectively ignore all but - // plain A/AAAA routes. + // SVCB/HTTPS-based endpoints will match and we will effectively ignore all + // but plain A/AAAA endpoints. for (const auto& alpn : result.metadata.supported_protocol_alpns) { if (params_->supported_alpns().contains(alpn)) { return true; diff --git a/naiveproxy/src/net/socket/udp_socket_posix.cc b/naiveproxy/src/net/socket/udp_socket_posix.cc index e4eff3a841..d2e57d6365 100644 --- a/naiveproxy/src/net/socket/udp_socket_posix.cc +++ b/naiveproxy/src/net/socket/udp_socket_posix.cc @@ -34,6 +34,7 @@ #include "base/rand_util.h" #include "base/task/current_thread.h" #include "base/task/thread_pool.h" +#include "base/trace_event/trace_event.h" #include "net/base/cronet_buildflags.h" #include "net/base/io_buffer.h" #include "net/base/ip_address.h" @@ -43,7 +44,6 @@ #include "net/base/network_activity_monitor.h" #include "net/base/sockaddr_storage.h" #include "net/base/trace_constants.h" -#include "net/base/tracing.h" #include "net/log/net_log.h" #include "net/log/net_log_event_type.h" #include "net/log/net_log_source.h" diff --git a/naiveproxy/src/net/socket/udp_socket_win.cc b/naiveproxy/src/net/socket/udp_socket_win.cc index 5e446ebbca..68401a5b6b 100644 --- a/naiveproxy/src/net/socket/udp_socket_win.cc +++ b/naiveproxy/src/net/socket/udp_socket_win.cc @@ -9,12 +9,12 @@ #include #include +#include #include "base/check_op.h" #include "base/containers/span.h" #include "base/functional/bind.h" #include "base/functional/callback.h" -#include "base/lazy_instance.h" #include "base/memory/raw_ptr.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" @@ -196,9 +196,9 @@ QwaveApi::QwaveApi() { } QwaveApi* QwaveApi::GetDefault() { - static base::LazyInstance::Leaky lazy_qwave = - LAZY_INSTANCE_INITIALIZER; - return lazy_qwave.Pointer(); + static_assert(std::is_trivially_destructible::value); + static QwaveApi qwave; + return &qwave; } bool QwaveApi::qwave_supported() const { diff --git a/naiveproxy/src/net/spdy/bidirectional_stream_spdy_impl.cc b/naiveproxy/src/net/spdy/bidirectional_stream_spdy_impl.cc index 85b3291d01..27fe395a94 100644 --- a/naiveproxy/src/net/spdy/bidirectional_stream_spdy_impl.cc +++ b/naiveproxy/src/net/spdy/bidirectional_stream_spdy_impl.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 "net/spdy/bidirectional_stream_spdy_impl.h" #include @@ -93,7 +88,7 @@ int BidirectionalStreamSpdyImpl::ReadData(IOBuffer* buf, int buf_len) { // If there is data buffered, complete the IO immediately. if (!read_data_queue_.IsEmpty()) { - return read_data_queue_.Dequeue(buf->data(), buf_len); + return read_data_queue_.Dequeue(buf->first(buf_len)); } else if (stream_closed_) { return closed_stream_status_; } @@ -135,12 +130,11 @@ void BidirectionalStreamSpdyImpl::SendvData( } else { pending_combined_buffer_ = base::MakeRefCounted(total_len); - int len = 0; + auto out_span = pending_combined_buffer_->span(); // TODO(xunjieli): Get rid of extra copy. Coalesce headers and data frames. for (size_t i = 0; i < buffers.size(); ++i) { - memcpy(pending_combined_buffer_->data() + len, buffers[i]->data(), - lengths[i]); - len += lengths[i]; + size_t sz_len = lengths[i]; + out_span.take_first(sz_len).copy_from(buffers[i]->first(sz_len)); } } stream_->SendData(pending_combined_buffer_.get(), total_len, diff --git a/naiveproxy/src/net/spdy/spdy_buffer.cc b/naiveproxy/src/net/spdy/spdy_buffer.cc index 271d94fac2..61d39009f2 100644 --- a/naiveproxy/src/net/spdy/spdy_buffer.cc +++ b/naiveproxy/src/net/spdy/spdy_buffer.cc @@ -2,17 +2,13 @@ // 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 "net/spdy/spdy_buffer.h" #include #include #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/functional/callback.h" #include "base/trace_event/memory_usage_estimator.h" #include "net/base/io_buffer.h" @@ -28,16 +24,16 @@ const size_t kMaxSpdyFrameSize = 0x00ffffff; // Makes a spdy::SpdySerializedFrame with |size| bytes of data copied from // |data|. |data| must be non-NULL and |size| must be positive. std::unique_ptr MakeSpdySerializedFrame( - const char* data, - size_t size) { - DCHECK(data); - CHECK_GT(size, 0u); - CHECK_LE(size, kMaxSpdyFrameSize); + base::span data) { + CHECK(!data.empty()); + CHECK_LE(data.size(), kMaxSpdyFrameSize); - auto frame_data = std::make_unique(size); - std::memcpy(frame_data.get(), data, size); + auto frame_data = std::make_unique(data.size()); + // SAFETY: `frame_data` has size `data.size()`, and so does `data`. The type + // is needed to transfer ownership over to Quiche. + UNSAFE_BUFFERS(std::memcpy(frame_data.get(), data.data(), data.size())); return std::make_unique(std::move(frame_data), - size); + data.size()); } } // namespace @@ -70,11 +66,11 @@ SpdyBuffer::SpdyBuffer(std::unique_ptr frame) // The given data may not be strictly a SPDY frame; we (ab)use // |frame_| just as a container. -SpdyBuffer::SpdyBuffer(const char* data, size_t size) +SpdyBuffer::SpdyBuffer(base::span data) : shared_frame_(base::MakeRefCounted()) { - CHECK_GT(size, 0u); - CHECK_LE(size, kMaxSpdyFrameSize); - shared_frame_->data = MakeSpdySerializedFrame(data, size); + CHECK_GT(data.size(), 0u); + CHECK_LE(data.size(), kMaxSpdyFrameSize); + shared_frame_->data = MakeSpdySerializedFrame(data); } SpdyBuffer::~SpdyBuffer() { @@ -82,8 +78,9 @@ SpdyBuffer::~SpdyBuffer() { ConsumeHelper(GetRemainingSize(), DISCARD); } -const char* SpdyBuffer::GetRemainingData() const { - return shared_frame_->data->data() + offset_; +base::span SpdyBuffer::GetRemaining() const { + std::string_view frame_view(*shared_frame_->data); + return base::as_byte_span(frame_view).subspan(offset_); } size_t SpdyBuffer::GetRemainingSize() const { diff --git a/naiveproxy/src/net/spdy/spdy_buffer.h b/naiveproxy/src/net/spdy/spdy_buffer.h index 49edec582d..7f04c60618 100644 --- a/naiveproxy/src/net/spdy/spdy_buffer.h +++ b/naiveproxy/src/net/spdy/spdy_buffer.h @@ -9,6 +9,7 @@ #include #include +#include "base/containers/span.h" #include "base/functional/callback_forward.h" #include "base/memory/ref_counted.h" #include "net/base/net_export.h" @@ -51,9 +52,8 @@ class NET_EXPORT_PRIVATE SpdyBuffer { // owned by |frame| or outlives it. explicit SpdyBuffer(std::unique_ptr frame); - // Construct with a copy of the given raw data. |data| must be - // non-NULL and |size| must be non-zero. - SpdyBuffer(const char* data, size_t size); + // Construct with a copy of the given raw data. `data` must be non-empty. + explicit SpdyBuffer(base::span data); SpdyBuffer(const SpdyBuffer&) = delete; SpdyBuffer& operator=(const SpdyBuffer&) = delete; @@ -63,7 +63,7 @@ class NET_EXPORT_PRIVATE SpdyBuffer { ~SpdyBuffer(); // Returns the remaining (unconsumed) data. - const char* GetRemainingData() const; + base::span GetRemaining() const; // Returns the number of remaining (unconsumed) bytes. size_t GetRemainingSize() const; diff --git a/naiveproxy/src/net/spdy/spdy_http_stream.cc b/naiveproxy/src/net/spdy/spdy_http_stream.cc index 400cdabf6f..54677771ae 100644 --- a/naiveproxy/src/net/spdy/spdy_http_stream.cc +++ b/naiveproxy/src/net/spdy/spdy_http_stream.cc @@ -117,7 +117,7 @@ int SpdyHttpStream::ReadResponseBody(IOBuffer* buf, // If we have data buffered, complete the IO immediately. if (!response_body_queue_.IsEmpty()) { - return response_body_queue_.Dequeue(buf->data(), buf_len); + return response_body_queue_.Dequeue(buf->first(buf_len)); } else if (stream_closed_) { return closed_stream_status_; } @@ -528,7 +528,7 @@ void SpdyHttpStream::DoBufferedReadCallback() { if (!response_body_queue_.IsEmpty()) { int rv = - response_body_queue_.Dequeue(user_buffer_->data(), user_buffer_len_); + response_body_queue_.Dequeue(user_buffer_->first(user_buffer_len_)); user_buffer_ = nullptr; user_buffer_len_ = 0; DoResponseCallback(rv); diff --git a/naiveproxy/src/net/spdy/spdy_proxy_client_socket.cc b/naiveproxy/src/net/spdy/spdy_proxy_client_socket.cc index 0888514880..44df2a258e 100644 --- a/naiveproxy/src/net/spdy/spdy_proxy_client_socket.cc +++ b/naiveproxy/src/net/spdy/spdy_proxy_client_socket.cc @@ -210,7 +210,7 @@ int SpdyProxyClientSocket::ReadIfReady(IOBuffer* buf, DCHECK(next_state_ == STATE_OPEN || next_state_ == STATE_CLOSED); DCHECK(buf); - size_t result = PopulateUserReadBuffer(buf->data(), buf_len); + size_t result = PopulateUserReadBuffer(buf->first(buf_len)); if (result == 0) { read_callback_ = std::move(callback); return ERR_IO_PENDING; @@ -225,8 +225,8 @@ int SpdyProxyClientSocket::CancelReadIfReady() { return OK; } -size_t SpdyProxyClientSocket::PopulateUserReadBuffer(char* data, size_t len) { - return read_buffer_queue_.Dequeue(data, len); +size_t SpdyProxyClientSocket::PopulateUserReadBuffer(base::span data) { + return read_buffer_queue_.Dequeue(data); } int SpdyProxyClientSocket::Write( @@ -504,8 +504,7 @@ void SpdyProxyClientSocket::OnHeadersReceived( void SpdyProxyClientSocket::OnDataReceived(std::unique_ptr buffer) { if (buffer) { net_log_.AddByteTransferEvent(NetLogEventType::SOCKET_BYTES_RECEIVED, - buffer->GetRemainingSize(), - buffer->GetRemainingData()); + buffer->GetRemaining()); read_buffer_queue_.Enqueue(std::move(buffer)); } else { net_log_.AddByteTransferEvent(NetLogEventType::SOCKET_BYTES_RECEIVED, 0, @@ -522,7 +521,7 @@ void SpdyProxyClientSocket::OnDataReceived(std::unique_ptr buffer) { if (read_callback_) { if (user_buffer_) { - int rv = PopulateUserReadBuffer(user_buffer_->data(), user_buffer_len_); + int rv = PopulateUserReadBuffer(user_buffer_->first(user_buffer_len_)); user_buffer_ = nullptr; user_buffer_len_ = 0; std::move(read_callback_).Run(rv); diff --git a/naiveproxy/src/net/spdy/spdy_proxy_client_socket.h b/naiveproxy/src/net/spdy/spdy_proxy_client_socket.h index 74953b3bdf..0b1d96ea5b 100644 --- a/naiveproxy/src/net/spdy/spdy_proxy_client_socket.h +++ b/naiveproxy/src/net/spdy/spdy_proxy_client_socket.h @@ -11,6 +11,7 @@ #include #include +#include "base/containers/span.h" #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" @@ -134,9 +135,9 @@ class NET_EXPORT_PRIVATE SpdyProxyClientSocket : public ProxyClientSocket, int DoSendRequestComplete(int result); int DoReadReplyComplete(int result); - // Populates |user_buffer_| with as much read data as possible + // Populates `data` with as much read data as possible // and returns the number of bytes read. - size_t PopulateUserReadBuffer(char* out, size_t len); + size_t PopulateUserReadBuffer(base::span data); // Called when the peer sent END_STREAM. void MaybeSendEndStream(); diff --git a/naiveproxy/src/net/spdy/spdy_read_queue.cc b/naiveproxy/src/net/spdy/spdy_read_queue.cc index 761e874c9f..9e97b0a72e 100644 --- a/naiveproxy/src/net/spdy/spdy_read_queue.cc +++ b/naiveproxy/src/net/spdy/spdy_read_queue.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 "net/spdy/spdy_read_queue.h" #include @@ -38,14 +33,14 @@ void SpdyReadQueue::Enqueue(std::unique_ptr buffer) { queue_.push_back(std::move(buffer)); } -size_t SpdyReadQueue::Dequeue(char* out, size_t len) { - DCHECK_GT(len, 0u); +size_t SpdyReadQueue::Dequeue(base::span out) { + DCHECK_GT(out.size(), 0u); size_t bytes_copied = 0; - while (!queue_.empty() && bytes_copied < len) { + while (!queue_.empty() && !out.empty()) { SpdyBuffer* buffer = queue_.front().get(); - size_t bytes_to_copy = - std::min(len - bytes_copied, buffer->GetRemainingSize()); - memcpy(out + bytes_copied, buffer->GetRemainingData(), bytes_to_copy); + size_t bytes_to_copy = std::min(out.size(), buffer->GetRemainingSize()); + out.take_first(bytes_to_copy) + .copy_from(buffer->GetRemaining().first(bytes_to_copy)); bytes_copied += bytes_to_copy; if (bytes_to_copy == buffer->GetRemainingSize()) queue_.pop_front(); diff --git a/naiveproxy/src/net/spdy/spdy_read_queue.h b/naiveproxy/src/net/spdy/spdy_read_queue.h index ef2c3d7f13..3ded16bc56 100644 --- a/naiveproxy/src/net/spdy/spdy_read_queue.h +++ b/naiveproxy/src/net/spdy/spdy_read_queue.h @@ -5,10 +5,13 @@ #ifndef NET_SPDY_SPDY_READ_QUEUE_H_ #define NET_SPDY_SPDY_READ_QUEUE_H_ +#include + #include #include #include "base/containers/circular_deque.h" +#include "base/containers/span.h" #include "net/base/net_export.h" namespace net { @@ -35,9 +38,9 @@ class NET_EXPORT_PRIVATE SpdyReadQueue { // Enqueues the bytes in |buffer|. void Enqueue(std::unique_ptr buffer); - // Dequeues up to |len| (which must be positive) bytes into - // |out|. Returns the number of bytes dequeued. - size_t Dequeue(char* out, size_t len); + // Dequeues up to `out.size()` bytes into `out`. Returns the number of bytes + // dequeued. + size_t Dequeue(base::span out); // Removes all bytes from the queue. void Clear(); diff --git a/naiveproxy/src/net/spdy/spdy_session.cc b/naiveproxy/src/net/spdy/spdy_session.cc index 3613f4b8c2..e8e8705c09 100644 --- a/naiveproxy/src/net/spdy/spdy_session.cc +++ b/naiveproxy/src/net/spdy/spdy_session.cc @@ -33,12 +33,12 @@ #include "base/task/single_thread_task_runner.h" #include "base/time/time.h" #include "base/trace_event/memory_usage_estimator.h" +#include "base/trace_event/trace_event.h" #include "base/values.h" #include "net/base/features.h" #include "net/base/privacy_mode.h" #include "net/base/proxy_chain.h" #include "net/base/proxy_string_util.h" -#include "net/base/tracing.h" #include "net/base/url_util.h" #include "net/cert/asn1_util.h" #include "net/cert/cert_verify_result.h" @@ -1323,9 +1323,10 @@ void SpdySession::CloseSessionOnError(Error err, DoDrainSession(err, description, force_send_go_away); } -void SpdySession::MakeUnavailable() { +void SpdySession::MakeUnavailable(Error error) { if (availability_state_ == STATE_AVAILABLE) { availability_state_ = STATE_GOING_AWAY; + error_on_unavailable_ = error; pool_->MakeSessionUnavailable(GetWeakPtr()); } } @@ -1335,6 +1336,7 @@ void SpdySession::StartGoingAway(spdy::SpdyStreamId last_good_stream_id, DCHECK_GE(availability_state_, STATE_GOING_AWAY); DCHECK_NE(OK, status); DCHECK_NE(ERR_IO_PENDING, status); + last_good_stream_id_ = last_good_stream_id; // The loops below are carefully written to avoid reentrancy problems. @@ -1407,6 +1409,7 @@ base::Value::Dict SpdySession::GetInfoAsValue() const { .Set("negotiated_protocol", NextProtoToString(socket_->GetNegotiatedProtocol())) .Set("error", error_on_close_) + .Set("error_on_unavailable", error_on_unavailable_) .Set("max_concurrent_streams", static_cast(max_concurrent_streams_)) .Set("streams_initiated_count", streams_initiated_count_) @@ -1420,7 +1423,8 @@ base::Value::Dict SpdySession::GetInfoAsValue() const { .Set("unacked_recv_window_bytes", session_unacked_recv_window_bytes_) .Set("support_websocket", support_websocket_) .Set("availability_state", - AvailabilityStateToString(availability_state_)); + AvailabilityStateToString(availability_state_)) + .Set("last_good_stream_id", static_cast(last_good_stream_id_)); // TODO(crbug.com/405934874): Remove once we identify the cause of the bug. { @@ -1451,6 +1455,13 @@ base::Value::Dict SpdySession::GetInfoAsValue() const { } dict.Set("aliases", std::move(alias_list)); } + + base::Value::List active_stream_details; + for (const auto& [_, stream] : active_streams_) { + active_stream_details.Append(stream->GetInfoAsValue()); + } + dict.Set("active_stream_details", std::move(active_stream_details)); + return dict; } @@ -2121,7 +2132,7 @@ int SpdySession::DoWrite() { CHECK_EQ(stream->stream_id(), kLastStreamId); // We've exhausted the stream ID space, and no new streams may be // created after this one. - MakeUnavailable(); + MakeUnavailable(ERR_HTTP2_PROTOCOL_ERROR); StartGoingAway(kLastStreamId, ERR_HTTP2_PROTOCOL_ERROR); } } @@ -2639,7 +2650,7 @@ void SpdySession::DoDrainSession(Error err, if (availability_state_ == STATE_DRAINING) { return; } - MakeUnavailable(); + MakeUnavailable(err); drain_error_ = err; drain_description_ = description; @@ -2845,14 +2856,22 @@ void SpdySession::OnGoAway(spdy::SpdyStreamId last_accepted_stream_id, }); go_away_error_ = error_code; go_away_debug_data_ = std::string(debug_data); - MakeUnavailable(); + + Error net_error; if (error_code == spdy::ERROR_CODE_HTTP_1_1_REQUIRED) { - // TODO(bnc): Record histogram with number of open streams capped at 50. - DoDrainSession(ERR_HTTP_1_1_REQUIRED, "HTTP_1_1_REQUIRED for stream."); + net_error = ERR_HTTP_1_1_REQUIRED; } else if (error_code == spdy::ERROR_CODE_NO_ERROR) { - StartGoingAway(last_accepted_stream_id, ERR_HTTP2_SERVER_REFUSED_STREAM); + net_error = ERR_HTTP2_SERVER_REFUSED_STREAM; } else { - StartGoingAway(last_accepted_stream_id, ERR_HTTP2_PROTOCOL_ERROR); + net_error = ERR_HTTP2_PROTOCOL_ERROR; + } + MakeUnavailable(net_error); + + if (net_error == ERR_HTTP_1_1_REQUIRED) { + // TODO(bnc): Record histogram with number of open streams capped at 50. + DoDrainSession(net_error, "HTTP_1_1_REQUIRED for stream."); + } else { + StartGoingAway(last_accepted_stream_id, net_error); } // This is to handle the case when we already don't have any active // streams (i.e., StartGoingAway() did nothing). Otherwise, we have @@ -2898,7 +2917,8 @@ void SpdySession::OnStreamFrameData(spdy::SpdyStreamId stream_id, if (data) { DCHECK_GT(len, 0u); CHECK_LE(len, static_cast(kReadBufferSize)); - buffer = std::make_unique(data, len); + buffer = std::make_unique( + base::as_byte_span(UNSAFE_TODO(base::span(data, len)))); DecreaseRecvWindowSize(static_cast(len)); buffer->AddConsumeCallback(base::BindRepeating( diff --git a/naiveproxy/src/net/spdy/spdy_session.h b/naiveproxy/src/net/spdy/spdy_session.h index 4b14d018d6..b9583aa6f2 100644 --- a/naiveproxy/src/net/spdy/spdy_session.h +++ b/naiveproxy/src/net/spdy/spdy_session.h @@ -534,7 +534,7 @@ class NET_EXPORT SpdySession // Mark this session as unavailable, meaning that it will not be used to // service new streams. Unlike when a GOAWAY frame is received, this function // will not close any streams. - void MakeUnavailable(); + void MakeUnavailable(Error error); // Closes all active streams with stream id's greater than // |last_good_stream_id|, as well as any created or pending @@ -1107,6 +1107,11 @@ class NET_EXPORT SpdySession // Initialized to OK. Error error_on_close_ = OK; + // If the session is made unavailable (i.e., `availability_state_` is + // STATE_GOING_AWAY), then `error_on_unavailable_` holds the error that + // caused it to become unavailable. Initialized to OK. + Error error_on_unavailable_ = OK; + // Settings that are sent in the initial SETTINGS frame // (if |enable_sending_initial_data_| is true), // and also control SpdySession parameters like initial receive window size @@ -1300,6 +1305,7 @@ class NET_EXPORT SpdySession std::string drain_description_; std::optional go_away_error_; std::string go_away_debug_data_; + spdy::SpdyStreamId last_good_stream_id_ = 0; // Represents how this session is created. const MultiplexedSessionCreationInitiator session_creation_initiator_; diff --git a/naiveproxy/src/net/spdy/spdy_session_pool.cc b/naiveproxy/src/net/spdy/spdy_session_pool.cc index c8f7909e4c..c80a770279 100644 --- a/naiveproxy/src/net/spdy/spdy_session_pool.cc +++ b/naiveproxy/src/net/spdy/spdy_session_pool.cc @@ -13,13 +13,13 @@ #include "base/functional/bind.h" #include "base/metrics/histogram_macros.h" #include "base/task/single_thread_task_runner.h" +#include "base/trace_event/trace_event.h" #include "base/types/expected.h" #include "base/values.h" #include "build/build_config.h" #include "net/base/features.h" #include "net/base/ip_endpoint.h" #include "net/base/trace_constants.h" -#include "net/base/tracing.h" #include "net/dns/host_resolver.h" #include "net/dns/public/host_resolver_source.h" #include "net/http/http_network_session.h" @@ -53,13 +53,13 @@ SpdySessionPool::SpdySessionRequest::Delegate::~Delegate() = default; SpdySessionPool::SpdySessionRequest::SpdySessionRequest( const SpdySessionKey& key, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool is_websocket, bool is_blocking_request_for_session, Delegate* delegate, SpdySessionPool* spdy_session_pool) : key_(key), - enable_ip_based_pooling_(enable_ip_based_pooling), + enable_ip_based_pooling_for_h2_(enable_ip_based_pooling_for_h2), is_websocket_(is_websocket), is_blocking_request_for_session_(is_blocking_request_for_session), delegate_(delegate), @@ -203,7 +203,7 @@ SpdySessionPool::CreateAvailableSessionFromSocket( base::WeakPtr SpdySessionPool::FindAvailableSession( const SpdySessionKey& key, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool is_websocket, const NetLogWithSource& net_log) { auto it = LookupAvailableSessionByKey(key); @@ -221,7 +221,7 @@ base::WeakPtr SpdySessionPool::FindAvailableSession( return it->second; } - if (enable_ip_based_pooling) { + if (enable_ip_based_pooling_for_h2) { UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionGet", FOUND_EXISTING_FROM_IP_POOL, SPDY_SESSION_GET_MAX); net_log.AddEventReferencingSource( @@ -238,7 +238,7 @@ SpdySessionPool::FindMatchingIpSessionForServiceEndpoint( const SpdySessionKey& key, const ServiceEndpoint& service_endpoint, const std::set& dns_aliases) { - CHECK(!HasAvailableSession(key, /*enable_ip_based_pooling=*/true, + CHECK(!HasAvailableSession(key, /*enable_ip_based_pooling_for_h2=*/true, /*is_websocket=*/false)); CHECK(key.socket_tag() == SocketTag()); @@ -252,7 +252,7 @@ SpdySessionPool::FindMatchingIpSessionForServiceEndpoint( } bool SpdySessionPool::HasAvailableSession(const SpdySessionKey& key, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool is_websocket) const { auto it = available_sessions_.find(key); if (it == available_sessions_.end() || @@ -260,12 +260,13 @@ bool SpdySessionPool::HasAvailableSession(const SpdySessionKey& key, return false; } - return enable_ip_based_pooling ? true : key == it->second->spdy_session_key(); + return enable_ip_based_pooling_for_h2 ? true + : key == it->second->spdy_session_key(); } base::WeakPtr SpdySessionPool::RequestSession( const SpdySessionKey& key, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool is_websocket, const NetLogWithSource& net_log, base::RepeatingClosure on_blocking_request_destroyed_callback, @@ -274,8 +275,8 @@ base::WeakPtr SpdySessionPool::RequestSession( bool* is_blocking_request_for_session) { DCHECK(delegate); - base::WeakPtr spdy_session = - FindAvailableSession(key, enable_ip_based_pooling, is_websocket, net_log); + base::WeakPtr spdy_session = FindAvailableSession( + key, enable_ip_based_pooling_for_h2, is_websocket, net_log); if (spdy_session) { // This value doesn't really matter, but best to always populate it, for // consistency. @@ -286,7 +287,7 @@ base::WeakPtr SpdySessionPool::RequestSession( RequestInfoForKey* request_info = &spdy_session_request_map_[key]; *is_blocking_request_for_session = !request_info->has_blocking_request; *spdy_session_request = std::make_unique( - key, enable_ip_based_pooling, is_websocket, + key, enable_ip_based_pooling_for_h2, is_websocket, *is_blocking_request_for_session, delegate, this); request_info->request_set.insert(spdy_session_request->get()); @@ -517,7 +518,7 @@ void SpdySessionPool::MakeCurrentSessionsGoingAway(Error error) { continue; } - session->MakeUnavailable(); + session->MakeUnavailable(error); session->StartGoingAway(kLastStreamId, error); session->MaybeFinishGoingAway(); DCHECK(!IsSessionAvailable(session)); @@ -584,7 +585,7 @@ void SpdySessionPool::OnSSLConfigForServersChanged( } if (session_matches) { - session->MakeUnavailable(); + session->MakeUnavailable(ERR_NETWORK_CHANGED); // Note this call preserves active streams but fails any streams that are // waiting on a stream ID. // TODO(crbug.com/40768859): This is not ideal, but SpdySession @@ -817,8 +818,9 @@ void SpdySessionPool::UpdatePendingRequests(const SpdySessionKey& key) { if ((*request)->is_websocket() && !new_session->support_websocket()) continue; // Don't use IP pooled session if not allowed. - if (!(*request)->enable_ip_based_pooling() && is_pooled) + if (!(*request)->enable_ip_based_pooling_for_h2() && is_pooled) { continue; + } break; } if (request == request_set->end()) diff --git a/naiveproxy/src/net/spdy/spdy_session_pool.h b/naiveproxy/src/net/spdy/spdy_session_pool.h index 3a1f304225..13aeb3f6c1 100644 --- a/naiveproxy/src/net/spdy/spdy_session_pool.h +++ b/naiveproxy/src/net/spdy/spdy_session_pool.h @@ -102,7 +102,7 @@ class NET_EXPORT SpdySessionPool // Constructor - this is called by the SpdySessionPool. SpdySessionRequest(const SpdySessionKey& key, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool is_websocket, bool is_blocking_request_for_session, Delegate* delegate, @@ -118,7 +118,9 @@ class NET_EXPORT SpdySessionPool void OnRemovedFromPool(); const SpdySessionKey& key() const { return key_; } - bool enable_ip_based_pooling() const { return enable_ip_based_pooling_; } + bool enable_ip_based_pooling_for_h2() const { + return enable_ip_based_pooling_for_h2_; + } bool is_websocket() const { return is_websocket_; } bool is_blocking_request_for_session() const { return is_blocking_request_for_session_; @@ -131,7 +133,7 @@ class NET_EXPORT SpdySessionPool private: const SpdySessionKey key_; - const bool enable_ip_based_pooling_; + const bool enable_ip_based_pooling_for_h2_; const bool is_websocket_; const bool is_blocking_request_for_session_; const raw_ptr delegate_; @@ -209,14 +211,14 @@ class NET_EXPORT SpdySessionPool // If there is an available session for |key|, return it. // Otherwise if there is a session to pool to based on IP address: - // * if |enable_ip_based_pooling == true|, + // * if |enable_ip_based_pooling_for_h2 == true|, // then mark it as available for |key| and return it; - // * if |enable_ip_based_pooling == false|, + // * if |enable_ip_based_pooling_for_h2 == false|, // then remove it from the available sessions, and return nullptr. // Otherwise return nullptr. base::WeakPtr FindAvailableSession( const SpdySessionKey& key, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool is_websocket, const NetLogWithSource& net_log); @@ -230,9 +232,9 @@ class NET_EXPORT SpdySessionPool // Returns true if there is an available session for `key`. Otherwise, if // there is a session to pool to based on IP address, returns true if - // `enable_ip_based_pooling` is true. Otherwise returns false. + // `enable_ip_based_pooling_for_h2` is true. Otherwise returns false. bool HasAvailableSession(const SpdySessionKey& key, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool is_websocket) const; // Just like FindAvailableSession. @@ -262,7 +264,7 @@ class NET_EXPORT SpdySessionPool // all requests for a session have been successfully responded to. base::WeakPtr RequestSession( const SpdySessionKey& key, - bool enable_ip_based_pooling, + bool enable_ip_based_pooling_for_h2, bool is_websocket, const NetLogWithSource& net_log, base::RepeatingClosure on_blocking_request_destroyed_callback, diff --git a/naiveproxy/src/net/spdy/spdy_stream.cc b/naiveproxy/src/net/spdy/spdy_stream.cc index 8367de812a..f7280e1f56 100644 --- a/naiveproxy/src/net/spdy/spdy_stream.cc +++ b/naiveproxy/src/net/spdy/spdy_stream.cc @@ -713,6 +713,15 @@ bool SpdyStream::GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const { return result; } +base::Value::Dict SpdyStream::GetInfoAsValue() const { + base::Value::Dict dict; + dict.Set("stream_id", static_cast(stream_id_)); + dict.Set("io_state", DescribeState(io_state_)); + dict.Set("send_stalled_by_flow_control", send_stalled_by_flow_control_); + dict.Set("pending_send_status", pending_send_status_); + return dict; +} + void SpdyStream::QueueNextDataFrame() { // Until the request has been completely sent, we cannot be sure // that our stream_id is correct. diff --git a/naiveproxy/src/net/spdy/spdy_stream.h b/naiveproxy/src/net/spdy/spdy_stream.h index 3c34474305..e49026df76 100644 --- a/naiveproxy/src/net/spdy/spdy_stream.h +++ b/naiveproxy/src/net/spdy/spdy_stream.h @@ -53,9 +53,9 @@ enum SpdyStreamType { // Passed to some SpdyStream functions to indicate whether there's // more data to send. -enum SpdySendStatus { - MORE_DATA_TO_SEND, - NO_MORE_DATA_TO_SEND +enum SpdySendStatus : int { + MORE_DATA_TO_SEND = 0, + NO_MORE_DATA_TO_SEND = 1, }; // SpdyStream is owned by SpdySession and is used to represent each stream known @@ -398,6 +398,8 @@ class NET_EXPORT_PRIVATE SpdyStream { bool detect_broken_connection() const { return detect_broken_connection_; } + base::Value::Dict GetInfoAsValue() const; + private: friend class test::SpdyStreamTest; diff --git a/naiveproxy/src/net/spdy/spdy_stream_test_util.cc b/naiveproxy/src/net/spdy/spdy_stream_test_util.cc index 0cc983baf1..fddfc96dce 100644 --- a/naiveproxy/src/net/spdy/spdy_stream_test_util.cc +++ b/naiveproxy/src/net/spdy/spdy_stream_test_util.cc @@ -8,6 +8,7 @@ #include #include +#include "base/containers/span.h" #include "net/spdy/spdy_stream.h" #include "testing/gtest/include/gtest/gtest.h" @@ -107,7 +108,9 @@ std::string StreamDelegateBase::TakeReceivedData() { size_t len = received_data_queue_.GetTotalSize(); std::string received_data(len, '\0'); if (len > 0) { - EXPECT_EQ(len, received_data_queue_.Dequeue(std::data(received_data), len)); + EXPECT_EQ(received_data_queue_.Dequeue( + base::as_writable_byte_span(received_data)), + len); } return received_data; } diff --git a/naiveproxy/src/net/spdy/spdy_test_util_common.cc b/naiveproxy/src/net/spdy/spdy_test_util_common.cc index 0dd996bd33..b776eec3d0 100644 --- a/naiveproxy/src/net/spdy/spdy_test_util_common.cc +++ b/naiveproxy/src/net/spdy/spdy_test_util_common.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 "net/spdy/spdy_test_util_common.h" #include @@ -25,6 +20,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "build/build_config.h" +#include "net/base/hash_value.h" #include "net/base/host_port_pair.h" #include "net/base/http_user_agent_settings.h" #include "net/base/proxy_delegate.h" @@ -92,17 +88,17 @@ void ParseUrl(std::string_view url, // Chop a frame into an array of MockWrites. // |frame| is the frame to chop. // |num_chunks| is the number of chunks to create. -std::unique_ptr ChopWriteFrame( - const spdy::SpdySerializedFrame& frame, - int num_chunks) { - auto chunks = std::make_unique(num_chunks); +std::vector ChopWriteFrame(const spdy::SpdySerializedFrame& frame, + int num_chunks) { + std::vector chunks(num_chunks); int chunk_size = frame.size() / num_chunks; + std::string_view frame_data(frame); for (int index = 0; index < num_chunks; index++) { - const char* ptr = frame.data() + (index * chunk_size); + int start = index * chunk_size; if (index == num_chunks - 1) chunk_size += frame.size() % chunk_size; // The last chunk takes the remainder. - chunks[index] = MockWrite(ASYNC, ptr, chunk_size); + chunks[index] = MockWrite(ASYNC, frame_data.substr(start, chunk_size)); } return chunks; } @@ -134,7 +130,7 @@ void AppendToHeaderBlock(base::span extra_headers, // Create a MockWrite from the given spdy::SpdySerializedFrame. MockWrite CreateMockWrite(const spdy::SpdySerializedFrame& req) { - return MockWrite(ASYNC, req.data(), req.size()); + return MockWrite(ASYNC, std::string_view(req)); } // Create a MockWrite from the given spdy::SpdySerializedFrame and sequence @@ -148,12 +144,12 @@ MockWrite CreateMockWrite(const spdy::SpdySerializedFrame& req, int seq) { MockWrite CreateMockWrite(const spdy::SpdySerializedFrame& req, int seq, IoMode mode) { - return MockWrite(mode, req.data(), req.size(), seq); + return MockWrite(mode, std::string_view(req), /*result=*/0, /*seq=*/seq); } // Create a MockRead from the given spdy::SpdySerializedFrame. MockRead CreateMockRead(const spdy::SpdySerializedFrame& resp) { - return MockRead(ASYNC, resp.data(), resp.size()); + return MockRead(ASYNC, std::string_view(resp)); } // Create a MockRead from the given spdy::SpdySerializedFrame and sequence @@ -167,7 +163,7 @@ MockRead CreateMockRead(const spdy::SpdySerializedFrame& resp, int seq) { MockRead CreateMockRead(const spdy::SpdySerializedFrame& resp, int seq, IoMode mode) { - return MockRead(mode, resp.data(), resp.size(), seq); + return MockRead(mode, std::string_view(resp), /*result=*/0, /*seq=*/seq); } // Combines the given vector of spdy::SpdySerializedFrame into a single frame. @@ -178,10 +174,11 @@ spdy::SpdySerializedFrame CombineFrames( total_size += frame->size(); } auto data = std::make_unique(total_size); - char* ptr = data.get(); + // SAFETY: We just allocated this buffer with size `total_size`. + // This is using a unique_ptr to interface with Quiche. + UNSAFE_BUFFERS(base::span out(data.get(), total_size)); for (const auto* frame : frames) { - memcpy(ptr, frame->data(), frame->size()); - ptr += frame->size(); + out.take_first(frame->size()).copy_from(std::string_view(*frame)); } return spdy::SpdySerializedFrame(std::move(data), total_size); } @@ -436,7 +433,7 @@ CreateSpdyTestURLRequestContextBuilder( bool HasSpdySession(SpdySessionPool* pool, const SpdySessionKey& key) { return static_cast(pool->FindAvailableSession( - key, /* enable_ip_based_pooling = */ true, + key, /* enable_ip_based_pooling_for_h2 = */ true, /* is_websocket = */ false, NetLogWithSource())); } @@ -446,9 +443,9 @@ base::WeakPtr CreateSpdySessionHelper( HttpNetworkSession* http_session, const SpdySessionKey& key, const NetLogWithSource& net_log, - bool enable_ip_based_pooling) { + bool enable_ip_based_pooling_for_h2) { EXPECT_FALSE(http_session->spdy_session_pool()->FindAvailableSession( - key, enable_ip_based_pooling, + key, enable_ip_based_pooling_for_h2, /*is_websocket=*/false, NetLogWithSource())); auto connection = std::make_unique(); @@ -496,7 +493,7 @@ base::WeakPtr CreateSpdySession(HttpNetworkSession* http_session, const SpdySessionKey& key, const NetLogWithSource& net_log) { return CreateSpdySessionHelper(http_session, key, net_log, - /* enable_ip_based_pooling = */ true); + /* enable_ip_based_pooling_for_h2 = */ true); } base::WeakPtr CreateSpdySessionWithIpBasedPoolingDisabled( @@ -504,7 +501,7 @@ base::WeakPtr CreateSpdySessionWithIpBasedPoolingDisabled( const SpdySessionKey& key, const NetLogWithSource& net_log) { return CreateSpdySessionHelper(http_session, key, net_log, - /* enable_ip_based_pooling = */ false); + /* enable_ip_based_pooling_for_h2 = */ false); } namespace { @@ -998,9 +995,9 @@ quiche::HttpHeaderBlock SpdyTestUtil::ConstructHeaderBlock( } namespace test { -HashValue GetTestHashValue(uint8_t label) { - HashValue hash_value(HASH_VALUE_SHA256); - std::ranges::fill(hash_value.span(), label); +SHA256HashValue GetTestHashValue(uint8_t label) { + SHA256HashValue hash_value; + std::ranges::fill(hash_value, label); return hash_value; } diff --git a/naiveproxy/src/net/spdy/spdy_test_util_common.h b/naiveproxy/src/net/spdy/spdy_test_util_common.h index 76f2d9af5d..a3e17c9572 100644 --- a/naiveproxy/src/net/spdy/spdy_test_util_common.h +++ b/naiveproxy/src/net/spdy/spdy_test_util_common.h @@ -48,7 +48,6 @@ class GURL; namespace net { class ClientSocketFactory; -class HashValue; class HostPortPair; class HostResolver; class QuicContext; @@ -74,9 +73,8 @@ const uint32_t kMaxHeaderListSizeForTest = 1024; // Chop a spdy::SpdySerializedFrame into an array of MockWrites. // |frame| is the frame to chop. // |num_chunks| is the number of chunks to create. -std::unique_ptr ChopWriteFrame( - const spdy::SpdySerializedFrame& frame, - int num_chunks); +std::vector ChopWriteFrame(const spdy::SpdySerializedFrame& frame, + int num_chunks); // Adds headers and values to a map. // |extra_headers| is an array of { name, value } pairs, arranged as strings @@ -496,8 +494,8 @@ class SpdyTestUtil { namespace test { -// Returns a SHA1 HashValue in which each byte has the value |label|. -HashValue GetTestHashValue(uint8_t label); +// Returns a SHA256HashValue in which each byte has the value |label|. +SHA256HashValue GetTestHashValue(uint8_t label); } // namespace test } // namespace net diff --git a/naiveproxy/src/net/ssl/client_cert_identity_test_util.cc b/naiveproxy/src/net/ssl/client_cert_identity_test_util.cc index ffe6efee73..71291bb7c2 100644 --- a/naiveproxy/src/net/ssl/client_cert_identity_test_util.cc +++ b/naiveproxy/src/net/ssl/client_cert_identity_test_util.cc @@ -9,11 +9,11 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" +#include "crypto/evp.h" #include "net/ssl/openssl_private_key.h" #include "net/ssl/ssl_private_key.h" #include "net/ssl/test_ssl_private_key.h" #include "net/test/cert_test_util.h" -#include "third_party/boringssl/src/include/openssl/bytestring.h" #include "third_party/boringssl/src/include/openssl/evp.h" namespace net { @@ -36,15 +36,16 @@ FakeClientCertIdentity::CreateFromCertAndKeyFiles( if (!cert) return nullptr; - std::string pkcs8; - if (!base::ReadFileToString(dir.AppendASCII(key_filename), &pkcs8)) + std::optional> pkcs8 = + base::ReadFileToBytes(dir.AppendASCII(key_filename)); + if (!pkcs8) { return nullptr; + } - CBS cbs; - CBS_init(&cbs, reinterpret_cast(pkcs8.data()), pkcs8.size()); - bssl::UniquePtr pkey(EVP_parse_private_key(&cbs)); - if (!pkey || CBS_len(&cbs) != 0) + bssl::UniquePtr pkey = crypto::evp::PrivateKeyFromBytes(*pkcs8); + if (!pkey) { return nullptr; + } scoped_refptr ssl_private_key = WrapOpenSSLPrivateKey(std::move(pkey)); diff --git a/naiveproxy/src/net/ssl/openssl_ssl_util.cc b/naiveproxy/src/net/ssl/openssl_ssl_util.cc index 5495559c15..214b43dd3e 100644 --- a/naiveproxy/src/net/ssl/openssl_ssl_util.cc +++ b/naiveproxy/src/net/ssl/openssl_ssl_util.cc @@ -6,9 +6,9 @@ #include +#include #include -#include "base/lazy_instance.h" #include "base/location.h" #include "base/logging.h" #include "base/notreached.h" @@ -49,11 +49,11 @@ class OpenSSLNetErrorLibSingleton { int net_error_lib_; }; -base::LazyInstance::Leaky g_openssl_net_error_lib = - LAZY_INSTANCE_INITIALIZER; - int OpenSSLNetErrorLib() { - return g_openssl_net_error_lib.Get().net_error_lib(); + static_assert( + std::is_trivially_destructible::value); + static OpenSSLNetErrorLibSingleton instance; + return instance.net_error_lib(); } int MapOpenSSLErrorSSL(uint32_t error_code) { @@ -229,91 +229,82 @@ int GetNetSSLVersion(SSL* ssl) { } } -bool SetSSLChainAndKey(SSL* ssl, - X509Certificate* cert, - EVP_PKEY* pkey, - const SSL_PRIVATE_KEY_METHOD* custom_key) { +std::vector GetCertChainRawVector(X509Certificate& cert) { std::vector chain_raw; - chain_raw.reserve(1 + cert->intermediate_buffers().size()); - chain_raw.push_back(cert->cert_buffer()); - for (const auto& handle : cert->intermediate_buffers()) + chain_raw.reserve(1 + cert.intermediate_buffers().size()); + chain_raw.push_back(cert.cert_buffer()); + for (const auto& handle : cert.intermediate_buffers()) { chain_raw.push_back(handle.get()); - - if (!SSL_set_chain_and_key(ssl, chain_raw.data(), chain_raw.size(), pkey, - custom_key)) { - LOG(WARNING) << "Failed to set client certificate"; - return false; } - - return true; + return chain_raw; } -bool ConfigureSSLCredential( - SSL* ssl, - base::span> cert_chain, - EVP_PKEY* pkey, - const SSL_PRIVATE_KEY_METHOD* custom_key, - base::span signing_algorithm_prefs, - base::span ocsp_response, - base::span signed_cert_timestamp_list, - base::span trust_anchor_id) { - bssl::UniquePtr credential(SSL_CREDENTIAL_new_x509()); - if (!credential) { - return false; - } - +std::vector GetCertChainRawVector( + const std::vector>& cert_chain) { std::vector chain_raw; chain_raw.reserve(cert_chain.size()); for (const auto& handle : cert_chain) { chain_raw.push_back(handle.get()); } + return chain_raw; +} - if (!SSL_CREDENTIAL_set1_cert_chain(credential.get(), chain_raw.data(), - chain_raw.size())) { +bool ConfigureSSLCredential(SSL* ssl, ConfigureSSLCredentialParams params) { + bssl::UniquePtr credential(SSL_CREDENTIAL_new_x509()); + if (!credential) { return false; } - if (!signing_algorithm_prefs.empty()) { + + if (!SSL_CREDENTIAL_set1_cert_chain(credential.get(), + params.cert_chain.data(), + params.cert_chain.size())) { + return false; + } + if (!params.signing_algorithm_prefs.empty()) { if (!SSL_CREDENTIAL_set1_signing_algorithm_prefs( - credential.get(), signing_algorithm_prefs.data(), - signing_algorithm_prefs.size())) { + credential.get(), params.signing_algorithm_prefs.data(), + params.signing_algorithm_prefs.size())) { return false; } } - DCHECK(pkey || custom_key); - if (pkey) { - DCHECK(!custom_key); + if (std::holds_alternative(params.private_key)) { + EVP_PKEY* pkey = std::get(params.private_key); + CHECK(pkey); if (!SSL_CREDENTIAL_set1_private_key(credential.get(), pkey)) { return false; } - } else if (custom_key) { - DCHECK(!pkey); + } else { + const SSL_PRIVATE_KEY_METHOD* custom_key = + std::get(params.private_key); + CHECK(custom_key); if (!SSL_CREDENTIAL_set_private_key_method(credential.get(), custom_key)) { return false; } } - if (!ocsp_response.empty()) { - bssl::UniquePtr buf( - CRYPTO_BUFFER_new(ocsp_response.data(), ocsp_response.size(), nullptr)); + if (!params.ocsp_response.empty()) { + bssl::UniquePtr buf(CRYPTO_BUFFER_new( + params.ocsp_response.data(), params.ocsp_response.size(), nullptr)); if (!SSL_CREDENTIAL_set1_ocsp_response(credential.get(), buf.get())) { return false; } } - if (!signed_cert_timestamp_list.empty()) { + if (!params.signed_cert_timestamp_list.empty()) { bssl::UniquePtr buf( - CRYPTO_BUFFER_new(signed_cert_timestamp_list.data(), - signed_cert_timestamp_list.size(), nullptr)); + CRYPTO_BUFFER_new(params.signed_cert_timestamp_list.data(), + params.signed_cert_timestamp_list.size(), nullptr)); if (!SSL_CREDENTIAL_set1_signed_cert_timestamp_list(credential.get(), buf.get())) { return false; } } - if (!trust_anchor_id.empty()) { - if (!SSL_CREDENTIAL_set1_trust_anchor_id( - credential.get(), trust_anchor_id.data(), trust_anchor_id.size())) { + if (!params.trust_anchor_id.empty()) { + if (!SSL_CREDENTIAL_set1_trust_anchor_id(credential.get(), + params.trust_anchor_id.data(), + params.trust_anchor_id.size())) { return false; } SSL_CREDENTIAL_set_must_match_issuer(credential.get(), 1); diff --git a/naiveproxy/src/net/ssl/openssl_ssl_util.h b/naiveproxy/src/net/ssl/openssl_ssl_util.h index 09bd5fd966..20eabaeb4c 100644 --- a/naiveproxy/src/net/ssl/openssl_ssl_util.h +++ b/naiveproxy/src/net/ssl/openssl_ssl_util.h @@ -7,6 +7,11 @@ #include +#include +#include + +#include "base/containers/span.h" +#include "base/memory/stack_allocated.h" #include "net/base/net_export.h" #include "net/cert/x509_certificate.h" #include "net/log/net_log_event_type.h" @@ -81,34 +86,44 @@ void NetLogOpenSSLError(const NetLogWithSource& net_log, // this SSL connection. int GetNetSSLVersion(SSL* ssl); -// Configures |ssl| to send the specified certificate and either |pkey| or -// |custom_key|. This is a wrapper over |SSL_set_chain_and_key|. -bool SetSSLChainAndKey(SSL* ssl, - X509Certificate* cert, - EVP_PKEY* pkey, - const SSL_PRIVATE_KEY_METHOD* custom_key); +// Returns a vector containing a pointer to the leaf certificate in `cert` +// followed by pointers to the intermediate certificates, suitable for passing +// via `ConfigureSSLCredentialParams`. +std::vector GetCertChainRawVector(X509Certificate& cert); -// Configures |ssl| to use the specified certificate and either |key| or -// |custom_key| as an available credential. This is a wrapper over -// |SSL_CREDENTIAL| APIs +// Converts `cert_chain` to a vector of raw pointers, suitable for passing via +// `ConfigureSSLCredentialParams`. +std::vector GetCertChainRawVector( + const std::vector>& cert_chain); + +// Holds params for `ConfigureSSLCredential()`. +struct ConfigureSSLCredentialParams { + STACK_ALLOCATED(); // Allow members to be spans instead of raw_spans. + public: + using PrivateKeyVariant = + std::variant; + + base::span cert_chain; + PrivateKeyVariant private_key; + base::span signing_algorithm_prefs; + base::span ocsp_response; + base::span signed_cert_timestamp_list; + base::span trust_anchor_id; +}; + +// Configures `ssl` to use the specified certificate and `params.private_key` +// as an available credential. This is a wrapper over |SSL_CREDENTIAL| APIs // (https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#Credentials). // -// |signing_algorithm_prefs|, |ocsp_response|, and |signed_cert_timestamp| are -// configured with the respective SSL_CREDENTIAL APIs if non-empty. +// |params.signing_algorithm_prefs|, |params.ocsp_response|, and +// |params.signed_cert_timestamp| are configured with the respective +// SSL_CREDENTIAL APIs if non-empty. // -// If |trust_anchor_id| is non-empty, it will be configured as the certificate's -// corresponding TLS Trust Anchor ID, and `SSL_CREDENTIAL_set_must_match_issuer` -// will be set to true +// If |params.trust_anchor_id| is non-empty, it will be configured as the +// certificate's corresponding TLS Trust Anchor ID, and +// `SSL_CREDENTIAL_set_must_match_issuer` will be set to true // (https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#SSL_CREDENTIAL_set_must_match_issuer). -bool ConfigureSSLCredential( - SSL* ssl, - base::span> cert_chain, - EVP_PKEY* pkey, - const SSL_PRIVATE_KEY_METHOD* custom_key, - base::span signing_algorithm_prefs, - base::span ocsp_response, - base::span signed_cert_timestamp_list, - base::span trust_anchor_id); +bool ConfigureSSLCredential(SSL* ssl, ConfigureSSLCredentialParams params); } // namespace net diff --git a/naiveproxy/src/net/ssl/ssl_info.h b/naiveproxy/src/net/ssl/ssl_info.h index c72d65262e..686ab12337 100644 --- a/naiveproxy/src/net/ssl/ssl_info.h +++ b/naiveproxy/src/net/ssl/ssl_info.h @@ -92,9 +92,11 @@ class NET_EXPORT SSLInfo { HandshakeType handshake_type = HANDSHAKE_UNKNOWN; - // The hashes, in several algorithms, of the SubjectPublicKeyInfos from - // each certificate in the chain. - HashValueVector public_key_hashes; + // If the certificate was successfully verified, contains the hashes of the + // SubjectPublicKeyInfo from each certificate in the verified chain. The + // ordering of the hashes matches the order of the verified chain (leaf to + // root). + std::vector public_key_hashes; // List of SignedCertificateTimestamps and their corresponding validation // status. diff --git a/naiveproxy/src/net/ssl/ssl_platform_key_mac.cc b/naiveproxy/src/net/ssl/ssl_platform_key_mac.cc index 0519f5bb02..e94f2ae5e7 100644 --- a/naiveproxy/src/net/ssl/ssl_platform_key_mac.cc +++ b/naiveproxy/src/net/ssl/ssl_platform_key_mac.cc @@ -28,6 +28,7 @@ #include "base/mac/mac_util.h" #include "base/memory/scoped_policy.h" #include "base/numerics/safe_conversions.h" +#include "crypto/evp.h" #include "crypto/openssl_util.h" #include "net/base/net_errors.h" #include "net/cert/x509_certificate.h" @@ -203,8 +204,8 @@ scoped_refptr CreateSSLPrivateKeyForSecKey( scoped_refptr WrapUnexportableKey( const crypto::UnexportableSigningKey& unexportable_key) { - bssl::UniquePtr pubkey = - ParseSpki(unexportable_key.GetSubjectPublicKeyInfo()); + bssl::UniquePtr pubkey = crypto::evp::PublicKeyFromBytes( + unexportable_key.GetSubjectPublicKeyInfo()); if (!pubkey) { return nullptr; } diff --git a/naiveproxy/src/net/ssl/ssl_platform_key_nss.cc b/naiveproxy/src/net/ssl/ssl_platform_key_nss.cc index b3fef19ea9..e80da54632 100644 --- a/naiveproxy/src/net/ssl/ssl_platform_key_nss.cc +++ b/naiveproxy/src/net/ssl/ssl_platform_key_nss.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 "net/ssl/ssl_platform_key_nss.h" #include @@ -18,6 +13,7 @@ #include #include +#include "base/compiler_specific.h" #include "base/logging.h" #include "base/strings/stringprintf.h" #include "base/threading/scoped_blocking_call.h" @@ -167,7 +163,8 @@ class SSLPlatformKeyNSS : public ThreadedSSLPrivateKey::Delegate { // Convert the RAW ECDSA signature to a DER-encoded ECDSA-Sig-Value. bssl::UniquePtr sig(ECDSA_SIG_new()); if (!sig || !BN_bin2bn(signature->data(), order_len, sig->r) || - !BN_bin2bn(signature->data() + order_len, order_len, sig->s)) { + !BN_bin2bn(UNSAFE_TODO(signature->data() + order_len), order_len, + sig->s)) { return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; } diff --git a/naiveproxy/src/net/ssl/ssl_platform_key_util.cc b/naiveproxy/src/net/ssl/ssl_platform_key_util.cc index bd9b89fe1c..987a2254cf 100644 --- a/naiveproxy/src/net/ssl/ssl_platform_key_util.cc +++ b/naiveproxy/src/net/ssl/ssl_platform_key_util.cc @@ -6,15 +6,15 @@ #include -#include "base/lazy_instance.h" #include "base/logging.h" +#include "base/no_destructor.h" #include "base/task/single_thread_task_runner.h" #include "base/threading/thread.h" +#include "crypto/evp.h" #include "crypto/openssl_util.h" #include "net/cert/asn1_util.h" #include "net/cert/x509_certificate.h" #include "net/cert/x509_util.h" -#include "third_party/boringssl/src/include/openssl/bytestring.h" #include "third_party/boringssl/src/include/openssl/ec_key.h" #include "third_party/boringssl/src/include/openssl/evp.h" #include "third_party/boringssl/src/include/openssl/rsa.h" @@ -44,13 +44,11 @@ class SSLPlatformKeyTaskRunner { base::Thread worker_thread_; }; -base::LazyInstance::Leaky g_platform_key_task_runner = - LAZY_INSTANCE_INITIALIZER; - } // namespace scoped_refptr GetSSLPlatformKeyTaskRunner() { - return g_platform_key_task_runner.Get().task_runner(); + static base::NoDestructor instance; + return instance->task_runner(); } bssl::UniquePtr GetClientCertPublicKey( @@ -65,7 +63,7 @@ bssl::UniquePtr GetClientCertPublicKey( return nullptr; } - return ParseSpki(base::as_byte_span(spki)); + return crypto::evp::PublicKeyFromBytes(base::as_byte_span(spki)); } bool GetClientCertInfo(const X509Certificate* certificate, @@ -81,21 +79,10 @@ bool GetClientCertInfo(const X509Certificate* certificate, return true; } -bssl::UniquePtr ParseSpki(base::span spki) { - CBS cbs; - CBS_init(&cbs, spki.data(), spki.size()); - bssl::UniquePtr key(EVP_parse_public_key(&cbs)); - if (!key || CBS_len(&cbs) != 0) { - LOG(ERROR) << "Could not parse public key."; - return nullptr; - } - return key; -} - bool GetPublicKeyInfo(base::span spki, int* out_type, size_t* out_max_length) { - auto key = ParseSpki(spki); + auto key = crypto::evp::PublicKeyFromBytes(spki); if (!key) { return false; } diff --git a/naiveproxy/src/net/ssl/ssl_private_key_test_util.cc b/naiveproxy/src/net/ssl/ssl_private_key_test_util.cc index 33e555a1b5..c74e6ea2be 100644 --- a/naiveproxy/src/net/ssl/ssl_private_key_test_util.cc +++ b/naiveproxy/src/net/ssl/ssl_private_key_test_util.cc @@ -12,12 +12,12 @@ #include "base/functional/bind.h" #include "base/location.h" #include "base/run_loop.h" +#include "crypto/evp.h" #include "crypto/openssl_util.h" #include "net/base/net_errors.h" #include "net/ssl/ssl_private_key.h" #include "net/test/gtest_util.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/boringssl/src/include/openssl/bytestring.h" #include "third_party/boringssl/src/include/openssl/digest.h" #include "third_party/boringssl/src/include/openssl/evp.h" #include "third_party/boringssl/src/include/openssl/rsa.h" @@ -75,15 +75,18 @@ Error DoKeySigningWithWrapper(SSLPrivateKey* key, } // namespace -void TestSSLPrivateKeyMatches(SSLPrivateKey* key, const std::string& pkcs8) { +void TestSSLPrivateKeyMatches(SSLPrivateKey* key, std::string_view pkcs8) { + TestSSLPrivateKeyMatches(key, base::as_byte_span(pkcs8)); +} + +void TestSSLPrivateKeyMatches(SSLPrivateKey* key, + base::span pkcs8) { crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); // Create the equivalent OpenSSL key. - CBS cbs; - CBS_init(&cbs, reinterpret_cast(pkcs8.data()), pkcs8.size()); - bssl::UniquePtr openssl_key(EVP_parse_private_key(&cbs)); + bssl::UniquePtr openssl_key = + crypto::evp::PrivateKeyFromBytes(pkcs8); ASSERT_TRUE(openssl_key); - EXPECT_EQ(0u, CBS_len(&cbs)); // Test all supported algorithms. std::vector preferences = key->GetAlgorithmPreferences(); diff --git a/naiveproxy/src/net/ssl/ssl_private_key_test_util.h b/naiveproxy/src/net/ssl/ssl_private_key_test_util.h index 6fb35fece2..1860daf047 100644 --- a/naiveproxy/src/net/ssl/ssl_private_key_test_util.h +++ b/naiveproxy/src/net/ssl/ssl_private_key_test_util.h @@ -7,6 +7,8 @@ #include +#include "base/containers/span.h" + namespace net { class SSLPrivateKey; @@ -15,7 +17,9 @@ class SSLPrivateKey; // reported type and key size are correct, and then it tests all advertised // signature algorithms align with |pkcs8|. It does not test unadvertised // algorithms, so the caller must check this list is as expected. -void TestSSLPrivateKeyMatches(SSLPrivateKey* key, const std::string& pkcs8); +void TestSSLPrivateKeyMatches(SSLPrivateKey* key, std::string_view pkcs8); +void TestSSLPrivateKeyMatches(SSLPrivateKey* key, + base::span pkcs8); } // namespace net diff --git a/naiveproxy/src/net/ssl/test_ssl_private_key.cc b/naiveproxy/src/net/ssl/test_ssl_private_key.cc index 2439efcf93..62c39ec2ad 100644 --- a/naiveproxy/src/net/ssl/test_ssl_private_key.cc +++ b/naiveproxy/src/net/ssl/test_ssl_private_key.cc @@ -10,7 +10,6 @@ #include "base/containers/contains.h" #include "base/containers/to_vector.h" #include "base/task/sequenced_task_runner.h" -#include "crypto/rsa_private_key.h" #include "net/base/net_errors.h" #include "net/ssl/openssl_private_key.h" #include "net/ssl/ssl_platform_key_util.h" @@ -81,11 +80,6 @@ class SSLPrivateKeyWithPreferences : public SSLPrivateKey { } // namespace -scoped_refptr WrapRSAPrivateKey( - crypto::RSAPrivateKey* rsa_private_key) { - return net::WrapOpenSSLPrivateKey(bssl::UpRef(rsa_private_key->key())); -} - scoped_refptr CreateFailSigningSSLPrivateKey() { return base::MakeRefCounted( std::make_unique(), GetSSLPlatformKeyTaskRunner()); diff --git a/naiveproxy/src/net/ssl/test_ssl_private_key.h b/naiveproxy/src/net/ssl/test_ssl_private_key.h index 0a3106f669..08d7921443 100644 --- a/naiveproxy/src/net/ssl/test_ssl_private_key.h +++ b/naiveproxy/src/net/ssl/test_ssl_private_key.h @@ -8,19 +8,10 @@ #include "base/containers/span.h" #include "base/memory/scoped_refptr.h" -namespace crypto { -class RSAPrivateKey; -} - namespace net { class SSLPrivateKey; -// Returns a new `SSLPrivateKey` which uses `rsa_private_key` for signing -// operations or `nullptr` on error. -scoped_refptr WrapRSAPrivateKey( - crypto::RSAPrivateKey* rsa_private_key); - // Returns a new `SSLPrivateKey` which fails all signing operations. scoped_refptr CreateFailSigningSSLPrivateKey(); diff --git a/naiveproxy/src/net/test/android/javatests/AndroidManifest.xml b/naiveproxy/src/net/test/android/javatests/AndroidManifest.xml index ba095c8151..faea3df9ef 100644 --- a/naiveproxy/src/net/test/android/javatests/AndroidManifest.xml +++ b/naiveproxy/src/net/test/android/javatests/AndroidManifest.xml @@ -14,16 +14,7 @@ - diff --git a/naiveproxy/src/net/test/android/net_test_jni_onload.cc b/naiveproxy/src/net/test/android/net_test_jni_onload.cc index 49d1d3d198..63152b855b 100644 --- a/naiveproxy/src/net/test/android/net_test_jni_onload.cc +++ b/naiveproxy/src/net/test/android/net_test_jni_onload.cc @@ -4,7 +4,7 @@ #include "net/test/android/net_test_jni_onload.h" -#include "base/android/base_jni_onload.h" +#include "base/android/base_jni_init.h" #include "base/android/jni_android.h" #include "base/functional/bind.h" #include "net/test/embedded_test_server/android/embedded_test_server_android.h" diff --git a/naiveproxy/src/net/test/cert_builder.cc b/naiveproxy/src/net/test/cert_builder.cc index 6d5b897e88..60dd10dc20 100644 --- a/naiveproxy/src/net/test/cert_builder.cc +++ b/naiveproxy/src/net/test/cert_builder.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 "net/test/cert_builder.h" #include @@ -18,6 +13,7 @@ #include #include +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/files/file_path.h" #include "base/memory/ptr_util.h" @@ -26,6 +22,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/time/time.h" +#include "crypto/evp.h" #include "crypto/hash.h" #include "crypto/keypair.h" #include "net/cert/asn1_util.h" @@ -128,7 +125,7 @@ std::vector FinishCBBToVector(CBB* cbb) { } bssl::UniquePtr delete_bytes(cbb_bytes); - return std::vector(cbb_bytes, cbb_bytes + cbb_len); + return std::vector(cbb_bytes, UNSAFE_TODO(cbb_bytes + cbb_len)); } } // namespace @@ -215,13 +212,10 @@ std::unique_ptr CertBuilder::FromSubjectPublicKeyInfo( DCHECK(issuer); auto builder = std::make_unique(/*orig_cert=*/nullptr, issuer); - CBS cbs; - CBS_init(&cbs, spki_der.data(), spki_der.size()); - builder->key_ = bssl::UniquePtr(EVP_parse_public_key(&cbs)); - // Check that there was no error in `EVP_parse_public_key` and that it - // consumed the entire public key. - if (!builder->key_ || (CBS_len(&cbs) != 0)) + builder->key_ = crypto::evp::PublicKeyFromBytes(spki_der); + if (!builder->key_) { return nullptr; + } return builder; } @@ -1412,12 +1406,9 @@ void CertBuilder::BuildSctListExtension(const std::string& pre_tbs_certificate, for (const SctConfig& sct_config : sct_configs_) { ct::SignedEntryData entry; entry.type = ct::SignedEntryData::LOG_ENTRY_TYPE_PRECERT; - bssl::ScopedCBB issuer_spki_cbb; - ASSERT_TRUE(CBB_init(issuer_spki_cbb.get(), 32)); - ASSERT_TRUE( - EVP_marshal_public_key(issuer_spki_cbb.get(), issuer_->GetKey())); - entry.issuer_key_hash = crypto::hash::Sha256( - base::as_byte_span(FinishCBB(issuer_spki_cbb.get()))); + std::vector issuer_spki = + crypto::evp::PublicKeyToBytes(issuer_->GetKey()); + entry.issuer_key_hash = crypto::hash::Sha256(issuer_spki); entry.tbs_certificate = pre_tbs_certificate; std::string serialized_log_entry; diff --git a/naiveproxy/src/net/test/cert_test_util_nss.cc b/naiveproxy/src/net/test/cert_test_util_nss.cc index 2c4f08cabb..5cd121ed8c 100644 --- a/naiveproxy/src/net/test/cert_test_util_nss.cc +++ b/naiveproxy/src/net/test/cert_test_util_nss.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 "net/test/cert_test_util.h" #include @@ -18,6 +13,7 @@ #include #include +#include "base/compiler_specific.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/logging.h" @@ -55,7 +51,7 @@ bool IsKnownRoot(CERTCertificate* root) { for (const SECMODModuleList* item = SECMOD_GetDefaultModuleList(); item != nullptr; item = item->next) { for (int i = 0; i < item->module->slotCount; ++i) { - PK11SlotInfo* slot = item->module->slots[i]; + PK11SlotInfo* slot = UNSAFE_TODO(item->module->slots[i]); if (PK11_IsPresent(slot) && PK11_HasRootCerts(slot)) { CK_OBJECT_HANDLE handle = PK11_FindCertInSlot(slot, root, nullptr); if (handle != CK_INVALID_HANDLE && @@ -97,7 +93,7 @@ crypto::ScopedPK11Slot GetNssBuiltInRootCertsSlot() { for (SECMODModuleList* item = head; item != nullptr; item = item->next) { int slot_count = item->module->loaded ? item->module->slotCount : 0; for (int i = 0; i < slot_count; i++) { - PK11SlotInfo* slot = item->module->slots[i]; + PK11SlotInfo* slot = UNSAFE_TODO(item->module->slots[i]); if (IsNssBuiltInRootSlot(slot)) { return crypto::ScopedPK11Slot(PK11_ReferenceSlot(slot)); } diff --git a/naiveproxy/src/net/test/ct_test_util.cc b/naiveproxy/src/net/test/ct_test_util.cc index 0833c9666b..74da91a102 100644 --- a/naiveproxy/src/net/test/ct_test_util.cc +++ b/naiveproxy/src/net/test/ct_test_util.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/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "net/test/ct_test_util.h" #include @@ -16,6 +11,7 @@ #include #include "base/base64.h" +#include "base/compiler_specific.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" @@ -275,7 +271,8 @@ bool GetSampleSignedTreeHead(SignedTreeHead* sth) { sth->timestamp = base::Time::UnixEpoch() + base::Milliseconds(kTestTimestamp); sth->tree_size = kSampleSTHTreeSize; std::string sha256_root_hash = GetSampleSTHSHA256RootHash(); - memcpy(sth->sha256_root_hash, sha256_root_hash.c_str(), kSthRootHashLength); + UNSAFE_TODO(memcpy(sth->sha256_root_hash, sha256_root_hash.c_str(), + kSthRootHashLength)); sth->log_id = GetTestPublicKeyId(); return GetSampleSTHTreeHeadDecodedSignature(&(sth->signature)); @@ -288,7 +285,8 @@ bool GetSampleEmptySignedTreeHead(SignedTreeHead* sth) { sth->tree_size = 0; std::string empty_root_hash = HexDecode( "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); - memcpy(sth->sha256_root_hash, empty_root_hash.c_str(), kSthRootHashLength); + UNSAFE_TODO(memcpy(sth->sha256_root_hash, empty_root_hash.c_str(), + kSthRootHashLength)); sth->log_id = GetTestPublicKeyId(); std::string tree_head_signature = HexDecode( @@ -304,7 +302,7 @@ bool GetBadEmptySignedTreeHead(SignedTreeHead* sth) { sth->timestamp = base::Time::UnixEpoch() + base::Milliseconds(INT64_C(1450870952897)); sth->tree_size = 0; - memset(sth->sha256_root_hash, 'f', kSthRootHashLength); + UNSAFE_TODO(memset(sth->sha256_root_hash, 'f', kSthRootHashLength)); sth->log_id = GetTestPublicKeyId(); std::string tree_head_signature = HexDecode( diff --git a/naiveproxy/src/net/test/embedded_test_server/android/embedded_test_server_android.cc b/naiveproxy/src/net/test/embedded_test_server/android/embedded_test_server_android.cc index c3db041b8a..7ad04c8de9 100644 --- a/naiveproxy/src/net/test/embedded_test_server/android/embedded_test_server_android.cc +++ b/naiveproxy/src/net/test/embedded_test_server/android/embedded_test_server_android.cc @@ -10,7 +10,7 @@ #include "base/files/file_path.h" #include "base/functional/bind.h" #include "base/test/test_support_android.h" -#include "net/base/tracing.h" +#include "base/trace_event/trace_event.h" // Must come after all headers that specialize FromJniType() / ToJniType(). #include "net/android/net_test_support_provider_jni/EmbeddedTestServerImpl_jni.h" diff --git a/naiveproxy/src/net/test/embedded_test_server/controllable_http_response.cc b/naiveproxy/src/net/test/embedded_test_server/controllable_http_response.cc index 19db67e5f1..3585bbeee8 100644 --- a/naiveproxy/src/net/test/embedded_test_server/controllable_http_response.cc +++ b/naiveproxy/src/net/test/embedded_test_server/controllable_http_response.cc @@ -8,7 +8,7 @@ #include "base/functional/bind.h" #include "base/strings/stringprintf.h" #include "base/task/single_thread_task_runner.h" -#include "net/base/tracing.h" +#include "base/trace_event/trace_event.h" #include "net/test/embedded_test_server/http_response.h" namespace net::test_server { diff --git a/naiveproxy/src/net/test/embedded_test_server/create_websocket_handler.cc b/naiveproxy/src/net/test/embedded_test_server/create_websocket_handler.cc index 96af1ea803..fda0d0760d 100644 --- a/naiveproxy/src/net/test/embedded_test_server/create_websocket_handler.cc +++ b/naiveproxy/src/net/test/embedded_test_server/create_websocket_handler.cc @@ -36,8 +36,8 @@ std::unique_ptr MakeErrorResponse(HttpStatusCode code, auto error_response = std::make_unique(); error_response->set_code(code); error_response->set_content(content); - DVLOG(3) << "Error response created. Code: " << static_cast(code) - << ", Content: " << content; + VLOG(3) << "Error response created. Code: " << static_cast(code) + << ", Content: " << content; return error_response; } @@ -47,7 +47,7 @@ EmbeddedTestServer::UpgradeResultOrHttpResponse HandleWebSocketUpgrade( EmbeddedTestServer* server, const HttpRequest& request, HttpConnection* connection) { - DVLOG(3) << "Handling WebSocket upgrade for path: " << handle_path; + VLOG(3) << "Handling WebSocket upgrade for path: " << handle_path; std::string_view request_path = StripQuery(request.relative_url); @@ -66,14 +66,14 @@ EmbeddedTestServer::UpgradeResultOrHttpResponse HandleWebSocketUpgrade( auto host_header = request.headers.find("Host"); if (host_header == request.headers.end()) { - DVLOG(1) << "Host header is missing."; + VLOG(1) << "Host header is missing."; return base::unexpected(MakeErrorResponse(HttpStatusCode::HTTP_BAD_REQUEST, "Host header is missing.")); } HostPortPair host_port = HostPortPair::FromString(host_header->second); if (!IsCanonicalizedHostCompliant(host_port.host())) { - DVLOG(1) << "Host header is invalid: " << host_port.host(); + VLOG(1) << "Host header is invalid: " << host_port.host(); return base::unexpected(MakeErrorResponse(HttpStatusCode::HTTP_BAD_REQUEST, "Host header is invalid.")); } @@ -81,8 +81,8 @@ EmbeddedTestServer::UpgradeResultOrHttpResponse HandleWebSocketUpgrade( auto upgrade_header = request.headers.find("Upgrade"); if (upgrade_header == request.headers.end() || !base::EqualsCaseInsensitiveASCII(upgrade_header->second, "websocket")) { - DVLOG(1) << "Upgrade header is missing or invalid: " - << upgrade_header->second; + VLOG(1) << "Upgrade header is missing or invalid: " + << upgrade_header->second; return base::unexpected( MakeErrorResponse(HttpStatusCode::HTTP_BAD_REQUEST, "Upgrade header is missing or invalid.")); @@ -90,7 +90,7 @@ EmbeddedTestServer::UpgradeResultOrHttpResponse HandleWebSocketUpgrade( auto connection_header = request.headers.find("Connection"); if (connection_header == request.headers.end()) { - DVLOG(1) << "Connection header is missing."; + VLOG(1) << "Connection header is missing."; return base::unexpected(MakeErrorResponse(HttpStatusCode::HTTP_BAD_REQUEST, "Connection header is missing.")); } @@ -101,8 +101,8 @@ EmbeddedTestServer::UpgradeResultOrHttpResponse HandleWebSocketUpgrade( if (!std::ranges::any_of(tokens, [](std::string_view token) { return base::EqualsCaseInsensitiveASCII(token, "Upgrade"); })) { - DVLOG(1) << "Connection header does not contain 'Upgrade'. Tokens: " - << connection_header->second; + VLOG(1) << "Connection header does not contain 'Upgrade'. Tokens: " + << connection_header->second; return base::unexpected( MakeErrorResponse(HttpStatusCode::HTTP_BAD_REQUEST, "Connection header does not contain 'Upgrade'.")); @@ -111,15 +111,15 @@ EmbeddedTestServer::UpgradeResultOrHttpResponse HandleWebSocketUpgrade( auto websocket_version_header = request.headers.find("Sec-WebSocket-Version"); if (websocket_version_header == request.headers.end() || websocket_version_header->second != "13") { - DVLOG(1) << "Invalid or missing Sec-WebSocket-Version: " - << websocket_version_header->second; + VLOG(1) << "Invalid or missing Sec-WebSocket-Version: " + << websocket_version_header->second; return base::unexpected(MakeErrorResponse( HttpStatusCode::HTTP_BAD_REQUEST, "Sec-WebSocket-Version must be 13.")); } auto sec_websocket_key_iter = request.headers.find("Sec-WebSocket-Key"); if (sec_websocket_key_iter == request.headers.end()) { - DVLOG(1) << "Sec-WebSocket-Key header is missing."; + VLOG(1) << "Sec-WebSocket-Key header is missing."; return base::unexpected( MakeErrorResponse(HttpStatusCode::HTTP_BAD_REQUEST, "Sec-WebSocket-Key header is missing.")); @@ -127,7 +127,7 @@ EmbeddedTestServer::UpgradeResultOrHttpResponse HandleWebSocketUpgrade( auto decoded = base::Base64Decode(sec_websocket_key_iter->second); if (!decoded || decoded->size() != 16) { - DVLOG(1) << "Sec-WebSocket-Key is invalid or has incorrect length."; + VLOG(1) << "Sec-WebSocket-Key is invalid or has incorrect length."; return base::unexpected(MakeErrorResponse( HttpStatusCode::HTTP_BAD_REQUEST, "Sec-WebSocket-Key is invalid or has incorrect length.")); diff --git a/naiveproxy/src/net/test/embedded_test_server/default_handlers.cc b/naiveproxy/src/net/test/embedded_test_server/default_handlers.cc index d720ef8418..f46cfda6fb 100644 --- a/naiveproxy/src/net/test/embedded_test_server/default_handlers.cc +++ b/naiveproxy/src/net/test/embedded_test_server/default_handlers.cc @@ -19,7 +19,6 @@ #include "base/functional/bind.h" #include "base/functional/callback_forward.h" #include "base/functional/callback_helpers.h" -#include "base/hash/md5.h" #include "base/logging.h" #include "base/memory/weak_ptr.h" #include "base/path_service.h" @@ -33,6 +32,7 @@ #include "base/task/single_thread_task_runner.h" #include "base/time/time.h" #include "base/unguessable_token.h" +#include "crypto/hash.h" #include "net/base/host_port_pair.h" #include "net/base/url_util.h" #include "net/filter/filter_source_stream_test_util.h" @@ -538,12 +538,16 @@ std::unique_ptr HandleAuthBasic(const HttpRequest& request) { return http_response; } +std::string Sha256String(std::string_view input) { + return base::ToLowerASCII(base::HexEncode(crypto::hash::Sha256(input))); +} + // /auth-digest // Performs "Digest" HTTP authentication. std::unique_ptr HandleAuthDigest(const HttpRequest& request) { - std::string nonce = base::MD5String( + std::string nonce = Sha256String( base::StringPrintf("privatekey%s", request.relative_url.c_str())); - std::string opaque = base::MD5String("opaque"); + std::string opaque = Sha256String("opaque"); std::string password = kDefaultPassword; std::string realm = kDefaultRealm; @@ -582,22 +586,22 @@ std::unique_ptr HandleAuthDigest(const HttpRequest& request) { } else { username = auth_pairs["username"]; - std::string hash1 = base::MD5String( + std::string hash1 = Sha256String( base::StringPrintf("%s:%s:%s", auth_pairs["username"].c_str(), realm.c_str(), password.c_str())); - std::string hash2 = base::MD5String(base::StringPrintf( + std::string hash2 = Sha256String(base::StringPrintf( "%s:%s", request.method_string.c_str(), auth_pairs["uri"].c_str())); std::string response; if (auth_pairs.find("qop") != auth_pairs.end() && auth_pairs.find("nc") != auth_pairs.end() && auth_pairs.find("cnonce") != auth_pairs.end()) { - response = base::MD5String(base::StringPrintf( + response = Sha256String(base::StringPrintf( "%s:%s:%s:%s:%s:%s", hash1.c_str(), nonce.c_str(), auth_pairs["nc"].c_str(), auth_pairs["cnonce"].c_str(), auth_pairs["qop"].c_str(), hash2.c_str())); } else { - response = base::MD5String(base::StringPrintf( + response = Sha256String(base::StringPrintf( "%s:%s:%s", hash1.c_str(), nonce.c_str(), hash2.c_str())); } @@ -614,7 +618,7 @@ std::unique_ptr HandleAuthDigest(const HttpRequest& request) { http_response->set_content_type("text/html"); std::string auth_header = base::StringPrintf( "Digest realm=\"%s\", " - "domain=\"/\", qop=\"auth\", algorithm=MD5, nonce=\"%s\", " + "domain=\"/\", qop=\"auth\", algorithm=SHA-256, nonce=\"%s\", " "opaque=\"%s\"", realm.c_str(), nonce.c_str(), opaque.c_str()); http_response->AddCustomHeader("WWW-Authenticate", auth_header); diff --git a/naiveproxy/src/net/test/embedded_test_server/embedded_test_server.cc b/naiveproxy/src/net/test/embedded_test_server/embedded_test_server.cc index d8be8ad437..80d0f7c615 100644 --- a/naiveproxy/src/net/test/embedded_test_server/embedded_test_server.cc +++ b/naiveproxy/src/net/test/embedded_test_server/embedded_test_server.cc @@ -11,6 +11,7 @@ #include #include +#include "base/containers/span.h" #include "base/files/file_path.h" #include "base/functional/bind.h" #include "base/functional/callback_forward.h" @@ -343,8 +344,8 @@ bool EmbeddedTestServer::InitializeAndListen(int port, do { if (++num_tries > max_tries) { - DVLOG(1) << "Failed to listen on a valid port after " << max_tries - << " attempts."; + LOG(ERROR) << "Failed to listen on a valid port after " << max_tries + << " attempts."; listen_socket_.reset(); return false; } @@ -354,14 +355,14 @@ bool EmbeddedTestServer::InitializeAndListen(int port, int result = listen_socket_->ListenWithAddressAndPort(address.data(), port, 10); if (result) { - DVLOG(1) << "Listen failed: " << ErrorToString(result); + LOG(ERROR) << "Listen failed: " << ErrorToString(result); listen_socket_.reset(); return false; } result = listen_socket_->GetLocalAddress(&local_endpoint_); if (result != OK) { - DVLOG(1) << "GetLocalAddress failed: " << ErrorToString(result); + LOG(ERROR) << "GetLocalAddress failed: " << ErrorToString(result); listen_socket_.reset(); return false; } @@ -384,7 +385,7 @@ bool EmbeddedTestServer::InitializeAndListen(int port, listen_socket_->DetachFromThread(); if (is_using_ssl_ && !InitializeSSLServerContext()) { - DVLOG(1) << "Unable to initialize SSL"; + LOG(ERROR) << "Unable to initialize SSL"; return false; } @@ -582,12 +583,12 @@ bool EmbeddedTestServer::GenerateCertAndKey() { bool EmbeddedTestServer::InitializeSSLServerContext() { if (UsingStaticCert()) { if (!InitializeCertAndKeyFromFile()) { - DVLOG(1) << "Unable to initialize cert and key from file"; + LOG(ERROR) << "Unable to initialize cert and key from file"; return false; } } else { if (!GenerateCertAndKey()) { - DVLOG(1) << "Unable to generate cert and key"; + LOG(ERROR) << "Unable to generate cert and key"; return false; } } @@ -749,7 +750,7 @@ void EmbeddedTestServer::HandleRequest( } } - if (http_connect_proxy_handler_) { + if (http_connect_proxy_handler_ && request->method == METHOD_CONNECT) { bool request_handled = http_connect_proxy_handler_->HandleProxyRequest(*connection, *request); // If the proxy handler took over the request, it took ownership of the @@ -758,6 +759,12 @@ void EmbeddedTestServer::HandleRequest( connections_.erase(socket); return; } + + auto response = std::make_unique(); + response->set_code(HttpStatusCode::HTTP_BAD_GATEWAY); + response->set_reason("Invalid destination"); + DispatchResponseToDelegate(std::move(response), delegate); + return; } for (const auto& upgrade_request_handler : upgrade_request_handlers_) { @@ -791,7 +798,7 @@ void EmbeddedTestServer::HandleRequest( } if (!response) { - DVLOG(2) << "Request not handled. Returning 404: " << request->relative_url; + VLOG(2) << "Request not handled. Returning 404: " << request->relative_url; auto not_found_response = std::make_unique(); not_found_response->set_code(HTTP_NOT_FOUND); response = std::move(not_found_response); @@ -985,19 +992,18 @@ void EmbeddedTestServer::RegisterAuthHandler( CHECK(!io_thread_) << "Handlers must be registered before starting the server."; if (auth_handler_) { - DVLOG(2) << "Overwriting existing Auth handler."; + VLOG(2) << "Overwriting existing Auth handler."; } auth_handler_ = callback; } void EmbeddedTestServer::EnableConnectProxy( - uint16_t dest_port, - std::optional expected_dest) { + base::span proxied_destinations) { CHECK(!StartedAcceptingConnection()); CHECK(!http_connect_proxy_handler_); - http_connect_proxy_handler_ = std::make_unique( - dest_port, std::move(expected_dest)); + http_connect_proxy_handler_ = + std::make_unique(proxied_destinations); } void EmbeddedTestServer::RegisterUpgradeRequestHandler( diff --git a/naiveproxy/src/net/test/embedded_test_server/embedded_test_server.h b/naiveproxy/src/net/test/embedded_test_server/embedded_test_server.h index f2e45772fc..be088a375c 100644 --- a/naiveproxy/src/net/test/embedded_test_server/embedded_test_server.h +++ b/naiveproxy/src/net/test/embedded_test_server/embedded_test_server.h @@ -15,6 +15,7 @@ #include #include "base/callback_list.h" +#include "base/containers/span.h" #include "base/files/file_path.h" #include "base/functional/callback.h" #include "base/functional/callback_forward.h" @@ -567,14 +568,12 @@ class EmbeddedTestServer { // Makes the server act as an HTTP/HTTPS CONNECT proxy. Must be invoked before // the server is fully started. Only supports HTTP/1.x. All CONNECT requests - // go to `dest_port` on localhost, regardless of what destination is actually - // provided. `expected_dest`, if provided, is the expected destination of all - // requests. CONNECT requests to other destinations will then result in test - // failures. + // to a port in `dest_ports` are go to the matching port on localhost, + // regardless of what destination host is actually provided. CONNECT requests + // to other destinations will then result 502 responses. // // Must be called before the EmbeddedTestServer starts accepting connections. - void EnableConnectProxy(uint16_t dest_port, - std::optional expected_dest); + void EnableConnectProxy(base::span proxied_destinations); // Adds a handler callback to process WebSocket upgrade requests. // |callback| will be invoked on the server's IO thread when a request diff --git a/naiveproxy/src/net/test/embedded_test_server/http_connect_proxy_handler.cc b/naiveproxy/src/net/test/embedded_test_server/http_connect_proxy_handler.cc index 1568c44652..4d6051467e 100644 --- a/naiveproxy/src/net/test/embedded_test_server/http_connect_proxy_handler.cc +++ b/naiveproxy/src/net/test/embedded_test_server/http_connect_proxy_handler.cc @@ -11,6 +11,8 @@ #include #include "base/check_op.h" +#include "base/containers/flat_set.h" +#include "base/containers/span.h" #include "base/containers/unique_ptr_adapters.h" #include "base/functional/bind.h" #include "base/location.h" @@ -68,7 +70,7 @@ class HttpConnectProxyHandler::ConnectTunnel { // If unable to connect, write a bad gateway error to `socket_` before // deleting `this`. if (result != OK) { - DVLOG(1) << "Failed to establish tunnel connection."; + VLOG(1) << "Failed to establish tunnel connection."; BasicHttpResponse response; response.set_code(HttpStatusCode::HTTP_BAD_GATEWAY); @@ -223,20 +225,17 @@ class HttpConnectProxyHandler::ConnectTunnel { }; HttpConnectProxyHandler::HttpConnectProxyHandler( - const uint16_t dest_port, - std::optional expected_dest) - : dest_port_(dest_port), expected_dest_(expected_dest) {} + base::span proxied_destinations) + : proxied_destinations_(proxied_destinations.begin(), + proxied_destinations.end()) {} HttpConnectProxyHandler::~HttpConnectProxyHandler() = default; bool HttpConnectProxyHandler::HandleProxyRequest(HttpConnection& connection, const HttpRequest& request) { - // This class only support HTTP/1.x. + // This class only supports HTTP/1.x. CHECK_EQ(connection.protocol(), HttpConnection::Protocol::kHttp1); - - if (request.method != METHOD_CONNECT) { - return false; - } + CHECK_EQ(request.method, METHOD_CONNECT); // For CONNECT requests, `relative_url` is actually a host and port. HostPortPair dest = HostPortPair::FromString(request.relative_url); @@ -244,18 +243,19 @@ bool HttpConnectProxyHandler::HandleProxyRequest(HttpConnection& connection, if (dest.IsEmpty()) { ADD_FAILURE() << "Invalid CONNECT destination: " << request.relative_url; - // Returning true on error will result in the socket being closed. - return true; + // Returning true on error will result in an HTTP error message being + // written to the socket. + return false; } - if (expected_dest_ && *expected_dest_ != dest) { - ADD_FAILURE() << "Unexpected CONNECT destination: " << dest.ToString(); - // Returning true on error will result in the socket being closed. - return true; + if (!proxied_destinations_.contains(dest)) { + // Returning true on error will result in an HTTP error message being + // written to the socket. + return false; } auto tunnel = std::make_unique(this, connection.TakeSocket()); auto tunnel_it = connect_tunnels_.insert(std::move(tunnel)).first; - (*tunnel_it)->Start(dest_port_); + (*tunnel_it)->Start(dest.port()); return true; } diff --git a/naiveproxy/src/net/test/embedded_test_server/http_connect_proxy_handler.h b/naiveproxy/src/net/test/embedded_test_server/http_connect_proxy_handler.h index 536f0c4c10..e950a2bef7 100644 --- a/naiveproxy/src/net/test/embedded_test_server/http_connect_proxy_handler.h +++ b/naiveproxy/src/net/test/embedded_test_server/http_connect_proxy_handler.h @@ -5,12 +5,12 @@ #ifndef NET_TEST_EMBEDDED_TEST_SERVER_HTTP_CONNECT_PROXY_HANDLER_H_ #define NET_TEST_EMBEDDED_TEST_SERVER_HTTP_CONNECT_PROXY_HANDLER_H_ -#include - #include #include #include +#include "base/containers/flat_set.h" +#include "base/containers/span.h" #include "base/containers/unique_ptr_adapters.h" #include "net/base/host_port_pair.h" @@ -20,25 +20,27 @@ class HttpConnection; struct HttpRequest; // Helper for use by the EmbeddedTestServer to act as an HTTP proxy. Only -// supports HTTP/1.x CONNECT requests. +// supports HTTP/1.x CONNECT requests. Non-CONNECT requests can be simulated +// without a proxy, if needed. class HttpConnectProxyHandler { public: - // Regardless of the requested destination, all requests are proxied to - // `dest_port` on 127.0.0.1. If provided, connections to destinations other - // than `expected_dest` result in test expectation failures. - HttpConnectProxyHandler(uint16_t dest_port, - std::optional expected_dest); + // Only CONNECT requests to destinations in proxied_destinations will be + // proxied. All others result in 502 errors. CONNECT requests are all + // connected to 127.0.0.1: where `port` is the destination port of the + // requested destination. + explicit HttpConnectProxyHandler( + base::span proxied_destinations); ~HttpConnectProxyHandler(); - // If `request` is not a CONNECT request, returns false. Otherwise, takes - // ownership of the socket owned by `connection`, validates the destination, - // connects to the real destination location, writes an HTTP success message - // to the original socket, and starts tunnelling data between the two sockets. + // `request` must be a CONNECT request. Returns false if the request is not a + // valid CONNECT request or is to a destination in `dest_ports`. In the former + // case, adds a gtest failure as well. // - // Logs on connection failures, but does not fail the test. + // If true is returned, takes ownership of the underlying socket, and attempts + // to establish an HTTP/1.x tunnel between that socket and the destination + // port on localost. // - // Only supports CONNECT requests. Non-CONNECT requests can be simulated - // without a proxy, if needed. + // Write an error to the socket and logs on connection failures. bool HandleProxyRequest(HttpConnection& connection, const HttpRequest& request); @@ -47,8 +49,7 @@ class HttpConnectProxyHandler { void DeleteTunnel(ConnectTunnel* tunnel); - const uint16_t dest_port_; - const std::optional expected_dest_; + const base::flat_set proxied_destinations_; std::set, base::UniquePtrComparator> connect_tunnels_; diff --git a/naiveproxy/src/net/test/embedded_test_server/install_default_websocket_handlers.cc b/naiveproxy/src/net/test/embedded_test_server/install_default_websocket_handlers.cc index c3af426e72..6850185fef 100644 --- a/naiveproxy/src/net/test/embedded_test_server/install_default_websocket_handlers.cc +++ b/naiveproxy/src/net/test/embedded_test_server/install_default_websocket_handlers.cc @@ -7,40 +7,28 @@ #include #include "base/check.h" -#include "base/path_service.h" #include "net/test/embedded_test_server/create_websocket_handler.h" #include "net/test/embedded_test_server/websocket_check_origin_handler.h" #include "net/test/embedded_test_server/websocket_close_handler.h" +#include "net/test/embedded_test_server/websocket_close_immediately_handler.h" #include "net/test/embedded_test_server/websocket_close_observer_handler.h" #include "net/test/embedded_test_server/websocket_echo_handler.h" #include "net/test/embedded_test_server/websocket_echo_request_headers_handler.h" +#include "net/test/embedded_test_server/websocket_set_hsts_handler.h" #include "net/test/embedded_test_server/websocket_split_packet_close_handler.h" -#include "net/test/test_data_directory.h" #include "url/url_constants.h" namespace net::test_server { -void InstallDefaultWebSocketHandlers(EmbeddedTestServer* server, - bool serve_websocket_test_data) { +void InstallDefaultWebSocketHandlers(EmbeddedTestServer* server) { CHECK(server); - // Optionally serve WebSocket test data. - if (serve_websocket_test_data) { - // Set up the file path for serving test files. - base::FilePath src_dir; - CHECK(base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &src_dir)); - - // Serve WebSocket test data directory for both HTTP and HTTPS servers. - const base::FilePath websocket_data_dir = - src_dir.AppendASCII("net").AppendASCII("data").AppendASCII("websocket"); - - server->ServeFilesFromDirectory(websocket_data_dir); - } - // Register default WebSocket handlers. RegisterWebSocketHandler(server, "/check-origin"); RegisterWebSocketHandler(server, "/close"); + RegisterWebSocketHandler( + server, "/close-immediately"); RegisterWebSocketHandler(server, "/close-observer"); RegisterWebSocketHandler(server, @@ -49,6 +37,7 @@ void InstallDefaultWebSocketHandlers(EmbeddedTestServer* server, server, "/echo-request-headers"); RegisterWebSocketHandler( server, "/close-with-split-packet"); + RegisterWebSocketHandler(server, "/set-hsts"); } GURL ToWebSocketUrl(const GURL& url) { diff --git a/naiveproxy/src/net/test/embedded_test_server/install_default_websocket_handlers.h b/naiveproxy/src/net/test/embedded_test_server/install_default_websocket_handlers.h index 8fdaeb4e2e..ddccd82f7a 100644 --- a/naiveproxy/src/net/test/embedded_test_server/install_default_websocket_handlers.h +++ b/naiveproxy/src/net/test/embedded_test_server/install_default_websocket_handlers.h @@ -13,26 +13,21 @@ namespace net::test_server { // Installs default WebSocket handlers, such as the echo handler, on the given -// EmbeddedTestServer instance. Optionally, it can also configure the server to -// serve WebSocket test data files from the `net/data/websocket` directory. +// EmbeddedTestServer instance. HTTP handlers may be added directly to the +// passed in EmbeddedTestServer as well, to allow a single server to support +// both HTTP and WebSockets. +// // // Parameters: // - `server`: The EmbeddedTestServer instance to configure. -// - `serve_websocket_test_data`: If true, serves test data files from -// `net/data/websocket`. Default is false. // // Note: -// - The `ServeFilesFromDirectory` function registers a file handler as part of -// the server's request handlers. The first handler to provide a valid -// response will "win," and subsequent handlers will not override the -// response. // - To ensure consistent behavior, it is recommended that only one file handler // (e.g., via `ServeFilesFromDirectory`) is installed per server instance. // - If multiple calls to `ServeFilesFromDirectory` are necessary, ensure they // serve distinct sets of files or are added intentionally to the // request-handling chain. -void InstallDefaultWebSocketHandlers(EmbeddedTestServer* server, - bool serve_websocket_test_data = false); +void InstallDefaultWebSocketHandlers(EmbeddedTestServer* server); // Converts a given HTTP or HTTPS URL to a corresponding WebSocket (ws) or // Secure WebSocket (wss) URL, depending on the server's SSL configuration. diff --git a/naiveproxy/src/net/test/embedded_test_server/register_basic_auth_handler.cc b/naiveproxy/src/net/test/embedded_test_server/register_basic_auth_handler.cc index 00bd70bd24..d6074d972b 100644 --- a/naiveproxy/src/net/test/embedded_test_server/register_basic_auth_handler.cc +++ b/naiveproxy/src/net/test/embedded_test_server/register_basic_auth_handler.cc @@ -54,12 +54,12 @@ std::unique_ptr HandleBasicAuth( if (auth_header == request.headers.end() || auth_header->second != expected_auth_header) { - DVLOG(1) << "Authorization failed or header missing. For Proxy: " - << std::boolalpha << is_proxy_auth; + VLOG(1) << "Authorization failed or header missing. For Proxy: " + << std::boolalpha << is_proxy_auth; return CreateUnauthorizedResponse(is_proxy_auth); } - DVLOG(3) << "Authorization successful. For Proxy: " << is_proxy_auth; + VLOG(3) << "Authorization successful. For Proxy: " << is_proxy_auth; return nullptr; } diff --git a/naiveproxy/src/net/test/embedded_test_server/websocket_check_origin_handler.cc b/naiveproxy/src/net/test/embedded_test_server/websocket_check_origin_handler.cc index ea0224b6e2..2179ca80c7 100644 --- a/naiveproxy/src/net/test/embedded_test_server/websocket_check_origin_handler.cc +++ b/naiveproxy/src/net/test/embedded_test_server/websocket_check_origin_handler.cc @@ -20,12 +20,12 @@ void WebSocketCheckOriginHandler::OnHandshake(const HttpRequest& request) { CHECK(it != request.headers.end()); origin_ = it->second; - DVLOG(3) << "Stored WebSocket origin: " << origin_; + VLOG(3) << "Stored WebSocket origin: " << origin_; } void WebSocketCheckOriginHandler::OnHandshakeComplete() { CHECK(connection()); - DVLOG(3) << "Sending stored origin after handshake completion: " << origin_; + VLOG(3) << "Sending stored origin after handshake completion: " << origin_; connection()->SendTextMessage(origin_); connection()->StartClosingHandshake(1000, "Goodbye"); } diff --git a/naiveproxy/src/net/test/embedded_test_server/websocket_close_immediately_handler.cc b/naiveproxy/src/net/test/embedded_test_server/websocket_close_immediately_handler.cc new file mode 100644 index 0000000000..799d011c74 --- /dev/null +++ b/naiveproxy/src/net/test/embedded_test_server/websocket_close_immediately_handler.cc @@ -0,0 +1,19 @@ +// Copyright 2025 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/embedded_test_server/websocket_close_immediately_handler.h" + +namespace net::test_server { + +WebSocketCloseImmediatelyHandler::WebSocketCloseImmediatelyHandler( + scoped_refptr connection) + : WebSocketHandler(std::move(connection)) {} + +WebSocketCloseImmediatelyHandler::~WebSocketCloseImmediatelyHandler() = default; + +void WebSocketCloseImmediatelyHandler::OnHandshakeComplete() { + connection()->StartClosingHandshake(/*code=*/std::nullopt, /*message=*/""); +} + +} // namespace net::test_server diff --git a/naiveproxy/src/net/test/embedded_test_server/websocket_close_immediately_handler.h b/naiveproxy/src/net/test/embedded_test_server/websocket_close_immediately_handler.h new file mode 100644 index 0000000000..9a3a7c34b8 --- /dev/null +++ b/naiveproxy/src/net/test/embedded_test_server/websocket_close_immediately_handler.h @@ -0,0 +1,28 @@ +// Copyright 2025 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_EMBEDDED_TEST_SERVER_WEBSOCKET_CLOSE_IMMEDIATELY_HANDLER_H_ +#define NET_TEST_EMBEDDED_TEST_SERVER_WEBSOCKET_CLOSE_IMMEDIATELY_HANDLER_H_ + +#include "base/memory/scoped_refptr.h" +#include "net/test/embedded_test_server/websocket_connection.h" +#include "net/test/embedded_test_server/websocket_handler.h" + +namespace net::test_server { + +// WebSocketCloseImmediatelyHandler is a handler for WebSocket connections that +// cleanly closes the WebSocket immediately after receiving a handshake. +class WebSocketCloseImmediatelyHandler + : public net::test_server::WebSocketHandler { + public: + explicit WebSocketCloseImmediatelyHandler( + scoped_refptr connection); + ~WebSocketCloseImmediatelyHandler() override; + + void OnHandshakeComplete() override; +}; + +} // namespace net::test_server + +#endif // NET_TEST_EMBEDDED_TEST_SERVER_WEBSOCKET_CLOSE_IMMEDIATELY_HANDLER_H_ diff --git a/naiveproxy/src/net/test/embedded_test_server/websocket_close_observer_handler.cc b/naiveproxy/src/net/test/embedded_test_server/websocket_close_observer_handler.cc index e6d3b1f1da..4d2229b179 100644 --- a/naiveproxy/src/net/test/embedded_test_server/websocket_close_observer_handler.cc +++ b/naiveproxy/src/net/test/embedded_test_server/websocket_close_observer_handler.cc @@ -47,7 +47,7 @@ void WebSocketCloseObserverHandler::OnHandshake(const HttpRequest& request) { std::string role; if (!GetValueForKeyInQuery(request.GetURL(), "role", &role)) { - DVLOG(1) << "Missing required 'role' parameter."; + VLOG(1) << "Missing required 'role' parameter."; SendBadRequest("Missing required 'role' parameter."); return; } @@ -59,7 +59,7 @@ void WebSocketCloseObserverHandler::OnHandshake(const HttpRequest& request) { } else if (role == "observed") { role_ = Role::kObserved; } else { - DVLOG(1) << "Invalid 'role' parameter: " << role; + VLOG(1) << "Invalid 'role' parameter: " << role; SendBadRequest("Invalid 'role' parameter."); return; } @@ -68,7 +68,7 @@ void WebSocketCloseObserverHandler::OnHandshake(const HttpRequest& request) { void WebSocketCloseObserverHandler::OnClosingHandshake( std::optional code, std::string_view message) { - DVLOG(3) << "OnClosingHandshake()"; + VLOG(3) << "OnClosingHandshake()"; if (role_ == Role::kObserved) { g_code = code.value_or(1006); @@ -79,7 +79,7 @@ void WebSocketCloseObserverHandler::OnClosingHandshake( } void WebSocketCloseObserverHandler::BeObserver() { - DVLOG(3) << "BeObserver()"; + VLOG(3) << "BeObserver()"; if (g_code) { SendCloseCode(); } else { diff --git a/naiveproxy/src/net/test/embedded_test_server/websocket_connection.cc b/naiveproxy/src/net/test/embedded_test_server/websocket_connection.cc index 8697d163c0..ab8d06a660 100644 --- a/naiveproxy/src/net/test/embedded_test_server/websocket_connection.cc +++ b/naiveproxy/src/net/test/embedded_test_server/websocket_connection.cc @@ -23,6 +23,7 @@ #include "net/socket/stream_socket.h" #include "net/test/embedded_test_server/websocket_handler.h" #include "net/test/embedded_test_server/websocket_message_assembler.h" +#include "net/websockets/websocket_errors.h" #include "net/websockets/websocket_frame.h" #include "net/websockets/websocket_frame_parser.h" #include "net/websockets/websocket_handshake_challenge.h" @@ -92,13 +93,13 @@ void WebSocketConnection::StartClosingHandshake(std::optional code, std::string_view message) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!stream_socket_) { - DVLOG(2) << "Attempted to start closing handshake, but socket is null."; + VLOG(2) << "Attempted to start closing handshake, but socket is null."; return; } - DVLOG(3) << "Starting closing handshake. Code: " - << (code ? base::NumberToString(*code) : "none") - << ", Message: " << message; + VLOG(3) << "Starting closing handshake. Code: " + << (code ? base::NumberToString(*code) : "none") + << ", Message: " << message; if (!code) { CHECK(base::IsStringUTF8AllowingNoncharacters(message)); @@ -119,14 +120,23 @@ void WebSocketConnection::RespondToCloseFrame(std::optional code, std::string_view message) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (state_ == WebSocketState::kClosed) { - DVLOG(2) << "Attempted to respond to close frame, but connection is " - "already closed."; + VLOG(2) << "Attempted to respond to close frame, but connection is " + "already closed."; return; } - CHECK(base::IsStringUTF8AllowingNoncharacters(message)); - scoped_refptr close_frame = CreateCloseFrame(code, message); - SendInternal(std::move(close_frame), /*wait_for_handshake=*/false); + // Only need to send a close frame if one was not already sent. + if (state_ != WebSocketState::kWaitingForClientClose) { + CHECK(base::IsStringUTF8AllowingNoncharacters(message)); + scoped_refptr close_frame; + if (code != kWebSocketErrorNoStatusReceived) { + close_frame = CreateCloseFrame(code, message); + } else { + close_frame = CreateCloseFrame(/*code=*/std::nullopt, /*message=*/""); + } + SendInternal(std::move(close_frame), /*wait_for_handshake=*/false); + } + DisconnectAfterAnyWritesDone(); } @@ -145,7 +155,7 @@ void WebSocketConnection::SendPong(base::span payload) { void WebSocketConnection::DisconnectAfterAnyWritesDone() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!stream_socket_) { - DVLOG(3) << "Socket is already disconnected."; + VLOG(3) << "Socket is already disconnected."; return; } @@ -162,7 +172,7 @@ void WebSocketConnection::DisconnectAfterAnyWritesDone() { void WebSocketConnection::DisconnectImmediately() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!stream_socket_) { - DVLOG(3) << "Socket is already disconnected."; + VLOG(3) << "Socket is already disconnected."; handler_.reset(); return; } @@ -229,7 +239,7 @@ void WebSocketConnection::PerformWrite() void WebSocketConnection::OnWriteComplete(int result) VALID_CONTEXT_REQUIRED(sequence_checker_) { if (result < 0) { - DVLOG(1) << "Failed to write to WebSocket connection, error: " << result; + VLOG(1) << "Failed to write to WebSocket connection, error: " << result; DisconnectImmediately(); return; } @@ -271,13 +281,13 @@ void WebSocketConnection::Read() VALID_CONTEXT_REQUIRED(sequence_checker_) { void WebSocketConnection::OnReadComplete(int result) VALID_CONTEXT_REQUIRED(sequence_checker_) { if (result <= 0) { - DVLOG(1) << "Failed to read from WebSocket connection, error: " << result; + VLOG(1) << "Failed to read from WebSocket connection, error: " << result; DisconnectImmediately(); return; } if (!handler_) { - DVLOG(1) << "No handler set, ignoring read."; + VLOG(1) << "No handler set, ignoring read."; return; } @@ -301,7 +311,7 @@ void WebSocketConnection::OnReadComplete(int result) } if (assemble_result.error() == ERR_WS_PROTOCOL_ERROR) { - DVLOG(1) << "Protocol error while handling frame."; + VLOG(1) << "Protocol error while handling frame."; StartClosingHandshake(1002, "Protocol error"); DisconnectAfterAnyWritesDone(); return; @@ -342,8 +352,8 @@ void WebSocketConnection::HandleFrame(WebSocketFrameHeader::OpCode opcode, case WebSocketFrameHeader::kOpCodeClose: { auto parse_close_frame_result = ParseCloseFrame(payload); if (parse_close_frame_result.error.has_value()) { - DVLOG(1) << "Failed to parse close frame: " - << parse_close_frame_result.error.value(); + VLOG(1) << "Failed to parse close frame: " + << parse_close_frame_result.error.value(); StartClosingHandshake(1002, "Protocol error"); DisconnectAfterAnyWritesDone(); } else { @@ -359,7 +369,7 @@ void WebSocketConnection::HandleFrame(WebSocketFrameHeader::OpCode opcode, handler_->OnPong(base::as_bytes(payload)); break; default: - DVLOG(2) << "Unknown frame opcode: " << opcode; + VLOG(2) << "Unknown frame opcode: " << opcode; StartClosingHandshake(1002, "Protocol error"); DisconnectAfterAnyWritesDone(); break; @@ -370,7 +380,7 @@ void WebSocketConnection::SendHandshakeResponse() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!stream_socket_) { - DVLOG(2) << "Stream socket is already null. Returning early."; + VLOG(2) << "Stream socket is already null. Returning early."; return; } @@ -392,8 +402,7 @@ void WebSocketConnection::SendHandshakeResponse() { if (handler_) { handler_->OnHandshakeComplete(); } else { - DVLOG(2) - << "Handler is null after starting Read. Connection likely closed."; + VLOG(2) << "Handler is null after starting Read. Connection likely closed."; } } @@ -409,9 +418,9 @@ scoped_refptr CreateBinaryFrame( scoped_refptr CreateCloseFrame(std::optional code, std::string_view message) { - DVLOG(3) << "Creating close frame with code: " - << (code ? base::NumberToString(*code) : "none") - << ", Message: " << message; + VLOG(3) << "Creating close frame with code: " + << (code ? base::NumberToString(*code) : "none") + << ", Message: " << message; CHECK(message.empty() || code); CHECK(base::IsStringUTF8AllowingNoncharacters(message)); diff --git a/naiveproxy/src/net/test/embedded_test_server/websocket_handler.cc b/naiveproxy/src/net/test/embedded_test_server/websocket_handler.cc index 9d6874f7a7..d8b23e6af2 100644 --- a/naiveproxy/src/net/test/embedded_test_server/websocket_handler.cc +++ b/naiveproxy/src/net/test/embedded_test_server/websocket_handler.cc @@ -26,15 +26,15 @@ void WebSocketHandler::OnPing(base::span payload) { // Default implementation of OnPong that does nothing. void WebSocketHandler::OnPong(base::span payload) { // Default implementation does nothing. - DVLOG(3) << "Received PONG message."; + VLOG(3) << "Received PONG message."; } // Default implementation of OnClosingHandshake. void WebSocketHandler::OnClosingHandshake(std::optional code, std::string_view message) { - DVLOG(3) << "Closing handshake received with code: " - << (code.has_value() ? base::NumberToString(code.value()) : "none") - << ", message: " << message; + VLOG(3) << "Closing handshake received with code: " + << (code.has_value() ? base::NumberToString(code.value()) : "none") + << ", message: " << message; connection()->RespondToCloseFrame(code, message); } diff --git a/naiveproxy/src/net/test/embedded_test_server/websocket_message_assembler.cc b/naiveproxy/src/net/test/embedded_test_server/websocket_message_assembler.cc index 6b039425f5..e235eaa030 100644 --- a/naiveproxy/src/net/test/embedded_test_server/websocket_message_assembler.cc +++ b/naiveproxy/src/net/test/embedded_test_server/websocket_message_assembler.cc @@ -26,7 +26,7 @@ MessageOrError WebSocketMessageAssembler::HandleFrame( switch (opcode) { case WebSocketFrameHeader::kOpCodeText: if (state_ != MessageState::kIdle) { - DVLOG(1) << "Unexpected text frame while expecting continuation"; + VLOG(1) << "Unexpected text frame while expecting continuation"; return base::unexpected(ERR_WS_PROTOCOL_ERROR); } is_text_message_ = true; @@ -34,7 +34,7 @@ MessageOrError WebSocketMessageAssembler::HandleFrame( case WebSocketFrameHeader::kOpCodeBinary: if (state_ != MessageState::kIdle) { - DVLOG(1) << "Unexpected binary frame while expecting continuation"; + VLOG(1) << "Unexpected binary frame while expecting continuation"; return base::unexpected(ERR_WS_PROTOCOL_ERROR); } // Explicitly set to indicate binary handling. @@ -43,13 +43,13 @@ MessageOrError WebSocketMessageAssembler::HandleFrame( case WebSocketFrameHeader::kOpCodeContinuation: if (state_ == MessageState::kIdle) { - DVLOG(1) << "Unexpected continuation frame in idle state"; + VLOG(1) << "Unexpected continuation frame in idle state"; return base::unexpected(ERR_WS_PROTOCOL_ERROR); } break; default: - DVLOG(1) << "Invalid frame opcode: " << opcode; + VLOG(1) << "Invalid frame opcode: " << opcode; return base::unexpected(ERR_WS_PROTOCOL_ERROR); } diff --git a/naiveproxy/src/net/test/embedded_test_server/websocket_set_hsts_handler.cc b/naiveproxy/src/net/test/embedded_test_server/websocket_set_hsts_handler.cc new file mode 100644 index 0000000000..5d7a56ebdc --- /dev/null +++ b/naiveproxy/src/net/test/embedded_test_server/websocket_set_hsts_handler.cc @@ -0,0 +1,23 @@ +// Copyright 2025 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/embedded_test_server/websocket_set_hsts_handler.h" + +#include "base/memory/scoped_refptr.h" +#include "net/test/embedded_test_server/websocket_connection.h" +#include "net/test/embedded_test_server/websocket_echo_handler.h" +#include "net/test/embedded_test_server/websocket_handler.h" + +namespace net::test_server { + +WebSocketSetHstsHandler::WebSocketSetHstsHandler( + scoped_refptr connection) + : WebSocketHandler(std::move(connection)) {} + +void WebSocketSetHstsHandler::OnHandshake(const HttpRequest& request) { + CHECK(connection()); + connection()->SetResponseHeader("Strict-Transport-Security", "max-age=3600"); +} + +} // namespace net::test_server diff --git a/naiveproxy/src/net/test/embedded_test_server/websocket_set_hsts_handler.h b/naiveproxy/src/net/test/embedded_test_server/websocket_set_hsts_handler.h new file mode 100644 index 0000000000..ae96326e49 --- /dev/null +++ b/naiveproxy/src/net/test/embedded_test_server/websocket_set_hsts_handler.h @@ -0,0 +1,29 @@ +// Copyright 2025 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_EMBEDDED_TEST_SERVER_WEBSOCKET_SET_HSTS_HANDLER_H_ +#define NET_TEST_EMBEDDED_TEST_SERVER_WEBSOCKET_SET_HSTS_HANDLER_H_ + +#include "base/memory/scoped_refptr.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "net/test/embedded_test_server/websocket_handler.h" + +namespace net::test_server { + +class WebSocketConnection; + +// WebSocketSetHstsHandler is a handler for WebSocket connections that enables +// HSTS for the host. +class WebSocketSetHstsHandler : public WebSocketHandler { + public: + // Constructs the handler with a given WebSocket connection. + explicit WebSocketSetHstsHandler( + scoped_refptr connection); + + void OnHandshake(const HttpRequest& request) override; +}; + +} // namespace net::test_server + +#endif // NET_TEST_EMBEDDED_TEST_SERVER_WEBSOCKET_SET_HSTS_HANDLER_H_ diff --git a/naiveproxy/src/net/test/revocation_builder.cc b/naiveproxy/src/net/test/revocation_builder.cc index 47f8d7b623..2b23089f1c 100644 --- a/naiveproxy/src/net/test/revocation_builder.cc +++ b/naiveproxy/src/net/test/revocation_builder.cc @@ -46,7 +46,7 @@ bool CBBAddBytes(CBB* cbb, base::span data) { // Adds a GeneralizedTime value to the given CBB. // The argument ordering follows the boringssl CBB_* api style. -bool CBBAddGeneralizedTime(CBB* cbb, const base::Time& time) { +bool CBBAddGeneralizedTime(CBB* cbb, base::Time time) { bssl::der::GeneralizedTime generalized_time; if (!EncodeTimeAsGeneralizedTime(time, &generalized_time)) { return false; diff --git a/naiveproxy/src/net/test/spawned_test_server/base_test_server.cc b/naiveproxy/src/net/test/spawned_test_server/base_test_server.cc deleted file mode 100644 index 38509f4065..0000000000 --- a/naiveproxy/src/net/test/spawned_test_server/base_test_server.cc +++ /dev/null @@ -1,378 +0,0 @@ -// 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. - -#include "net/test/spawned_test_server/base_test_server.h" - -#include -#include -#include -#include -#include -#include - -#include "base/base64.h" -#include "base/files/file_util.h" -#include "base/json/json_reader.h" -#include "base/logging.h" -#include "base/notreached.h" -#include "base/path_service.h" -#include "base/strings/string_util.h" -#include "base/values.h" -#include "net/base/address_list.h" -#include "net/base/host_port_pair.h" -#include "net/base/net_errors.h" -#include "net/base/network_isolation_key.h" -#include "net/base/port_util.h" -#include "net/cert/x509_certificate.h" -#include "net/dns/public/dns_query_type.h" -#include "net/log/net_log_with_source.h" -#include "net/test/cert_test_util.h" -#include "net/test/test_data_directory.h" -#include "url/gurl.h" - -namespace net { - -namespace { - -std::string GetHostname(BaseTestServer::Type type, - const BaseTestServer::SSLOptions& options) { - if (BaseTestServer::UsingSSL(type)) { - if (options.server_certificate == - BaseTestServer::SSLOptions::CERT_MISMATCHED_NAME || - options.server_certificate == - BaseTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN) { - // For |CERT_MISMATCHED_NAME|, return a different hostname string - // that resolves to the same hostname. For - // |CERT_COMMON_NAME_IS_DOMAIN|, the certificate is issued for - // "localhost" instead of "127.0.0.1". - return "localhost"; - } - } - - return "127.0.0.1"; -} - -bool GetLocalCertificatesDir(const base::FilePath& certificates_dir, - base::FilePath* local_certificates_dir) { - if (certificates_dir.IsAbsolute()) { - *local_certificates_dir = certificates_dir; - return true; - } - - base::FilePath src_dir; - if (!base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &src_dir)) { - return false; - } - - *local_certificates_dir = src_dir.Append(certificates_dir); - return true; -} - -} // namespace - -BaseTestServer::SSLOptions::SSLOptions() = default; -BaseTestServer::SSLOptions::SSLOptions(ServerCertificate cert) - : server_certificate(cert) {} -BaseTestServer::SSLOptions::SSLOptions(base::FilePath cert) - : custom_certificate(std::move(cert)) {} -BaseTestServer::SSLOptions::SSLOptions(const SSLOptions& other) = default; - -BaseTestServer::SSLOptions::~SSLOptions() = default; - -base::FilePath BaseTestServer::SSLOptions::GetCertificateFile() const { - if (!custom_certificate.empty()) - return custom_certificate; - - switch (server_certificate) { - case CERT_OK: - case CERT_MISMATCHED_NAME: - return base::FilePath(FILE_PATH_LITERAL("ok_cert.pem")); - case CERT_COMMON_NAME_IS_DOMAIN: - return base::FilePath(FILE_PATH_LITERAL("localhost_cert.pem")); - case CERT_EXPIRED: - return base::FilePath(FILE_PATH_LITERAL("expired_cert.pem")); - case CERT_CHAIN_WRONG_ROOT: - // This chain uses its own dedicated test root certificate to avoid - // side-effects that may affect testing. - return base::FilePath(FILE_PATH_LITERAL("redundant-server-chain.pem")); - case CERT_KEY_USAGE_RSA_ENCIPHERMENT: - return base::FilePath( - FILE_PATH_LITERAL("key_usage_rsa_keyencipherment.pem")); - case CERT_KEY_USAGE_RSA_DIGITAL_SIGNATURE: - return base::FilePath( - FILE_PATH_LITERAL("key_usage_rsa_digitalsignature.pem")); - case CERT_TEST_NAMES: - return base::FilePath(FILE_PATH_LITERAL("test_names.pem")); - default: - NOTREACHED(); - } -} - -BaseTestServer::BaseTestServer(Type type) : type_(type) { - Init(GetHostname(type, ssl_options_)); -} - -BaseTestServer::BaseTestServer(Type type, const SSLOptions& ssl_options) - : ssl_options_(ssl_options), type_(type) { - DCHECK(UsingSSL(type)); - Init(GetHostname(type, ssl_options)); -} - -BaseTestServer::~BaseTestServer() = default; - -bool BaseTestServer::Start() { - return StartInBackground() && BlockUntilStarted(); -} - -const HostPortPair& BaseTestServer::host_port_pair() const { - DCHECK(started_); - return host_port_pair_; -} - -std::string BaseTestServer::GetScheme() const { - switch (type_) { - case TYPE_WS: - return "ws"; - case TYPE_WSS: - return "wss"; - default: - NOTREACHED(); - } -} - -bool BaseTestServer::GetAddressList(AddressList* address_list) const { - // Historically, this function did a DNS lookup because `host_port_pair_` - // could specify something other than localhost. Now it is always localhost. - DCHECK(host_port_pair_.host() == "127.0.0.1" || - host_port_pair_.host() == "localhost"); - DCHECK(address_list); - *address_list = AddressList( - IPEndPoint(IPAddress::IPv4Localhost(), host_port_pair_.port())); - return true; -} - -uint16_t BaseTestServer::GetPort() { - return host_port_pair_.port(); -} - -void BaseTestServer::SetPort(uint16_t port) { - host_port_pair_.set_port(port); -} - -GURL BaseTestServer::GetURL(const std::string& path) const { - return GURL(GetScheme() + "://" + host_port_pair_.ToString() + "/" + path); -} - -GURL BaseTestServer::GetURL(const std::string& hostname, - const std::string& relative_url) const { - GURL local_url = GetURL(relative_url); - GURL::Replacements replace_host; - replace_host.SetHostStr(hostname); - return local_url.ReplaceComponents(replace_host); -} - -GURL BaseTestServer::GetURLWithUser(const std::string& path, - const std::string& user) const { - return GURL(GetScheme() + "://" + user + "@" + host_port_pair_.ToString() + - "/" + path); -} - -GURL BaseTestServer::GetURLWithUserAndPassword(const std::string& path, - const std::string& user, - const std::string& password) const { - return GURL(GetScheme() + "://" + user + ":" + password + "@" + - host_port_pair_.ToString() + "/" + path); -} - -// static -bool BaseTestServer::GetFilePathWithReplacements( - const std::string& original_file_path, - const std::vector& text_to_replace, - std::string* replacement_path) { - std::string new_file_path = original_file_path; - bool first_query_parameter = true; - const std::vector::const_iterator end = text_to_replace.end(); - for (auto it = text_to_replace.begin(); it != end; ++it) { - const std::string& old_text = it->first; - const std::string& new_text = it->second; - std::string base64_old = base::Base64Encode(old_text); - std::string base64_new = base::Base64Encode(new_text); - if (first_query_parameter) { - new_file_path += "?"; - first_query_parameter = false; - } else { - new_file_path += "&"; - } - new_file_path += "replace_text="; - new_file_path += base64_old; - new_file_path += ":"; - new_file_path += base64_new; - } - - *replacement_path = new_file_path; - return true; -} - -ScopedTestRoot BaseTestServer::RegisterTestCerts() { - auto root = ImportCertFromFile(GetTestCertsDirectory(), "root_ca_cert.pem"); - if (!root) - return ScopedTestRoot(); - return ScopedTestRoot(CertificateList{root}); -} - -bool BaseTestServer::LoadTestRootCert() { - scoped_test_root_ = RegisterTestCerts(); - return !scoped_test_root_.IsEmpty(); -} - -scoped_refptr BaseTestServer::GetCertificate() const { - base::FilePath certificate_path; - if (!GetLocalCertificatesDir(certificates_dir_, &certificate_path)) - return nullptr; - - base::FilePath certificate_file(ssl_options_.GetCertificateFile()); - if (certificate_file.value().empty()) - return nullptr; - - certificate_path = certificate_path.Append(certificate_file); - - std::string cert_data; - if (!base::ReadFileToString(certificate_path, &cert_data)) - return nullptr; - - CertificateList certs_in_file = - X509Certificate::CreateCertificateListFromBytes( - base::as_byte_span(cert_data), - X509Certificate::FORMAT_PEM_CERT_SEQUENCE); - if (certs_in_file.empty()) - return nullptr; - return certs_in_file[0]; -} - -void BaseTestServer::Init(const std::string& host) { - host_port_pair_ = HostPortPair(host, 0); - - // TODO(battre) Remove this after figuring out why the TestServer is flaky. - // http://crbug.com/96594 - log_to_console_ = true; -} - -void BaseTestServer::SetResourcePath(const base::FilePath& document_root, - const base::FilePath& certificates_dir) { - // This method shouldn't get called twice. - DCHECK(certificates_dir_.empty()); - document_root_ = document_root; - certificates_dir_ = certificates_dir; - DCHECK(!certificates_dir_.empty()); -} - -bool BaseTestServer::SetAndParseServerData(const std::string& server_data, - int* port) { - VLOG(1) << "Server data: " << server_data; - auto parsed_json = base::JSONReader::ReadAndReturnValueWithError(server_data); - if (!parsed_json.has_value()) { - LOG(ERROR) << "Could not parse server data: " - << parsed_json.error().message; - return false; - } else if (!parsed_json->is_dict()) { - LOG(ERROR) << "Could not parse server data: expecting a dictionary"; - return false; - } - - std::optional port_value = parsed_json->GetDict().FindInt("port"); - if (!port_value) { - LOG(ERROR) << "Could not find port value"; - return false; - } - - *port = *port_value; - if ((*port <= 0) || (*port > std::numeric_limits::max())) { - LOG(ERROR) << "Invalid port value: " << port; - return false; - } - - return true; -} - -bool BaseTestServer::SetupWhenServerStarted() { - DCHECK(host_port_pair_.port()); - DCHECK(!started_); - - if (UsingSSL(type_) && !LoadTestRootCert()) { - LOG(ERROR) << "Could not load test root certificate."; - return false; - } - - started_ = true; - allowed_port_ = std::make_unique(host_port_pair_.port()); - return true; -} - -void BaseTestServer::CleanUpWhenStoppingServer() { - scoped_test_root_.Reset({}); - host_port_pair_.set_port(0); - allowed_port_.reset(); - started_ = false; -} - -std::optional BaseTestServer::GenerateArguments() const { - base::Value::Dict arguments; - arguments.Set("host", host_port_pair_.host()); - arguments.Set("port", host_port_pair_.port()); - arguments.Set("data-dir", document_root_.AsUTF8Unsafe()); - - if (VLOG_IS_ON(1) || log_to_console_) - arguments.Set("log-to-console", base::Value()); - - if (ws_basic_auth_) { - DCHECK(type_ == TYPE_WS || type_ == TYPE_WSS); - arguments.Set("ws-basic-auth", base::Value()); - } - - if (redirect_connect_to_localhost_) { - DCHECK(type_ == TYPE_BASIC_AUTH_PROXY || type_ == TYPE_PROXY); - arguments.Set("redirect-connect-to-localhost", base::Value()); - } - - if (UsingSSL(type_)) { - // Check the certificate arguments of the HTTPS server. - base::FilePath certificate_path(certificates_dir_); - base::FilePath certificate_file(ssl_options_.GetCertificateFile()); - if (!certificate_file.value().empty()) { - certificate_path = certificate_path.Append(certificate_file); - if (certificate_path.IsAbsolute() && - !base::PathExists(certificate_path)) { - LOG(ERROR) << "Certificate path " << certificate_path.value() - << " doesn't exist. Can't launch https server."; - return std::nullopt; - } - arguments.Set("cert-and-key-file", certificate_path.AsUTF8Unsafe()); - } - - // Check the client certificate related arguments. - if (ssl_options_.request_client_certificate) - arguments.Set("ssl-client-auth", base::Value()); - - base::Value::List ssl_client_certs; - - std::vector::const_iterator it; - for (it = ssl_options_.client_authorities.begin(); - it != ssl_options_.client_authorities.end(); ++it) { - if (it->IsAbsolute() && !base::PathExists(*it)) { - LOG(ERROR) << "Client authority path " << it->value() - << " doesn't exist. Can't launch https server."; - return std::nullopt; - } - ssl_client_certs.Append(it->AsUTF8Unsafe()); - } - - if (ssl_client_certs.size()) { - arguments.Set("ssl-client-ca", std::move(ssl_client_certs)); - } - } - - return std::make_optional(std::move(arguments)); -} - -} // namespace net diff --git a/naiveproxy/src/net/test/spawned_test_server/base_test_server.h b/naiveproxy/src/net/test/spawned_test_server/base_test_server.h deleted file mode 100644 index 5a4b124cbf..0000000000 --- a/naiveproxy/src/net/test/spawned_test_server/base_test_server.h +++ /dev/null @@ -1,262 +0,0 @@ -// 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. - -// NOTE: spawned_test_server is deprecated, since it frequently causes test -// flakiness. Please consider using embedded_test_server if possible. - -#ifndef NET_TEST_SPAWNED_TEST_SERVER_BASE_TEST_SERVER_H_ -#define NET_TEST_SPAWNED_TEST_SERVER_BASE_TEST_SERVER_H_ - -#include - -#include -#include -#include -#include -#include - -#include "base/files/file_path.h" -#include "base/memory/scoped_refptr.h" -#include "base/values.h" -#include "net/base/host_port_pair.h" -#include "net/cert/test_root_certs.h" - -class GURL; - -namespace net { - -class AddressList; -class ScopedPortException; -class ScopedTestRoot; -class X509Certificate; - -// The base class of Test server implementation. -class BaseTestServer { - public: - typedef std::pair StringPair; - - enum Type { - TYPE_BASIC_AUTH_PROXY, - TYPE_WS, - TYPE_WSS, - TYPE_PROXY, - }; - - // Container for various options to control how the HTTPS or WSS server is - // initialized. - struct SSLOptions { - enum ServerCertificate { - CERT_OK, - - CERT_MISMATCHED_NAME, - CERT_EXPIRED, - // Cross-signed certificate to test PKIX path building. Contains an - // intermediate cross-signed by an unknown root, while the client (via - // TestRootStore) is expected to have a self-signed version of the - // intermediate. - CERT_CHAIN_WRONG_ROOT, - - // Causes the testserver to use a hostname that is a domain - // instead of an IP. - CERT_COMMON_NAME_IS_DOMAIN, - - // An RSA certificate with the keyUsage extension specifying that the key - // is only for encipherment. - CERT_KEY_USAGE_RSA_ENCIPHERMENT, - - // An RSA certificate with the keyUsage extension specifying that the key - // is only for digital signatures. - CERT_KEY_USAGE_RSA_DIGITAL_SIGNATURE, - - // A certificate that covers a number of test names. See [test_names] in - // net/data/ssl/scripts/ee.cnf. More may be added by editing this list and - // and rerunning net/data/ssl/scripts/generate-test-certs.sh. - CERT_TEST_NAMES, - }; - - // Initialize a new SSLOptions using CERT_OK as the certificate. - SSLOptions(); - - // Initialize a new SSLOptions that will use the specified certificate. - explicit SSLOptions(ServerCertificate cert); - explicit SSLOptions(base::FilePath cert); - SSLOptions(const SSLOptions& other); - ~SSLOptions(); - - // Returns the relative filename of the file that contains the - // |server_certificate|. - base::FilePath GetCertificateFile() const; - - // The certificate to use when serving requests. - ServerCertificate server_certificate = CERT_OK; - base::FilePath custom_certificate; - - // True if a CertificateRequest should be sent to the client during - // handshaking. - bool request_client_certificate = false; - - // If |request_client_certificate| is true, an optional list of files, - // each containing a single, PEM-encoded X.509 certificates. The subject - // from each certificate will be added to the certificate_authorities - // field of the CertificateRequest. - std::vector client_authorities; - }; - - // Initialize a TestServer. - explicit BaseTestServer(Type type); - - // Initialize a TestServer with a specific set of SSLOptions for HTTPS or WSS. - BaseTestServer(Type type, const SSLOptions& ssl_options); - - BaseTestServer(const BaseTestServer&) = delete; - BaseTestServer& operator=(const BaseTestServer&) = delete; - - // Starts the server blocking until the server is ready. - [[nodiscard]] bool Start(); - - // Start the test server without blocking. Use this if you need multiple test - // servers (such as WebSockets and HTTP, or HTTP and HTTPS). You must call - // BlockUntilStarted on all servers your test requires before executing the - // test. For example: - // - // // Start the servers in parallel. - // ASSERT_TRUE(http_server.StartInBackground()); - // ASSERT_TRUE(websocket_server.StartInBackground()); - // // Wait for both servers to be ready. - // ASSERT_TRUE(http_server.BlockUntilStarted()); - // ASSERT_TRUE(websocket_server.BlockUntilStarted()); - // RunMyTest(); - // - // Returns true on success. - [[nodiscard]] virtual bool StartInBackground() = 0; - - // Block until the test server is ready. Returns true on success. See - // StartInBackground() documentation for more information. - [[nodiscard]] virtual bool BlockUntilStarted() = 0; - - // Returns the host port pair used by current Python based test server only - // if the server is started. - const HostPortPair& host_port_pair() const; - - const base::FilePath& document_root() const { return document_root_; } - std::string GetScheme() const; - [[nodiscard]] bool GetAddressList(AddressList* address_list) const; - - GURL GetURL(const std::string& path) const; - GURL GetURL(const std::string& hostname, - const std::string& relative_url) const; - - GURL GetURLWithUser(const std::string& path, - const std::string& user) const; - - GURL GetURLWithUserAndPassword(const std::string& path, - const std::string& user, - const std::string& password) const; - - static bool GetFilePathWithReplacements( - const std::string& original_path, - const std::vector& text_to_replace, - std::string* replacement_path); - - static bool UsingSSL(Type type) { return type == BaseTestServer::TYPE_WSS; } - - // Enable HTTP basic authentication. Currently this only works for TYPE_WS and - // TYPE_WSS. - void set_websocket_basic_auth(bool ws_basic_auth) { - ws_basic_auth_ = ws_basic_auth; - } - - // Redirect proxied CONNECT requests to localhost. - void set_redirect_connect_to_localhost(bool redirect_connect_to_localhost) { - redirect_connect_to_localhost_ = redirect_connect_to_localhost; - } - - // Registers the test server's certs for the current process. - [[nodiscard]] static ScopedTestRoot RegisterTestCerts(); - - // Marks the root certificate of an HTTPS test server as trusted for - // the duration of tests. - [[nodiscard]] bool LoadTestRootCert(); - - // Returns the certificate that the server is using. - scoped_refptr GetCertificate() const; - - protected: - virtual ~BaseTestServer(); - Type type() const { return type_; } - const SSLOptions& ssl_options() const { return ssl_options_; } - - bool started() const { return started_; } - - // Gets port currently assigned to host_port_pair_ without checking - // whether it's available (server started) or not. - uint16_t GetPort(); - - // Sets |port| as the actual port used by Python based test server. - void SetPort(uint16_t port); - - // Set up internal status when the server is started. - [[nodiscard]] bool SetupWhenServerStarted(); - - // Clean up internal status when starting to stop server. - void CleanUpWhenStoppingServer(); - - // Set path of test resources. - void SetResourcePath(const base::FilePath& document_root, - const base::FilePath& certificates_dir); - - // Parses the server data read from the test server and sets |server_data_|. - // *port is set to the port number specified in server_data. The port may be - // different from the local port set in |host_port_pair_|, specifically when - // using RemoteTestServer (which proxies connections from 127.0.0.1 to a - // different IP). Returns true on success. - [[nodiscard]] bool SetAndParseServerData(const std::string& server_data, - int* port); - - // Returns a base::Value::Dict with the arguments for launching the external - // Python test server, in the form of - // { argument-name: argument-value, ... } - // - // Returns nullopt if an invalid configuration is specified. - std::optional GenerateArguments() const; - - private: - void Init(const std::string& host); - - // Document root of the test server. - base::FilePath document_root_; - - // Directory that contains the SSL certificates. - base::FilePath certificates_dir_; - - ScopedTestRoot scoped_test_root_; - - // Address on which the tests should connect to the server. With - // RemoteTestServer it may be different from the address on which the server - // listens on. - HostPortPair host_port_pair_; - - // If |UsingSSL(type_)|, the TLS settings to use for the test server. - SSLOptions ssl_options_; - - Type type_; - - // Has the server been started? - bool started_ = false; - - // Enables logging of the server to the console. - bool log_to_console_ = false; - - // Is WebSocket basic HTTP authentication enabled? - bool ws_basic_auth_ = false; - - // Redirect proxied CONNECT requests to localhost? - bool redirect_connect_to_localhost_ = false; - - std::unique_ptr allowed_port_; -}; - -} // namespace net - -#endif // NET_TEST_SPAWNED_TEST_SERVER_BASE_TEST_SERVER_H_ diff --git a/naiveproxy/src/net/test/spawned_test_server/local_test_server.cc b/naiveproxy/src/net/test/spawned_test_server/local_test_server.cc deleted file mode 100644 index 5232749743..0000000000 --- a/naiveproxy/src/net/test/spawned_test_server/local_test_server.cc +++ /dev/null @@ -1,227 +0,0 @@ -// 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. - -#include "net/test/spawned_test_server/local_test_server.h" - -#include "base/command_line.h" -#include "base/json/json_reader.h" -#include "base/logging.h" -#include "base/notreached.h" -#include "base/path_service.h" -#include "base/strings/string_number_conversions.h" -#include "base/threading/thread_restrictions.h" -#include "base/values.h" -#include "net/base/host_port_pair.h" -#include "net/base/net_errors.h" -#include "net/test/python_utils.h" -#include "url/gurl.h" - -namespace net { - -namespace { - -bool AppendArgumentFromJSONValue(const std::string& key, - const base::Value& value_node, - base::CommandLine* command_line) { - std::string argument_name = "--" + key; - switch (value_node.type()) { - case base::Value::Type::NONE: - command_line->AppendArg(argument_name); - break; - case base::Value::Type::INTEGER: { - command_line->AppendArg(argument_name + "=" + - base::NumberToString(value_node.GetInt())); - break; - } - case base::Value::Type::STRING: { - if (!value_node.is_string()) - return false; - const std::string value = value_node.GetString(); - if (value.empty()) - return false; - command_line->AppendArg(argument_name + "=" + value); - break; - } - case base::Value::Type::BOOLEAN: - case base::Value::Type::DOUBLE: - case base::Value::Type::LIST: - case base::Value::Type::DICT: - case base::Value::Type::BINARY: - default: - NOTREACHED() << "improper json type"; - } - return true; -} - -} // namespace - -LocalTestServer::LocalTestServer(Type type, const base::FilePath& document_root) - : BaseTestServer(type) { - if (!Init(document_root)) - NOTREACHED(); -} - -LocalTestServer::LocalTestServer(Type type, - const SSLOptions& ssl_options, - const base::FilePath& document_root) - : BaseTestServer(type, ssl_options) { - if (!Init(document_root)) - NOTREACHED(); -} - -LocalTestServer::~LocalTestServer() { - Stop(); -} - -bool LocalTestServer::GetTestServerPath(base::FilePath* testserver_path) const { - base::FilePath testserver_dir; - if (!base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &testserver_dir)) { - LOG(ERROR) << "Failed to get DIR_SRC_TEST_DATA_ROOT"; - return false; - } - testserver_dir = testserver_dir.Append(FILE_PATH_LITERAL("net")) - .Append(FILE_PATH_LITERAL("tools")) - .Append(FILE_PATH_LITERAL("testserver")); - *testserver_path = testserver_dir.Append(FILE_PATH_LITERAL("testserver.py")); - return true; -} - -bool LocalTestServer::StartInBackground() { - DCHECK(!started()); - - base::ScopedAllowBlockingForTesting allow_blocking; - - // Get path to Python server script. - base::FilePath testserver_path; - if (!GetTestServerPath(&testserver_path)) { - LOG(ERROR) << "Could not get test server path."; - return false; - } - - std::optional> python_path = GetPythonPath(); - if (!python_path) { - LOG(ERROR) << "Could not get Python path."; - return false; - } - - if (!LaunchPython(testserver_path, *python_path)) { - LOG(ERROR) << "Could not launch Python with path " << testserver_path; - return false; - } - - return true; -} - -bool LocalTestServer::BlockUntilStarted() { - if (!WaitToStart()) { - Stop(); - return false; - } - - return SetupWhenServerStarted(); -} - -bool LocalTestServer::Stop() { - CleanUpWhenStoppingServer(); - - if (!process_.IsValid()) - return true; - - // First check if the process has already terminated. - bool ret = process_.WaitForExitWithTimeout(base::TimeDelta(), nullptr); - if (!ret) { - base::ScopedAllowBaseSyncPrimitivesForTesting allow_wait_process; - ret = process_.Terminate(1, true); - } - - if (ret) - process_.Close(); - else - VLOG(1) << "Kill failed?"; - - return ret; -} - -bool LocalTestServer::Init(const base::FilePath& document_root) { - if (document_root.IsAbsolute()) - return false; - - // At this point, the port that the test server will listen on is unknown. - // The test server will listen on an ephemeral port, and write the port - // number out over a pipe that this TestServer object will read from. Once - // that is complete, the host port pair will contain the actual port. - DCHECK(!GetPort()); - - base::FilePath src_dir; - if (!base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &src_dir)) { - return false; - } - SetResourcePath(src_dir.Append(document_root), - src_dir.AppendASCII("net") - .AppendASCII("data") - .AppendASCII("ssl") - .AppendASCII("certificates")); - return true; -} - -std::optional> LocalTestServer::GetPythonPath() - const { - base::FilePath third_party_dir; - if (!base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &third_party_dir)) { - LOG(ERROR) << "Failed to get DIR_SRC_TEST_DATA_ROOT"; - return std::nullopt; - } - third_party_dir = third_party_dir.AppendASCII("third_party"); - - std::vector ret = { - third_party_dir.AppendASCII("pywebsocket3").AppendASCII("src"), - }; - - return ret; -} - -bool LocalTestServer::AddCommandLineArguments( - base::CommandLine* command_line) const { - std::optional arguments_dict = GenerateArguments(); - if (!arguments_dict) - return false; - - // Serialize the argument dictionary into CommandLine. - for (auto it = arguments_dict->begin(); it != arguments_dict->end(); ++it) { - const base::Value& value = it->second; - const std::string& key = it->first; - - // Add arguments from a list. - if (value.is_list()) { - if (value.GetList().empty()) - return false; - for (const auto& entry : value.GetList()) { - if (!AppendArgumentFromJSONValue(key, entry, command_line)) - return false; - } - } else if (!AppendArgumentFromJSONValue(key, value, command_line)) { - return false; - } - } - - // Append the appropriate server type argument. - switch (type()) { - case TYPE_WS: - case TYPE_WSS: - command_line->AppendArg("--websocket"); - break; - case TYPE_BASIC_AUTH_PROXY: - command_line->AppendArg("--basic-auth-proxy"); - break; - case TYPE_PROXY: - command_line->AppendArg("--proxy"); - break; - default: - NOTREACHED(); - } - - return true; -} - -} // namespace net diff --git a/naiveproxy/src/net/test/spawned_test_server/local_test_server.h b/naiveproxy/src/net/test/spawned_test_server/local_test_server.h deleted file mode 100644 index 4a39362874..0000000000 --- a/naiveproxy/src/net/test/spawned_test_server/local_test_server.h +++ /dev/null @@ -1,102 +0,0 @@ -// 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 NET_TEST_SPAWNED_TEST_SERVER_LOCAL_TEST_SERVER_H_ -#define NET_TEST_SPAWNED_TEST_SERVER_LOCAL_TEST_SERVER_H_ - -#include -#include - -#include "base/files/file_util.h" -#include "base/files/scoped_file.h" -#include "base/process/process.h" -#include "build/build_config.h" -#include "net/test/spawned_test_server/base_test_server.h" - -#if BUILDFLAG(IS_WIN) -#include "base/win/scoped_handle.h" -#endif - -namespace base { -class CommandLine; -} - -namespace net { - -// The LocalTestServer runs an external Python-based test server in the -// same machine in which the LocalTestServer runs. -class LocalTestServer : public BaseTestServer { - public: - // Initialize a TestServer. |document_root| must be a relative path under the - // root tree. - LocalTestServer(Type type, const base::FilePath& document_root); - - // Initialize a TestServer with a specific set of SSLOptions. - // |document_root| must be a relative path under the root tree. - LocalTestServer(Type type, - const SSLOptions& ssl_options, - const base::FilePath& document_root); - - LocalTestServer(const LocalTestServer&) = delete; - LocalTestServer& operator=(const LocalTestServer&) = delete; - - ~LocalTestServer() override; - - // BaseTestServer overrides. - [[nodiscard]] bool StartInBackground() override; - [[nodiscard]] bool BlockUntilStarted() override; - - // Stop the server started by Start(). - bool Stop(); - - // Returns the directories to use as the PYTHONPATH, or nullopt on error. - virtual std::optional> GetPythonPath() const; - - // Returns true if the base::FilePath for the testserver python script is - // successfully stored in |*testserver_path|. - [[nodiscard]] virtual bool GetTestServerPath( - base::FilePath* testserver_path) const; - - // Adds the command line arguments for the Python test server to - // |command_line|. Returns true on success. - [[nodiscard]] virtual bool AddCommandLineArguments( - base::CommandLine* command_line) const; - - // Returns the actual path of document root for test cases. This function - // should be called by test cases to retrieve the actual document root path. - base::FilePath GetDocumentRoot() const { return document_root(); } - - private: - bool Init(const base::FilePath& document_root); - - // Launches the Python test server. Returns true on success. |testserver_path| - // is the path to the test server script. |python_path| is the list of - // directories to use as the PYTHONPATH environment variable. - [[nodiscard]] bool LaunchPython( - const base::FilePath& testserver_path, - const std::vector& python_path); - - // Waits for the server to start. Returns true on success. - [[nodiscard]] bool WaitToStart(); - - // The Python process running the test server. - base::Process process_; - -#if BUILDFLAG(IS_WIN) - // The pipe file handle we read from. - base::win::ScopedHandle child_read_fd_; - - // The pipe file handle the child and we write to. - base::win::ScopedHandle child_write_fd_; -#endif - -#if BUILDFLAG(IS_POSIX) - // The file descriptor the child writes to when it starts. - base::ScopedFD child_fd_; -#endif -}; - -} // namespace net - -#endif // NET_TEST_SPAWNED_TEST_SERVER_LOCAL_TEST_SERVER_H_ diff --git a/naiveproxy/src/net/test/spawned_test_server/local_test_server_posix.cc b/naiveproxy/src/net/test/spawned_test_server/local_test_server_posix.cc deleted file mode 100644 index 7a0e629b7c..0000000000 --- a/naiveproxy/src/net/test/spawned_test_server/local_test_server_posix.cc +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2012 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/spawned_test_server/local_test_server.h" - -#include -#include - -#include - -#include "base/command_line.h" -#include "base/containers/span.h" -#include "base/files/file_util.h" -#include "base/files/scoped_file.h" -#include "base/logging.h" -#include "base/path_service.h" -#include "base/process/kill.h" -#include "base/process/launch.h" -#include "base/process/process_iterator.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "net/test/python_utils.h" - -namespace { - -// Helper class used to detect and kill orphaned python test server processes. -// Checks if the command line of a process contains |path_string| (the path -// from which the test server was launched) and |port_string| (the port used by -// the test server), and if the parent pid of the process is 1 (indicating that -// it is an orphaned process). -class OrphanedTestServerFilter : public base::ProcessFilter { - public: - OrphanedTestServerFilter( - const std::string& path_string, const std::string& port_string) - : path_string_(path_string), - port_string_(port_string) {} - - OrphanedTestServerFilter(const OrphanedTestServerFilter&) = delete; - OrphanedTestServerFilter& operator=(const OrphanedTestServerFilter&) = delete; - - bool Includes(const base::ProcessEntry& entry) const override { - if (entry.parent_pid() != 1) - return false; - bool found_path_string = false; - bool found_port_string = false; - for (const auto& cmd_line_arg : entry.cmd_line_args()) { - if (cmd_line_arg.find(path_string_) != std::string::npos) - found_path_string = true; - if (cmd_line_arg.find(port_string_) != std::string::npos) - found_port_string = true; - } - return found_path_string && found_port_string; - } - - private: - std::string path_string_; - std::string port_string_; -}; - -// Given a file descriptor, reads into |buffer| until it's full or an error has -// been encountered. Returns true if the read was successful. -bool ReadData(int fd, base::span buffer) { - size_t initial_size = buffer.size(); - while (!buffer.empty()) { - struct pollfd poll_fds[1]; - - poll_fds[0].fd = fd; - poll_fds[0].events = POLLIN | POLLPRI; - poll_fds[0].revents = 0; - - // Each test itself has its own timeout, so no need to use one here. - int rv = HANDLE_EINTR(poll(poll_fds, 1, -1)); - if (rv == 0) { - LOG(ERROR) << "poll() timed out; bytes_read=" - << (initial_size - buffer.size()); - return false; - } else if (rv < 0) { - PLOG(ERROR) << "poll() failed for child file descriptor; bytes_read=" - << (initial_size - buffer.size()); - return false; - } - - ssize_t num_bytes = HANDLE_EINTR(read(fd, buffer.data(), buffer.size())); - if (num_bytes <= 0) - return false; - buffer.take_first(static_cast(num_bytes)); - } - return true; -} - -} // namespace - -namespace net { - -bool LocalTestServer::LaunchPython( - const base::FilePath& testserver_path, - const std::vector& python_path) { - base::CommandLine python_command(base::CommandLine::NO_PROGRAM); - if (!GetPython3Command(&python_command)) - return false; - - python_command.AppendArgPath(testserver_path); - if (!AddCommandLineArguments(&python_command)) - return false; - - int pipefd[2]; - if (pipe(pipefd) != 0) { - PLOG(ERROR) << "Could not create pipe."; - return false; - } - - // Save the read half. The write half is sent to the child. - child_fd_.reset(pipefd[0]); - base::ScopedFD write_closer(pipefd[1]); - - python_command.AppendArg("--startup-pipe=" + base::NumberToString(pipefd[1])); - - // Try to kill any orphaned testserver processes that may be running. - OrphanedTestServerFilter filter(testserver_path.value(), - base::NumberToString(GetPort())); - if (!base::KillProcesses("python", -1, &filter)) { - LOG(WARNING) << "Failed to clean up older orphaned testserver instances."; - } - - // Launch a new testserver process. - base::LaunchOptions options; - SetPythonPathInEnvironment(python_path, &options.environment); - - // Log is useful in the event you want to run a nearby script (e.g. a test) in - // the same environment as the TestServer. - LOG(ERROR) << "LaunchPython called with PYTHONPATH = " - << options.environment["PYTHONPATH"]; - - // Set CWD to source root. - if (!base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, - &options.current_directory)) { - LOG(ERROR) << "Failed to get DIR_SRC_TEST_DATA_ROOT"; - return false; - } - - options.fds_to_remap.emplace_back(pipefd[1], pipefd[1]); - LOG(ERROR) << "Running: " << python_command.GetCommandLineString(); - process_ = base::LaunchProcess(python_command, options); - if (!process_.IsValid()) { - LOG(ERROR) << "Failed to launch " << python_command.GetCommandLineString(); - return false; - } - - return true; -} - -bool LocalTestServer::WaitToStart() { - base::ScopedFD our_fd(child_fd_.release()); - - uint32_t server_data_len = 0; - if (!ReadData(our_fd.get(), base::byte_span_from_ref(server_data_len))) { - LOG(ERROR) << "Could not read server_data_len"; - return false; - } - std::string server_data(server_data_len, '\0'); - if (!ReadData(our_fd.get(), base::as_writable_byte_span(server_data))) { - LOG(ERROR) << "Could not read server_data (" << server_data_len - << " bytes)"; - return false; - } - - int port; - if (!SetAndParseServerData(server_data, &port)) { - LOG(ERROR) << "Could not parse server_data: " << server_data; - return false; - } - SetPort(port); - - return true; -} - -} // namespace net diff --git a/naiveproxy/src/net/test/spawned_test_server/local_test_server_win.cc b/naiveproxy/src/net/test/spawned_test_server/local_test_server_win.cc deleted file mode 100644 index f226d26bec..0000000000 --- a/naiveproxy/src/net/test/spawned_test_server/local_test_server_win.cc +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2012 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 "net/test/spawned_test_server/local_test_server.h" - -#include - -#include "base/base_paths.h" -#include "base/command_line.h" -#include "base/environment.h" -#include "base/files/file_path.h" -#include "base/functional/bind.h" -#include "base/logging.h" -#include "base/path_service.h" -#include "base/process/launch.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "base/win/scoped_handle.h" -#include "net/test/python_utils.h" - -namespace { - -// Given a file handle, reads into |buffer| until |bytes_max| bytes -// has been read or an error has been encountered. Returns -// true if the read was successful. -bool ReadData(HANDLE read_fd, - HANDLE write_fd, - DWORD bytes_max, - uint8_t* buffer) { - DWORD bytes_read = 0; - while (bytes_read < bytes_max) { - DWORD num_bytes; - if (!ReadFile(read_fd, buffer + bytes_read, bytes_max - bytes_read, - &num_bytes, nullptr)) { - PLOG(ERROR) << "ReadFile failed"; - return false; - } - if (num_bytes <= 0) { - LOG(ERROR) << "ReadFile returned invalid byte count: " << num_bytes; - return false; - } - bytes_read += num_bytes; - } - - return true; -} - -} // namespace - -namespace net { - -bool LocalTestServer::LaunchPython( - const base::FilePath& testserver_path, - const std::vector& python_path) { - base::CommandLine python_command(base::CommandLine::NO_PROGRAM); - if (!GetPython3Command(&python_command)) - return false; - - python_command.AppendArgPath(testserver_path); - if (!AddCommandLineArguments(&python_command)) - return false; - - HANDLE child_read = nullptr; - HANDLE child_write = nullptr; - if (!CreatePipe(&child_read, &child_write, nullptr, 0)) { - PLOG(ERROR) << "Failed to create pipe"; - return false; - } - child_read_fd_.Set(child_read); - child_write_fd_.Set(child_write); - - // Have the child inherit the write half. - if (!::DuplicateHandle(::GetCurrentProcess(), child_write, - ::GetCurrentProcess(), &child_write, 0, TRUE, - DUPLICATE_SAME_ACCESS)) { - PLOG(ERROR) << "Failed to enable pipe inheritance"; - return false; - } - - // Pass the handle on the command-line. Although HANDLE is a - // pointer, truncating it on 64-bit machines is okay. See - // http://msdn.microsoft.com/en-us/library/aa384203.aspx - // - // "64-bit versions of Windows use 32-bit handles for - // interoperability. When sharing a handle between 32-bit and 64-bit - // applications, only the lower 32 bits are significant, so it is - // safe to truncate the handle (when passing it from 64-bit to - // 32-bit) or sign-extend the handle (when passing it from 32-bit to - // 64-bit)." - python_command.AppendArg( - "--startup-pipe=" + - base::NumberToString(reinterpret_cast(child_write))); - - base::LaunchOptions launch_options; - SetPythonPathInEnvironment(python_path, &launch_options.environment); - - // Set CWD to source root. - if (!base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, - &launch_options.current_directory)) { - LOG(ERROR) << "Failed to get DIR_SRC_TEST_DATA_ROOT"; - return false; - } - - // TODO(brettw) bug 748258: Share only explicit handles. - launch_options.inherit_mode = base::LaunchOptions::Inherit::kAll; - process_ = base::LaunchProcess(python_command, launch_options); - if (!process_.IsValid()) { - LOG(ERROR) << "Failed to launch " << python_command.GetCommandLineString(); - ::CloseHandle(child_write); - return false; - } - - ::CloseHandle(child_write); - return true; -} - -bool LocalTestServer::WaitToStart() { - base::win::ScopedHandle read_fd(child_read_fd_.Take()); - base::win::ScopedHandle write_fd(child_write_fd_.Take()); - - uint32_t server_data_len = 0; - if (!ReadData(read_fd.Get(), write_fd.Get(), sizeof(server_data_len), - reinterpret_cast(&server_data_len))) { - LOG(ERROR) << "Could not read server_data_len"; - return false; - } - std::string server_data(server_data_len, '\0'); - if (!ReadData(read_fd.Get(), write_fd.Get(), server_data_len, - reinterpret_cast(&server_data[0]))) { - LOG(ERROR) << "Could not read server_data (" << server_data_len - << " bytes)"; - return false; - } - - int port; - if (!SetAndParseServerData(server_data, &port)) { - LOG(ERROR) << "Could not parse server_data: " << server_data; - return false; - } - SetPort(port); - - return true; -} - -} // namespace net diff --git a/naiveproxy/src/net/test/spawned_test_server/remote_test_server.cc b/naiveproxy/src/net/test/spawned_test_server/remote_test_server.cc deleted file mode 100644 index 476a9f2e6c..0000000000 --- a/naiveproxy/src/net/test/spawned_test_server/remote_test_server.cc +++ /dev/null @@ -1,228 +0,0 @@ -// 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. - -#include "net/test/spawned_test_server/remote_test_server.h" - -#include - -#include -#include - -#include "base/base_paths.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/json/json_reader.h" -#include "base/json/json_writer.h" -#include "base/logging.h" -#include "base/message_loop/message_pump_type.h" -#include "base/path_service.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_split.h" -#include "base/strings/stringprintf.h" -#include "base/threading/thread_restrictions.h" -#include "base/values.h" -#include "build/build_config.h" -#include "net/base/host_port_pair.h" -#include "net/base/ip_endpoint.h" -#include "net/base/net_errors.h" -#include "net/test/spawned_test_server/remote_test_server_spawner_request.h" -#include "url/gurl.h" - -namespace net { - -namespace { - -// Please keep in sync with dictionary SERVER_TYPES in testserver.py -std::string GetServerTypeString(BaseTestServer::Type type) { - switch (type) { - case BaseTestServer::TYPE_WS: - case BaseTestServer::TYPE_WSS: - return "ws"; - default: - NOTREACHED(); - } -} - -#if !BUILDFLAG(IS_FUCHSIA) -// Returns platform-specific path to the config file for the test server. -base::FilePath GetTestServerConfigFilePath() { - base::FilePath dir; -#if BUILDFLAG(IS_ANDROID) - base::PathService::Get(base::DIR_ANDROID_EXTERNAL_STORAGE, &dir); -#else - base::PathService::Get(base::DIR_TEMP, &dir); -#endif - return dir.AppendASCII("net-test-server-config"); -} -#endif // !BUILDFLAG(IS_FUCHSIA) - -// Reads base URL for the test server spawner. That URL is used to control the -// test server. -std::string GetSpawnerUrlBase() { -#if BUILDFLAG(IS_FUCHSIA) - std::string spawner_url_base( - base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - "remote-test-server-spawner-url-base")); - LOG_IF(FATAL, spawner_url_base.empty()) - << "--remote-test-server-spawner-url-base missing from command line"; - return spawner_url_base; -#else // BUILDFLAG(IS_FUCHSIA) - base::ScopedAllowBlockingForTesting allow_blocking; - - base::FilePath config_path = GetTestServerConfigFilePath(); - - if (!base::PathExists(config_path)) - return ""; - - std::string config_json; - if (!ReadFileToString(config_path, &config_json)) - LOG(FATAL) << "Failed to read " << config_path.value(); - - std::optional config = base::JSONReader::Read(config_json); - if (!config) - LOG(FATAL) << "Failed to parse " << config_path.value(); - - std::string* result = config->GetDict().FindString("spawner_url_base"); - if (!result) - LOG(FATAL) << "spawner_url_base is not specified in the config"; - - return *result; -#endif // BUILDFLAG(IS_FUCHSIA) -} - -} // namespace - -RemoteTestServer::RemoteTestServer(Type type, - const base::FilePath& document_root) - : BaseTestServer(type), io_thread_("RemoteTestServer IO Thread") { - if (!Init(document_root)) { - NOTREACHED(); - } -} - -RemoteTestServer::RemoteTestServer(Type type, - const SSLOptions& ssl_options, - const base::FilePath& document_root) - : BaseTestServer(type, ssl_options), - io_thread_("RemoteTestServer IO Thread") { - if (!Init(document_root)) { - NOTREACHED(); - } -} - -RemoteTestServer::~RemoteTestServer() { - Stop(); -} - -bool RemoteTestServer::StartInBackground() { - DCHECK(!started()); - DCHECK(!start_request_); - - std::optional arguments_dict = GenerateArguments(); - if (!arguments_dict) - return false; - - arguments_dict->Set("on-remote-server", base::Value()); - - // Append the 'server-type' argument which is used by spawner server to - // pass right server type to Python test server. - arguments_dict->Set("server-type", GetServerTypeString(type())); - - // Generate JSON-formatted argument string. - std::string arguments_string; - base::JSONWriter::Write(*arguments_dict, &arguments_string); - if (arguments_string.empty()) - return false; - - start_request_ = std::make_unique( - io_thread_.task_runner(), GetSpawnerUrl("start"), arguments_string); - - return true; -} - -bool RemoteTestServer::BlockUntilStarted() { - DCHECK(start_request_); - - std::string server_data_json; - bool request_result = start_request_->WaitForCompletion(&server_data_json); - start_request_.reset(); - if (!request_result) - return false; - - // Parse server_data_json. - if (server_data_json.empty() || - !SetAndParseServerData(server_data_json, &remote_port_)) { - LOG(ERROR) << "Could not parse server_data: " << server_data_json; - return false; - } - - SetPort(remote_port_); - - return SetupWhenServerStarted(); -} - -bool RemoteTestServer::Stop() { - DCHECK(!start_request_); - - if (remote_port_) { - std::unique_ptr kill_request = - std::make_unique( - io_thread_.task_runner(), - GetSpawnerUrl(base::StringPrintf("kill?port=%d", remote_port_)), - std::string()); - - if (!kill_request->WaitForCompletion(nullptr)) - LOG(FATAL) << "Failed stopping RemoteTestServer"; - - remote_port_ = 0; - } - - CleanUpWhenStoppingServer(); - - return true; -} - -// On Android, the document root in the device is not the same as the document -// root in the host machine where the test server is launched. So prepend -// DIR_SRC_TEST_DATA_ROOT here to get the actual path of document root on the -// Android device. -base::FilePath RemoteTestServer::GetDocumentRoot() const { - base::FilePath src_dir; - base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &src_dir); - return src_dir.Append(document_root()); -} - -bool RemoteTestServer::Init(const base::FilePath& document_root) { - if (document_root.IsAbsolute()) - return false; - - spawner_url_base_ = GetSpawnerUrlBase(); - - bool thread_started = io_thread_.StartWithOptions( - base::Thread::Options(base::MessagePumpType::IO, 0)); - CHECK(thread_started); - - // Unlike LocalTestServer, RemoteTestServer passes relative paths to the test - // server. The test server fails on empty strings in some configurations. - base::FilePath fixed_root = document_root; - if (fixed_root.empty()) - fixed_root = base::FilePath(base::FilePath::kCurrentDirectory); - SetResourcePath(fixed_root, base::FilePath() - .AppendASCII("net") - .AppendASCII("data") - .AppendASCII("ssl") - .AppendASCII("certificates")); - return true; -} - -GURL RemoteTestServer::GetSpawnerUrl(const std::string& command) const { - CHECK(!spawner_url_base_.empty()); - std::string url = spawner_url_base_ + "/" + command; - GURL result = GURL(url); - CHECK(result.is_valid()) << url; - return result; -} - -} // namespace net diff --git a/naiveproxy/src/net/test/spawned_test_server/remote_test_server.h b/naiveproxy/src/net/test/spawned_test_server/remote_test_server.h deleted file mode 100644 index 08fdec3c56..0000000000 --- a/naiveproxy/src/net/test/spawned_test_server/remote_test_server.h +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2012 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_SPAWNED_TEST_SERVER_REMOTE_TEST_SERVER_H_ -#define NET_TEST_SPAWNED_TEST_SERVER_REMOTE_TEST_SERVER_H_ - -#include - -#include "base/threading/thread.h" -#include "net/test/spawned_test_server/base_test_server.h" - -namespace net { - -class RemoteTestServerSpawnerRequest; - -// The RemoteTestServer runs an external Python-based test server in another -// machine that is different from the machine that executes the tests. It is -// necessary because it's not always possible to run the test server on the same -// machine (it doesn't run on Android and Fuchsia because it's written in -// Python). -// -// The actual test server is executed on the host machine, while the unit tests -// themselves continue running on the device. To control the test server on the -// host machine, a second HTTP server is started, the spawner server, which -// controls the life cycle of remote test servers. Calls to start/kill the -// SpawnedTestServer are then redirected to the spawner server via -// this spawner communicator. The spawner is implemented in -// build/util/lib/common/chrome_test_server_spawner.py . -// -// On Fuchsia, the URL for the spawner server is passed to a test via the -// --remote-test-server-spawner-url-base switch on the command line. On other -// platforms, the URL is discovered by reading config file that's expected to be -// written on the test device by the test scrips. Location of the config -// dependends on platform: -// - Android: DIR_ANDROID_EXTERNAL_STORAGE/net-test-server-config -// - other: DIR_TEMP/net-test-server-config -// -// The config file must be stored in the following format: -// { -// 'spawner_url_base': 'http://localhost:5000' -// } -// -// 'spawner_url_base' specifies base URL for the spawner. -// -// Currently the following two commands are supported by spawner. -// -// (1) Start Python test server, format is: -// Path: "/start". -// Method: "POST". -// Data to server: all arguments needed to launch the Python test server, in -// JSON format. -// Data from server: a JSON dict includes the following two field if success, -// "port": the port the Python test server actually listen on that. -// "message": must be "started". -// -// (2) Kill Python test server, format is: -// Path: "/kill". -// Method: "GET". -// Data to server: port=. -// Data from server: String "killed" returned if success. -// -// The internal I/O thread is required by net stack to perform net I/O. -// The Start/StopServer methods block the caller thread until result is -// fetched from spawner server or timed-out. -class RemoteTestServer : public BaseTestServer { - public: - // Initialize a TestServer. |document_root| must be a relative path under the - // root tree. - RemoteTestServer(Type type, const base::FilePath& document_root); - - // Initialize a TestServer with a specific set of SSLOptions. - // |document_root| must be a relative path under the root tree. - RemoteTestServer(Type type, - const SSLOptions& ssl_options, - const base::FilePath& document_root); - - RemoteTestServer(const RemoteTestServer&) = delete; - RemoteTestServer& operator=(const RemoteTestServer&) = delete; - - ~RemoteTestServer() override; - - // BaseTestServer overrides. - [[nodiscard]] bool StartInBackground() override; - [[nodiscard]] bool BlockUntilStarted() override; - - // Stops the Python test server that is running on the host machine. - bool Stop(); - - // Returns the actual path of document root for the test cases. This function - // should be called by test cases to retrieve the actual document root path - // on the Android device, otherwise document_root() function is used to get - // the document root. - base::FilePath GetDocumentRoot() const; - - private: - bool Init(const base::FilePath& document_root); - - // Returns URL for the specified spawner |command|. - GURL GetSpawnerUrl(const std::string& command) const; - - // URL of the test server spawner. Read from the config file during - // initialization. - std::string spawner_url_base_; - - // Thread used to run all IO activity in RemoteTestServerSpawnerRequest and - // |ocsp_proxy_|. - base::Thread io_thread_; - - std::unique_ptr start_request_; - - // Server port. Non-zero when the server is running. - int remote_port_ = 0; -}; - -} // namespace net - -#endif // NET_TEST_SPAWNED_TEST_SERVER_REMOTE_TEST_SERVER_H_ diff --git a/naiveproxy/src/net/test/spawned_test_server/remote_test_server_spawner_request.cc b/naiveproxy/src/net/test/spawned_test_server/remote_test_server_spawner_request.cc deleted file mode 100644 index a06f90c37f..0000000000 --- a/naiveproxy/src/net/test/spawned_test_server/remote_test_server_spawner_request.cc +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright 2017 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/spawned_test_server/remote_test_server_spawner_request.h" - -#include -#include - -#include "base/functional/bind.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/synchronization/waitable_event.h" -#include "base/task/single_thread_task_runner.h" -#include "build/build_config.h" -#include "net/base/elements_upload_data_stream.h" -#include "net/base/io_buffer.h" -#include "net/base/port_util.h" -#include "net/base/upload_bytes_element_reader.h" -#include "net/http/http_response_headers.h" -#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" -#include "net/url_request/url_request.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_context_builder.h" -#include "net/url_request/url_request_test_util.h" -#include "url/gurl.h" - -namespace net { - -static const int kBufferSize = 2048; - -class RemoteTestServerSpawnerRequest::Core : public URLRequest::Delegate { - public: - Core(); - - Core(const Core&) = delete; - Core& operator=(const Core&) = delete; - - ~Core() override; - - void SendRequest(const GURL& url, const std::string& post_data); - - // Blocks until request is finished. If |response| isn't nullptr then server - // response is copied to *response. Returns true if the request was completed - // successfully. - [[nodiscard]] bool WaitForCompletion(std::string* response); - - private: - // URLRequest::Delegate methods. - void OnResponseStarted(URLRequest* request, int net_error) override; - void OnReadCompleted(URLRequest* request, int num_bytes) override; - - void ReadResponse(); - void OnCommandCompleted(int net_error); - - // Request results. - int result_code_ = 0; - std::string data_received_; - - // WaitableEvent to notify when the request is finished. - base::WaitableEvent event_; - - std::unique_ptr context_; - std::unique_ptr request_; - - scoped_refptr read_buffer_; - - THREAD_CHECKER(thread_checker_); -}; - -RemoteTestServerSpawnerRequest::Core::Core() - : event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED), - read_buffer_(base::MakeRefCounted(kBufferSize)) { - DETACH_FROM_THREAD(thread_checker_); -} - -void RemoteTestServerSpawnerRequest::Core::SendRequest( - const GURL& url, - const std::string& post_data) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - // Prepare the URLRequest for sending the command. - DCHECK(!request_.get()); - context_ = CreateTestURLRequestContextBuilder()->Build(); - request_ = context_->CreateRequest(url, DEFAULT_PRIORITY, this, - TRAFFIC_ANNOTATION_FOR_TESTS); - - if (post_data.empty()) { - request_->set_method("GET"); - } else { - request_->set_method("POST"); - std::unique_ptr reader( - UploadOwnedBytesElementReader::CreateWithString(post_data)); - request_->set_upload( - ElementsUploadDataStream::CreateWithReader(std::move(reader))); - request_->SetExtraRequestHeaderByName(HttpRequestHeaders::kContentType, - "application/json", - /*overwrite=*/true); - } - - request_->Start(); -} - -RemoteTestServerSpawnerRequest::Core::~Core() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); -} - -bool RemoteTestServerSpawnerRequest::Core::WaitForCompletion( - std::string* response) { - // Called by RemoteTestServerSpawnerRequest::WaitForCompletion() on the main - // thread. - - event_.Wait(); - if (response) - *response = data_received_; - return result_code_ == OK; -} - -void RemoteTestServerSpawnerRequest::Core::OnCommandCompleted(int net_error) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK_NE(ERR_IO_PENDING, net_error); - DCHECK(!event_.IsSignaled()); - - // If request has failed, return the error code. - if (net_error != OK) { - LOG(ERROR) << "request failed, error: " << ErrorToString(net_error); - result_code_ = net_error; - } else if (request_->GetResponseCode() != 200) { - LOG(ERROR) << "Spawner server returned bad status: " - << request_->response_headers()->GetStatusLine() << ", " - << data_received_; - result_code_ = ERR_FAILED; - } - - if (result_code_ != OK) - data_received_.clear(); - - request_.reset(); - context_.reset(); - - event_.Signal(); -} - -void RemoteTestServerSpawnerRequest::Core::ReadResponse() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - while (true) { - int result = request_->Read(read_buffer_.get(), kBufferSize); - if (result == ERR_IO_PENDING) - return; - - if (result <= 0) { - OnCommandCompleted(result); - return; - } - - data_received_.append(read_buffer_->data(), result); - } -} - -void RemoteTestServerSpawnerRequest::Core::OnResponseStarted( - URLRequest* request, - int net_error) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK_NE(ERR_IO_PENDING, net_error); - DCHECK_EQ(request, request_.get()); - - if (net_error != OK) { - OnCommandCompleted(net_error); - return; - } - - ReadResponse(); -} - -void RemoteTestServerSpawnerRequest::Core::OnReadCompleted(URLRequest* request, - int read_result) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK_NE(ERR_IO_PENDING, read_result); - DCHECK_EQ(request, request_.get()); - - if (read_result <= 0) { - OnCommandCompleted(read_result); - return; - } - - data_received_.append(read_buffer_->data(), read_result); - - ReadResponse(); -} - -RemoteTestServerSpawnerRequest::RemoteTestServerSpawnerRequest( - scoped_refptr io_task_runner, - const GURL& url, - const std::string& post_data) - : io_task_runner_(io_task_runner), - core_(std::make_unique()), - allowed_port_( - std::make_unique(url.EffectiveIntPort())) { - io_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&Core::SendRequest, - base::Unretained(core_.get()), url, post_data)); -} - -RemoteTestServerSpawnerRequest::~RemoteTestServerSpawnerRequest() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - io_task_runner_->DeleteSoon(FROM_HERE, core_.release()); -} - -bool RemoteTestServerSpawnerRequest::WaitForCompletion(std::string* response) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return core_->WaitForCompletion(response); -} - -} // namespace net diff --git a/naiveproxy/src/net/test/spawned_test_server/remote_test_server_spawner_request.h b/naiveproxy/src/net/test/spawned_test_server/remote_test_server_spawner_request.h deleted file mode 100644 index 90d4fbfc51..0000000000 --- a/naiveproxy/src/net/test/spawned_test_server/remote_test_server_spawner_request.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2017 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_SPAWNED_TEST_SERVER_REMOTE_TEST_SERVER_SPAWNER_REQUEST_H_ -#define NET_TEST_SPAWNED_TEST_SERVER_REMOTE_TEST_SERVER_SPAWNER_REQUEST_H_ - -#include -#include - -#include "base/memory/scoped_refptr.h" -#include "base/threading/thread_checker.h" - -class GURL; - -namespace base { -class SingleThreadTaskRunner; -} // namespace base - -namespace net { - -class ScopedPortException; - -// RemoteTestServerSpawnerRequest is used by RemoteTestServer to send a request -// to the test server spawner. -class RemoteTestServerSpawnerRequest { - public: - // Queries the specified URL. If |post_data| is empty then a GET request is - // sent. Otherwise |post_data| must be a json blob which is sent as a POST - // request body. - RemoteTestServerSpawnerRequest( - scoped_refptr io_task_runner, - const GURL& url, - const std::string& post_data); - - RemoteTestServerSpawnerRequest(const RemoteTestServerSpawnerRequest&) = - delete; - RemoteTestServerSpawnerRequest& operator=( - const RemoteTestServerSpawnerRequest&) = delete; - - ~RemoteTestServerSpawnerRequest(); - - // Blocks until request is finished. If |response| isn't nullptr then server - // response is copied to *response. Returns true if the request was completed - // successfully. - [[nodiscard]] bool WaitForCompletion(std::string* response); - - private: - class Core; - - scoped_refptr io_task_runner_; - - // Core runs on |io_task_runner_|. It's responsible for sending the request - // and reading the response. - std::unique_ptr core_; - - // Helper to add spawner port to the list of the globally explicitly allowed - // ports. It needs to be here instead of in Core because ScopedPortException - // is not thread-safe. - std::unique_ptr allowed_port_; - - THREAD_CHECKER(thread_checker_); -}; - -} // namespace net - -#endif // NET_TEST_SPAWNED_TEST_SERVER_REMOTE_TEST_SERVER_SPAWNER_REQUEST_H_ diff --git a/naiveproxy/src/net/test/spawned_test_server/spawned_test_server.h b/naiveproxy/src/net/test/spawned_test_server/spawned_test_server.h deleted file mode 100644 index 0213b023b0..0000000000 --- a/naiveproxy/src/net/test/spawned_test_server/spawned_test_server.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 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_SPAWNED_TEST_SERVER_SPAWNED_TEST_SERVER_H_ -#define NET_TEST_SPAWNED_TEST_SERVER_SPAWNED_TEST_SERVER_H_ - -#include "build/build_config.h" - -#if defined(USE_REMOTE_TEST_SERVER) -#include "net/test/spawned_test_server/remote_test_server.h" -#else -#include "net/test/spawned_test_server/local_test_server.h" -#endif - -namespace net { - -#if defined(USE_REMOTE_TEST_SERVER) -typedef RemoteTestServer SpawnedTestServer; -#else -typedef LocalTestServer SpawnedTestServer; -#endif - -} // namespace net - -#endif // NET_TEST_SPAWNED_TEST_SERVER_SPAWNED_TEST_SERVER_H_ diff --git a/naiveproxy/src/net/test/ssl_test_util.cc b/naiveproxy/src/net/test/ssl_test_util.cc index 7484017353..b16ae8823d 100644 --- a/naiveproxy/src/net/test/ssl_test_util.cc +++ b/naiveproxy/src/net/test/ssl_test_util.cc @@ -2,16 +2,12 @@ // 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 "net/test/ssl_test_util.h" #include #include +#include "base/compiler_specific.h" #include "third_party/boringssl/src/include/openssl/hpke.h" namespace net { @@ -46,8 +42,9 @@ bssl::UniquePtr MakeTestEchKeys( } bssl::UniquePtr scoped_ech_config_list(ech_config_list_raw); - ech_config_list->assign(ech_config_list_raw, - ech_config_list_raw + ech_config_list_len); + ech_config_list->assign( + ech_config_list_raw, + UNSAFE_TODO(ech_config_list_raw + ech_config_list_len)); return keys; } diff --git a/naiveproxy/src/net/test/test_data_directory.cc b/naiveproxy/src/net/test/test_data_directory.cc index 8b9a4f939a..c294516a4f 100644 --- a/naiveproxy/src/net/test/test_data_directory.cc +++ b/naiveproxy/src/net/test/test_data_directory.cc @@ -47,9 +47,4 @@ base::FilePath GetTestClientCertsDirectory() { return base::FilePath(kNetDataRelativePath).Append(kCertificateDataSubPath); } -base::FilePath GetWebSocketTestDataDirectory() { - base::FilePath data_dir(FILE_PATH_LITERAL("net/data/websocket")); - return data_dir; -} - } // namespace net diff --git a/naiveproxy/src/net/test/test_data_directory.h b/naiveproxy/src/net/test/test_data_directory.h index b5b59415fa..60946fa941 100644 --- a/naiveproxy/src/net/test/test_data_directory.h +++ b/naiveproxy/src/net/test/test_data_directory.h @@ -27,11 +27,6 @@ base::FilePath GetTestCertsDirectory(); // instead. base::FilePath GetTestClientCertsDirectory(); -// Returns the base::FilePath object representing the relative path containing -// resource files for testing WebSocket. Typically the FilePath will be used as -// document root argument for net::SpawnedTestServer with TYPE_WS or TYPE_WSS. -base::FilePath GetWebSocketTestDataDirectory(); - } // namespace net #endif // NET_TEST_TEST_DATA_DIRECTORY_H_ diff --git a/naiveproxy/src/net/third_party/quiche/BUILD.gn b/naiveproxy/src/net/third_party/quiche/BUILD.gn index 18965baece..dfc46ec144 100644 --- a/naiveproxy/src/net/third_party/quiche/BUILD.gn +++ b/naiveproxy/src/net/third_party/quiche/BUILD.gn @@ -87,6 +87,10 @@ component("quiche") { ] defines = [ "IS_QUICHE_IMPL" ] + + # TODO(crbug.com/40031409): Fix code that adds exit-time destructors and + # enable the diagnostic by removing this line. + configs += [ "//build/config/compiler:no_exit_time_destructors" ] } proto_library("net_quic_proto") { diff --git a/naiveproxy/src/net/third_party/quiche/src/.bazelrc b/naiveproxy/src/net/third_party/quiche/src/.bazelrc index 3b2dcc026e..497497d3f1 100644 --- a/naiveproxy/src/net/third_party/quiche/src/.bazelrc +++ b/naiveproxy/src/net/third_party/quiche/src/.bazelrc @@ -1,7 +1,7 @@ # Automatically detect host platform to pick config common --enable_platform_specific_config -build --cxxopt=-std=c++17 +build --cxxopt=-std=c++20 build --cxxopt=-fno-rtti # Enable Abseil/Googletest integration 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 0bbd9b2e21..2c9819717f 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 @@ -1557,7 +1557,6 @@ moqt_hdrs = [ "quic/moqt/moqt_session_interface.h", "quic/moqt/moqt_subscribe_windows.h", "quic/moqt/moqt_track.h", - "quic/moqt/test_tools/mock_moqt_session.h", "quic/moqt/test_tools/moqt_framer_utils.h", "quic/moqt/test_tools/moqt_parser_test_visitor.h", "quic/moqt/test_tools/moqt_session_peer.h", @@ -1597,8 +1596,6 @@ moqt_srcs = [ "quic/moqt/moqt_subscribe_windows_test.cc", "quic/moqt/moqt_track.cc", "quic/moqt/moqt_track_test.cc", - "quic/moqt/test_tools/mock_moqt_session.cc", - "quic/moqt/test_tools/mock_moqt_session_test.cc", "quic/moqt/test_tools/moqt_framer_utils.cc", "quic/moqt/test_tools/moqt_simulator_harness.cc", "quic/moqt/tools/chat_client.cc", @@ -1713,6 +1710,7 @@ blind_sign_auth_hdrs = [ "blind_sign_auth/blind_sign_auth.h", "blind_sign_auth/blind_sign_auth_interface.h", "blind_sign_auth/blind_sign_auth_protos.h", + "blind_sign_auth/blind_sign_auth_test_data.h", "blind_sign_auth/blind_sign_message_interface.h", "blind_sign_auth/blind_sign_message_response.h", "blind_sign_auth/cached_blind_sign_auth.h", @@ -1721,6 +1719,7 @@ blind_sign_auth_hdrs = [ ] blind_sign_auth_srcs = [ "blind_sign_auth/blind_sign_auth.cc", + "blind_sign_auth/blind_sign_auth_test_data.cc", "blind_sign_auth/blind_sign_message_response.cc", "blind_sign_auth/cached_blind_sign_auth.cc", ] @@ -1728,10 +1727,12 @@ blind_sign_auth_tests_hdrs = [ ] blind_sign_auth_tests_srcs = [ "blind_sign_auth/blind_sign_auth_test.cc", + "blind_sign_auth/blind_sign_auth_test_data_test.cc", "blind_sign_auth/cached_blind_sign_auth_test.cc", ] protobuf_blind_sign_auth = [ "blind_sign_auth/proto/any.proto", + "blind_sign_auth/proto/attest_and_sign.proto", "blind_sign_auth/proto/attestation.proto", "blind_sign_auth/proto/auth_and_sign.proto", "blind_sign_auth/proto/blind_sign_auth_options.proto", 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 54bbd26159..6be36a6fd2 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 @@ -1561,7 +1561,6 @@ moqt_hdrs = [ "src/quiche/quic/moqt/moqt_session_interface.h", "src/quiche/quic/moqt/moqt_subscribe_windows.h", "src/quiche/quic/moqt/moqt_track.h", - "src/quiche/quic/moqt/test_tools/mock_moqt_session.h", "src/quiche/quic/moqt/test_tools/moqt_framer_utils.h", "src/quiche/quic/moqt/test_tools/moqt_parser_test_visitor.h", "src/quiche/quic/moqt/test_tools/moqt_session_peer.h", @@ -1601,8 +1600,6 @@ moqt_srcs = [ "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/mock_moqt_session.cc", - "src/quiche/quic/moqt/test_tools/mock_moqt_session_test.cc", "src/quiche/quic/moqt/test_tools/moqt_framer_utils.cc", "src/quiche/quic/moqt/test_tools/moqt_simulator_harness.cc", "src/quiche/quic/moqt/tools/chat_client.cc", @@ -1717,6 +1714,7 @@ blind_sign_auth_hdrs = [ "src/quiche/blind_sign_auth/blind_sign_auth.h", "src/quiche/blind_sign_auth/blind_sign_auth_interface.h", "src/quiche/blind_sign_auth/blind_sign_auth_protos.h", + "src/quiche/blind_sign_auth/blind_sign_auth_test_data.h", "src/quiche/blind_sign_auth/blind_sign_message_interface.h", "src/quiche/blind_sign_auth/blind_sign_message_response.h", "src/quiche/blind_sign_auth/cached_blind_sign_auth.h", @@ -1725,6 +1723,7 @@ blind_sign_auth_hdrs = [ ] blind_sign_auth_srcs = [ "src/quiche/blind_sign_auth/blind_sign_auth.cc", + "src/quiche/blind_sign_auth/blind_sign_auth_test_data.cc", "src/quiche/blind_sign_auth/blind_sign_message_response.cc", "src/quiche/blind_sign_auth/cached_blind_sign_auth.cc", ] @@ -1733,10 +1732,12 @@ blind_sign_auth_tests_hdrs = [ ] blind_sign_auth_tests_srcs = [ "src/quiche/blind_sign_auth/blind_sign_auth_test.cc", + "src/quiche/blind_sign_auth/blind_sign_auth_test_data_test.cc", "src/quiche/blind_sign_auth/cached_blind_sign_auth_test.cc", ] protobuf_blind_sign_auth = [ "src/quiche/blind_sign_auth/proto/any.proto", + "src/quiche/blind_sign_auth/proto/attest_and_sign.proto", "src/quiche/blind_sign_auth/proto/attestation.proto", "src/quiche/blind_sign_auth/proto/auth_and_sign.proto", "src/quiche/blind_sign_auth/proto/blind_sign_auth_options.proto", 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 98306758b5..19b4cdfca8 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 @@ -1560,7 +1560,6 @@ "quiche/quic/moqt/moqt_session_interface.h", "quiche/quic/moqt/moqt_subscribe_windows.h", "quiche/quic/moqt/moqt_track.h", - "quiche/quic/moqt/test_tools/mock_moqt_session.h", "quiche/quic/moqt/test_tools/moqt_framer_utils.h", "quiche/quic/moqt/test_tools/moqt_parser_test_visitor.h", "quiche/quic/moqt/test_tools/moqt_session_peer.h", @@ -1600,8 +1599,6 @@ "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/mock_moqt_session.cc", - "quiche/quic/moqt/test_tools/mock_moqt_session_test.cc", "quiche/quic/moqt/test_tools/moqt_framer_utils.cc", "quiche/quic/moqt/test_tools/moqt_simulator_harness.cc", "quiche/quic/moqt/tools/chat_client.cc", @@ -1716,6 +1713,7 @@ "quiche/blind_sign_auth/blind_sign_auth.h", "quiche/blind_sign_auth/blind_sign_auth_interface.h", "quiche/blind_sign_auth/blind_sign_auth_protos.h", + "quiche/blind_sign_auth/blind_sign_auth_test_data.h", "quiche/blind_sign_auth/blind_sign_message_interface.h", "quiche/blind_sign_auth/blind_sign_message_response.h", "quiche/blind_sign_auth/cached_blind_sign_auth.h", @@ -1724,6 +1722,7 @@ ], "blind_sign_auth_srcs": [ "quiche/blind_sign_auth/blind_sign_auth.cc", + "quiche/blind_sign_auth/blind_sign_auth_test_data.cc", "quiche/blind_sign_auth/blind_sign_message_response.cc", "quiche/blind_sign_auth/cached_blind_sign_auth.cc" ], @@ -1732,10 +1731,12 @@ ], "blind_sign_auth_tests_srcs": [ "quiche/blind_sign_auth/blind_sign_auth_test.cc", + "quiche/blind_sign_auth/blind_sign_auth_test_data_test.cc", "quiche/blind_sign_auth/cached_blind_sign_auth_test.cc" ], "protobuf_blind_sign_auth": [ "quiche/blind_sign_auth/proto/any.proto", + "quiche/blind_sign_auth/proto/attest_and_sign.proto", "quiche/blind_sign_auth/proto/attestation.proto", "quiche/blind_sign_auth/proto/auth_and_sign.proto", "quiche/blind_sign_auth/proto/blind_sign_auth_options.proto", diff --git a/naiveproxy/src/net/third_party/quiche/src/build/test.bzl b/naiveproxy/src/net/third_party/quiche/src/build/test.bzl index 33bef08aa2..b3b9da8cac 100644 --- a/naiveproxy/src/net/third_party/quiche/src/build/test.bzl +++ b/naiveproxy/src/net/third_party/quiche/src/build/test.bzl @@ -2,6 +2,7 @@ load("@bazel_skylib//lib:dicts.bzl", "dicts") load("@bazel_skylib//lib:paths.bzl", "paths") +load("@rules_cc//cc:cc_test.bzl", "cc_test") def test_suite_from_source_list(name, srcs, **kwargs): """ @@ -21,7 +22,7 @@ def test_suite_from_source_list(name, srcs, **kwargs): extra_kwargs = {} if test_name == "end_to_end_test": extra_kwargs["shard_count"] = 16 - native.cc_test( + cc_test( name = test_name, srcs = [sourcefile], **dicts.add(kwargs, extra_kwargs) 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 552cc0927c..ad7dbd2fc2 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/BUILD.bazel +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/BUILD.bazel @@ -62,6 +62,7 @@ cc_library( "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", + "@com_google_absl//absl/strings:str_format", ], ) 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 0567386b76..42b9e417a3 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 @@ -84,6 +84,8 @@ const char* BalsaFrameEnums::ErrorCodeToString( return "CHUNK_LENGTH_OVERFLOW"; case INVALID_CHUNK_EXTENSION: return "INVALID_CHUNK_EXTENSION"; + case INVALID_CHUNK_FRAMING: + return "INVALID_CHUNK_FRAMING"; case CALLED_BYTES_SPLICED_WHEN_UNSAFE_TO_DO_SO: return "CALLED_BYTES_SPLICED_WHEN_UNSAFE_TO_DO_SO"; case CALLED_BYTES_SPLICED_AND_EXCEEDED_SAFE_SPLICE_AMOUNT: 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 00e081ac97..f6cce3facd 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 @@ -86,6 +86,7 @@ struct QUICHE_EXPORT BalsaFrameEnums { INVALID_CHUNK_LENGTH, CHUNK_LENGTH_OVERFLOW, INVALID_CHUNK_EXTENSION, + INVALID_CHUNK_FRAMING, // Other errors. CALLED_BYTES_SPLICED_WHEN_UNSAFE_TO_DO_SO, 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 c9cfae279f..9c356420eb 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 @@ -20,6 +20,8 @@ #include "quiche/balsa/balsa_headers.h" #include "quiche/balsa/balsa_visitor_interface.h" #include "quiche/balsa/header_properties.h" +#include "quiche/balsa/http_validation_policy.h" +#include "quiche/common/platform/api/quiche_flag_utils.h" #include "quiche/common/platform/api/quiche_logging.h" // When comparing characters (other than == and !=), cast to unsigned char @@ -1341,10 +1343,33 @@ size_t BalsaFrame::ProcessInput(const char* input, size_t size) { } const char c = *current; - if (HeaderFramingFound(c) != 0) { - // If we've found a "\r\n\r\n", then the message - // is done. + const int32_t framing_found = HeaderFramingFound(c); + if (framing_found != 0) { + // TODO(b/433557986) remove these code counts + if (framing_found == kValidTerm1 && is_request_) { + QUICHE_CODE_COUNT(balsa_frame_framing_found_valid_term1_request); + } else if (framing_found == kValidTerm1 && !is_request_) { + QUICHE_CODE_COUNT(balsa_frame_framing_found_valid_term1_response); + } else if (framing_found == kValidTerm2 && is_request_) { + QUICHE_CODE_COUNT(balsa_frame_framing_found_valid_term2_request); + } else if (framing_found == kValidTerm2 && !is_request_) { + QUICHE_CODE_COUNT(balsa_frame_framing_found_valid_term2_response); + } + + // If we've found the end of the chunk, then we're done. ++current; + + if (http_validation_policy() + .require_chunked_body_end_with_crlf_crlf && + framing_found != kValidTerm1) { + // https://datatracker.ietf.org/doc/html/rfc9112#name-chunked-transfer-coding + // The ABNF for chunked coding states that both `last-chunk` _and_ + // `chunked_body` must end with CR_LF, i.e. kValidTerm2 is not + // allowed. + HandleError(BalsaFrameEnums::INVALID_CHUNK_FRAMING); + return current - input; + } + parse_state_ = BalsaFrameEnums::MESSAGE_FULLY_READ; visitor_->OnRawBodyInput( absl::string_view(on_entry, current - on_entry)); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/header_properties.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/header_properties.cc index 17115b405d..b0e78912ed 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/header_properties.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/header_properties.cc @@ -5,8 +5,6 @@ #include "absl/container/flat_hash_set.h" #include "absl/strings/string_view.h" -#include "quiche/common/platform/api/quiche_flag_utils.h" -#include "quiche/common/platform/api/quiche_flags.h" #include "quiche/common/quiche_text_utils.h" namespace quiche::header_properties { 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 5c80f5ce98..80e0aec7e1 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 @@ -87,6 +87,10 @@ struct QUICHE_EXPORT HttpValidationPolicy { // If true, the parser rejects messages where there is a lone LF not preceded // by CR. bool disallow_lone_lf_in_chunk_extension = true; + + // If true, the parser rejects chunked messages that don't end with + // CR_LF_CR_LF. + bool require_chunked_body_end_with_crlf_crlf = false; }; } // namespace quiche diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/binary_http/binary_http_message.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/binary_http/binary_http_message.cc index cf95e34507..bc7a9b0867 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/binary_http/binary_http_message.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/binary_http/binary_http_message.cc @@ -10,11 +10,13 @@ #include #include +#include "absl/base/attributes.h" #include "absl/container/flat_hash_map.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/ascii.h" #include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" #include "absl/strings/str_join.h" #include "absl/strings/string_view.h" #include "quiche/common/quiche_callbacks.h" @@ -24,8 +26,17 @@ namespace quiche { namespace { -constexpr uint8_t kKnownLengthRequestFraming = 0; -constexpr uint8_t kKnownLengthResponseFraming = 1; +constexpr uint64_t kKnownLengthRequestFraming = 0; +constexpr uint64_t kKnownLengthResponseFraming = 1; +constexpr uint64_t kIndeterminateLengthRequestFraming = 2; +constexpr uint64_t kContentTerminator = 0; + +// A view of a field name and value. Used to pass around a field without owning +// or copying the backing data. +struct FieldView { + absl::string_view name; + absl::string_view value; +}; bool ReadStringValue(quiche::QuicheDataReader& reader, std::string& data) { absl::string_view data_view; @@ -59,6 +70,21 @@ absl::StatusOr DecodeControlData( return control_data; } +// Decodes a header/trailer name and value. This takes a length which represents +// only the name length. +absl::StatusOr DecodeField(QuicheDataReader& reader, + uint64_t name_length) { + absl::string_view name; + if (!reader.ReadStringPiece(&name, name_length)) { + return absl::OutOfRangeError("Not enough data to read field name."); + } + absl::string_view value; + if (!reader.ReadStringPieceVarInt62(&value)) { + return absl::OutOfRangeError("Not enough data to read field value."); + } + return FieldView{name, value}; +} + absl::Status DecodeFields(quiche::QuicheDataReader& reader, quiche::UnretainedCallback @@ -270,7 +296,7 @@ absl::StatusOr BinaryHttpResponse::EncodeAsKnownLength() const { std::string data; data.resize(EncodedSize()); quiche::QuicheDataWriter writer(data.size(), data.data()); - if (!writer.WriteUInt8(kKnownLengthResponseFraming)) { + if (!writer.WriteVarInt62(kKnownLengthResponseFraming)) { return absl::InvalidArgumentError("Failed to write framing indicator"); } // Informational response @@ -293,7 +319,7 @@ absl::StatusOr BinaryHttpResponse::EncodeAsKnownLength() const { } size_t BinaryHttpResponse::EncodedSize() const { - size_t size = sizeof(kKnownLengthResponseFraming); + size_t size = QuicheDataWriter::GetVarInt62Len(kKnownLengthResponseFraming); for (const auto& informational : informational_response_control_data_) { size += informational.EncodedSize(); } @@ -363,8 +389,9 @@ size_t BinaryHttpRequest::EncodedControlDataSize() const { } size_t BinaryHttpRequest::EncodedSize() const { - return sizeof(kKnownLengthRequestFraming) + EncodedControlDataSize() + - EncodedKnownLengthFieldsAndBodySize() + num_padding_bytes(); + return QuicheDataWriter::GetVarInt62Len(kKnownLengthRequestFraming) + + EncodedControlDataSize() + EncodedKnownLengthFieldsAndBodySize() + + num_padding_bytes(); } // https://www.ietf.org/archive/id/draft-ietf-httpbis-binary-message-06.html#name-known-length-messages @@ -372,7 +399,7 @@ absl::StatusOr BinaryHttpRequest::EncodeAsKnownLength() const { std::string data; data.resize(EncodedSize()); quiche::QuicheDataWriter writer(data.size(), data.data()); - if (!writer.WriteUInt8(kKnownLengthRequestFraming)) { + if (!writer.WriteVarInt62(kKnownLengthRequestFraming)) { return absl::InvalidArgumentError("Failed to encode framing indicator."); } if (const absl::Status status = EncodeControlData(writer); !status.ok()) { @@ -390,8 +417,8 @@ absl::StatusOr BinaryHttpRequest::EncodeAsKnownLength() const { absl::StatusOr BinaryHttpRequest::Create( absl::string_view data) { quiche::QuicheDataReader reader(data); - uint8_t framing; - if (!reader.ReadUInt8(&framing)) { + uint64_t framing; + if (!reader.ReadVarInt62(&framing)) { return absl::InvalidArgumentError("Missing framing indicator."); } if (framing == kKnownLengthRequestFraming) { @@ -401,11 +428,189 @@ absl::StatusOr BinaryHttpRequest::Create( absl::StrCat("Unsupported framing type ", framing)); } +absl::Status +BinaryHttpRequest::IndeterminateLengthDecoder::DecodeContentTerminatedSection( + QuicheDataReader& reader) { + uint64_t length_or_content_terminator; + do { + if (!reader.ReadVarInt62(&length_or_content_terminator)) { + return absl::OutOfRangeError("Not enough data to read section."); + } + if (length_or_content_terminator != kContentTerminator) { + switch (current_section_) { + case MessageSection::kHeader: { + const absl::StatusOr field = + DecodeField(reader, length_or_content_terminator); + if (!field.ok()) { + return field.status(); + } + message_section_handler_.OnHeader(field->name, field->value); + break; + } + case MessageSection::kBody: { + absl::string_view body_chunk; + if (!reader.ReadStringPiece(&body_chunk, + length_or_content_terminator)) { + return absl::OutOfRangeError("Failed to read body chunk."); + } + message_section_handler_.OnBodyChunk(body_chunk); + break; + } + case MessageSection::kTrailer: { + const absl::StatusOr field = + DecodeField(reader, length_or_content_terminator); + if (!field.ok()) { + return field.status(); + } + message_section_handler_.OnTrailer(field->name, field->value); + break; + } + default: + return absl::InternalError( + "Unexpected section in DecodeContentTerminatedSection."); + } + } + // Either a section was successfully decoded or a content terminator was + // encountered, save the checkpoint. + SaveCheckpoint(reader); + } while (length_or_content_terminator != kContentTerminator); + return absl::OkStatus(); +} + +// Returns Ok status only if the decoding processes the Padding section +// successfully or if the message is truncated properly. All other points of +// return are errors. +absl::Status +BinaryHttpRequest::IndeterminateLengthDecoder::DecodeCheckpointData( + bool end_stream) { + QuicheDataReader reader(checkpoint_view_); + switch (current_section_) { + case MessageSection::kEnd: + return absl::InternalError("Decoder is invalid."); + case MessageSection::kControlData: { + uint64_t framing; + if (!reader.ReadVarInt62(&framing)) { + return absl::OutOfRangeError("Failed to read framing."); + } + if (framing != kIndeterminateLengthRequestFraming) { + return absl::InvalidArgumentError( + absl::StrFormat("Unsupported framing type: 0x%02x", framing)); + } + + const absl::StatusOr control_data = + DecodeControlData(reader); + // Only fails if there is not enough data to read the entire control data. + if (!control_data.ok()) { + return absl::OutOfRangeError("Failed to read control data."); + } + + message_section_handler_.OnControlData(control_data.value()); + SaveCheckpoint(reader); + current_section_ = MessageSection::kHeader; + } + ABSL_FALLTHROUGH_INTENDED; + case MessageSection::kHeader: { + const absl::Status status = DecodeContentTerminatedSection(reader); + if (!status.ok()) { + return status; + } + message_section_handler_.OnHeadersDone(); + current_section_ = MessageSection::kBody; + } + ABSL_FALLTHROUGH_INTENDED; + case MessageSection::kBody: { + if (!reader.IsDoneReading()) { + maybe_truncated_ = false; + } + // Body and trailers truncation is valid only if: + // 1. There is no data to read after the headers section. + // 2. This is signaled as the last piece of data (end_stream). + if (maybe_truncated_ && end_stream) { + message_section_handler_.OnBodyChunksDone(); + message_section_handler_.OnTrailersDone(); + return absl::OkStatus(); + } + + const absl::Status status = DecodeContentTerminatedSection(reader); + if (!status.ok()) { + return status; + } + message_section_handler_.OnBodyChunksDone(); + current_section_ = MessageSection::kTrailer; + // Reset the truncation flag before entering the trailers section. + maybe_truncated_ = true; + } + ABSL_FALLTHROUGH_INTENDED; + case MessageSection::kTrailer: { + if (!reader.IsDoneReading()) { + maybe_truncated_ = false; + } + // Trailers truncation is valid only if: + // 1. There is no data to read after the body section. + // 2. This is signaled as the last piece of data (end_stream). + if (maybe_truncated_ && end_stream) { + message_section_handler_.OnTrailersDone(); + return absl::OkStatus(); + } + + const absl::Status status = DecodeContentTerminatedSection(reader); + if (!status.ok()) { + return status; + } + message_section_handler_.OnTrailersDone(); + current_section_ = MessageSection::kPadding; + } + ABSL_FALLTHROUGH_INTENDED; + case MessageSection::kPadding: { + if (!IsValidPadding(reader.PeekRemainingPayload())) { + return absl::InvalidArgumentError("Non-zero padding."); + } + return absl::OkStatus(); + } + } +} + +void BinaryHttpRequest::IndeterminateLengthDecoder::InitializeCheckpoint( + absl::string_view data) { + checkpoint_view_ = data; + // Prepend buffered data if present. This is the data from a previous call to + // Decode that could not finish because it needed this new data. + if (!buffer_.empty()) { + absl::StrAppend(&buffer_, data); + checkpoint_view_ = buffer_; + } +} + +absl::Status BinaryHttpRequest::IndeterminateLengthDecoder::Decode( + absl::string_view data, bool end_stream) { + if (current_section_ == MessageSection::kEnd) { + return absl::InternalError("Decoder is invalid."); + } + + InitializeCheckpoint(data); + absl::Status status = DecodeCheckpointData(end_stream); + if (end_stream) { + current_section_ = MessageSection::kEnd; + buffer_.clear(); + return status; + } + if (absl::IsOutOfRange(status)) { + BufferCheckpoint(); + return absl::OkStatus(); + } + if (!status.ok()) { + current_section_ = MessageSection::kEnd; + } + + buffer_.clear(); + return status; +} + absl::StatusOr BinaryHttpResponse::Create( absl::string_view data) { quiche::QuicheDataReader reader(data); - uint8_t framing; - if (!reader.ReadUInt8(&framing)) { + uint64_t framing; + if (!reader.ReadVarInt62(&framing)) { return absl::InvalidArgumentError("Missing framing indicator."); } if (framing == kKnownLengthResponseFraming) { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/binary_http/binary_http_message.h b/naiveproxy/src/net/third_party/quiche/src/quiche/binary_http/binary_http_message.h index 8f1f8f8832..0a28e0a1fd 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/binary_http/binary_http_message.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/binary_http/binary_http_message.h @@ -11,9 +11,11 @@ #include #include "absl/container/flat_hash_map.h" +#include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/string_view.h" #include "quiche/common/platform/api/quiche_export.h" +#include "quiche/common/quiche_data_reader.h" #include "quiche/common/quiche_data_writer.h" namespace quiche { @@ -171,6 +173,91 @@ class QUICHE_EXPORT BinaryHttpRequest : public BinaryHttpMessage { return !(*this == rhs); } + // Provides a Decode method that can be called multiple times as data is + // received. The relevant MessageSectionHandler method will be called when + // its corresponding section is successfully decoded. + class QUICHE_EXPORT IndeterminateLengthDecoder { + public: + // The handler to invoke when a section is decoded successfully. + class MessageSectionHandler { + public: + virtual ~MessageSectionHandler() = default; + virtual void OnControlData(const ControlData& control_data) = 0; + virtual void OnHeader(absl::string_view name, + absl::string_view value) = 0; + virtual void OnHeadersDone() = 0; + virtual void OnBodyChunk(absl::string_view body_chunk) = 0; + virtual void OnBodyChunksDone() = 0; + virtual void OnTrailer(absl::string_view name, + absl::string_view value) = 0; + virtual void OnTrailersDone() = 0; + }; + + explicit IndeterminateLengthDecoder( + MessageSectionHandler& message_section_handler) + : message_section_handler_(message_section_handler) {} + + // Decodes an Indeterminate-Length BHTTP request. As the caller receives + // portions of the request, the caller can call this method with the request + // portion. The class keeps track of the current message section that is + // being decoded and buffers data if the section is not fully decoded so + // that the next call can continue decoding from where it left off. It will + // also invoke the appropriate MessageSectionHandler method when a section + // is decoded successfully. + // `end_stream` indicates that no more data will be provided to the decoder. + // This is used to determine if a valid message was decoded properly given + // the last piece of data provided, handling both complete messages and + // truncated messages. + absl::Status Decode(absl::string_view data, bool end_stream); + + private: + // The sections of an Indeterminate-Length BHTTP request. + enum class MessageSection { + kControlData, + kHeader, + kBody, + kTrailer, + kPadding, + // The decoder is set to end after end_stream is received or when an error + // occurs while decoding. + kEnd, + }; + + // Initializes the checkpoint with the provided data and any buffered data. + void InitializeCheckpoint(absl::string_view data); + // Carries out the decode logic from the checkpoint. Returns + // OutOfRangeError if there is not enough data to decode the current + // section. When a section is fully decoded, the checkpoint is updated. + absl::Status DecodeCheckpointData(bool end_stream); + // Saves the checkpoint based on the current position of the reader. + void SaveCheckpoint(const QuicheDataReader& reader) { + checkpoint_view_ = reader.PeekRemainingPayload(); + } + // Buffers the checkpoint. + void BufferCheckpoint() { buffer_ = std::string(checkpoint_view_); } + // Decodes a section 0 or more times until a content terminator is + // encountered. + absl::Status DecodeContentTerminatedSection(QuicheDataReader& reader); + + MessageSectionHandler& message_section_handler_; + // Stores the data that could not be processed due to missing data. + std::string buffer_; + // Tracks the remaining data to be processed or buffered. + // When decoding fails due to missing data, we buffer based on this + // checkpoint and return. When decoding succeeds, we update the checkpoint + // to not buffer the already processed data. + absl::string_view checkpoint_view_; + // The current section that is being decoded. + MessageSection current_section_ = MessageSection::kControlData; + // Upon initial entry of the body or trailer section, the message is assumed + // to be truncated. This will be set to `false` upon the detection of data, + // and the state remains consistent for the remainder of the section. This + // serves to differentiate between true truncation and an `end_stream` + // occurring after partial processing of the section's content but before + // its content terminator. + bool maybe_truncated_ = true; + }; + private: absl::Status EncodeControlData(quiche::QuicheDataWriter& writer) const; 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 d7f8542366..8d4c6b7502 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 @@ -42,8 +42,39 @@ std::string OmitDefault(T value) { return value == 0 ? "" : absl::StrCat(value); } +constexpr absl::string_view kAttestationProtoTypeUrl = + "type.googleapis.com/privacy.ppn.AndroidAttestationData"; constexpr absl::string_view kIssuerHostname = "https://ipprotection-ppissuer.googleapis.com"; +constexpr size_t kExpectedExtensionTypesSize = 5; +constexpr std::array + kExpectedExtensionTypes = {0x0001, 0x0002, 0xF001, 0xF002, 0xF003}; + +using quiche::protobuf::Any; +using privacy::ppn::AndroidAttestationData; +using privacy::ppn::AttestAndSignRequest; +using privacy::ppn::AttestAndSignResponse; +using privacy::ppn::AttestationData; +using privacy::ppn::AuthAndSignRequest; +using privacy::ppn::AuthAndSignResponse; +using privacy::ppn::GetInitialDataRequest; +using privacy::ppn::GetInitialDataResponse; +using privacy::ppn::PrivacyPassTokenData; +using anonymous_tokens::AnonymousTokensUseCase; +using anonymous_tokens::CreatePublicKeyRSA; +using anonymous_tokens::DecodeExtensions; +using anonymous_tokens::ExpirationTimestamp; +using anonymous_tokens::ExtendedTokenRequest; +using anonymous_tokens::Extensions; +using anonymous_tokens::GeoHint; +using anonymous_tokens::MarshalTokenChallenge; +using anonymous_tokens::ParseUseCase; +using anonymous_tokens:: + PrivacyPassRsaBssaPublicMetadataClient; +using anonymous_tokens::RSAPublicKey; +using anonymous_tokens::Token; +using anonymous_tokens::TokenChallenge; +using anonymous_tokens::ValidateExtensionsOrderAndValues; } // namespace @@ -52,7 +83,7 @@ void BlindSignAuth::GetTokens(std::optional oauth_token, BlindSignAuthServiceType service_type, SignedTokenCallback callback) { // Create GetInitialData RPC. - privacy::ppn::GetInitialDataRequest request; + GetInitialDataRequest request; request.set_use_attestation(false); request.set_service_type(BlindSignAuthServiceTypeToString(service_type)); request.set_location_granularity( @@ -62,12 +93,12 @@ void BlindSignAuth::GetTokens(std::optional oauth_token, request.set_proxy_layer(QuicheProxyLayerToPpnProxyLayer(proxy_layer)); // Call GetInitialData on the BlindSignMessageInterface Fetcher. - std::string body = request.SerializeAsString(); + std::string body_bytes = request.SerializeAsString(); BlindSignMessageCallback initial_data_callback = absl::bind_front( &BlindSignAuth::GetInitialDataCallback, this, oauth_token, num_tokens, proxy_layer, service_type, std::move(callback)); fetcher_->DoRequest(BlindSignMessageRequestType::kGetInitialData, oauth_token, - body, std::move(initial_data_callback)); + body_bytes, std::move(initial_data_callback)); } void BlindSignAuth::GetInitialDataCallback( @@ -75,44 +106,28 @@ void BlindSignAuth::GetInitialDataCallback( ProxyLayer proxy_layer, BlindSignAuthServiceType service_type, SignedTokenCallback callback, absl::StatusOr response) { - if (!response.ok()) { - QUICHE_LOG(WARNING) << "GetInitialDataRequest failed: " - << response.status(); - std::move(callback)(absl::InvalidArgumentError( - "GetInitialDataRequest failed: invalid response")); - return; - } - absl::StatusCode code = response->status_code(); - if (code != absl::StatusCode::kOk) { - std::string message = - absl::StrCat("GetInitialDataRequest failed with code: ", code); - QUICHE_LOG(WARNING) << message; - std::move(callback)(absl::InvalidArgumentError(message)); - return; - } - // Parse GetInitialDataResponse. - privacy::ppn::GetInitialDataResponse initial_data_response; - if (!initial_data_response.ParseFromString(response->body())) { - QUICHE_LOG(WARNING) << "Failed to parse GetInitialDataResponse"; - std::move(callback)( - absl::InternalError("Failed to parse GetInitialDataResponse")); + absl::StatusOr initial_data_response = + ParseGetInitialDataResponseMessage(response); + if (!initial_data_response.ok()) { + std::move(callback)(initial_data_response.status()); return; } // Create token signing requests. - bool use_privacy_pass_client = - initial_data_response.has_privacy_pass_data() && + const bool use_privacy_pass_client = + initial_data_response->has_privacy_pass_data() && auth_options_.enable_privacy_pass(); if (use_privacy_pass_client) { QUICHE_DVLOG(1) << "Using Privacy Pass client"; - GeneratePrivacyPassTokens(initial_data_response, std::move(oauth_token), + GeneratePrivacyPassTokens(*initial_data_response, std::move(oauth_token), num_tokens, proxy_layer, service_type, std::move(callback)); } else { QUICHE_LOG(ERROR) << "Non-Privacy Pass tokens are no longer supported"; std::move(callback)(absl::UnimplementedError( "Non-Privacy Pass tokens are no longer supported")); + return; } } @@ -121,73 +136,18 @@ void BlindSignAuth::GeneratePrivacyPassTokens( std::optional oauth_token, int num_tokens, ProxyLayer proxy_layer, BlindSignAuthServiceType service_type, SignedTokenCallback callback) { - // Set up values used in the token generation loop. - anonymous_tokens::RSAPublicKey public_key_proto; - if (!public_key_proto.ParseFromString( - initial_data_response.at_public_metadata_public_key() - .serialized_public_key())) { - std::move(callback)( - absl::InvalidArgumentError("Failed to parse Privacy Pass public key")); + absl::StatusOr pp_context = + CreatePrivacyPassContext(initial_data_response); + if (!pp_context.ok()) { + std::move(callback)(pp_context.status()); return; } - absl::StatusOr> bssl_rsa_key = - anonymous_tokens::CreatePublicKeyRSA( - public_key_proto.n(), public_key_proto.e()); - if (!bssl_rsa_key.ok()) { - QUICHE_LOG(ERROR) << "Failed to create RSA public key: " - << bssl_rsa_key.status(); - std::move(callback)(absl::InternalError("Failed to create RSA public key")); - return; - } - absl::StatusOr extensions = - anonymous_tokens::DecodeExtensions( - initial_data_response.privacy_pass_data() - .public_metadata_extensions()); - if (!extensions.ok()) { - QUICHE_LOG(WARNING) << "Failed to decode extensions: " - << extensions.status(); - std::move(callback)( - absl::InvalidArgumentError("Failed to decode extensions")); - return; - } - 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()); - if (!result.ok()) { - QUICHE_LOG(WARNING) << "Failed to validate extensions: " << result; - std::move(callback)( - absl::InvalidArgumentError("Failed to validate extensions")); - return; - } - absl::StatusOr - expiration_timestamp = anonymous_tokens:: - ExpirationTimestamp::FromExtension(extensions->extensions.at(0)); - if (!expiration_timestamp.ok()) { - QUICHE_LOG(WARNING) << "Failed to parse expiration timestamp: " - << expiration_timestamp.status(); - std::move(callback)( - absl::InvalidArgumentError("Failed to parse expiration timestamp")); - return; - } - 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; + TokenChallenge challenge; challenge.issuer_name = kIssuerHostname; absl::StatusOr token_challenge = - anonymous_tokens::MarshalTokenChallenge(challenge); + MarshalTokenChallenge(challenge); if (!token_challenge.ok()) { QUICHE_LOG(WARNING) << "Failed to marshal token challenge: " << token_challenge.status(); @@ -196,78 +156,34 @@ void BlindSignAuth::GeneratePrivacyPassTokens( return; } - QuicheRandom* random = QuicheRandom::GetInstance(); - // Create vector of Privacy Pass clients, one for each token. - std::vector - extended_token_requests; - std::vector> - privacy_pass_clients; - std::vector privacy_pass_blinded_tokens; - - for (int i = 0; i < num_tokens; i++) { - // Create client. - auto client = anonymous_tokens:: - PrivacyPassRsaBssaPublicMetadataClient::Create(*bssl_rsa_key.value()); - if (!client.ok()) { - QUICHE_LOG(WARNING) << "Failed to create Privacy Pass client: " - << client.status(); - std::move(callback)( - absl::InternalError("Failed to create Privacy Pass client")); - return; - } - - // Create nonce. - std::string nonce_rand(32, '\0'); - random->RandBytes(nonce_rand.data(), nonce_rand.size()); - - // Create token request. - absl::StatusOr - extended_token_request = client.value()->CreateTokenRequest( - *token_challenge, nonce_rand, - initial_data_response.privacy_pass_data().token_key_id(), - *extensions); - if (!extended_token_request.ok()) { - QUICHE_LOG(WARNING) << "Failed to create ExtendedTokenRequest: " - << extended_token_request.status(); - std::move(callback)( - absl::InternalError("Failed to create ExtendedTokenRequest")); - return; - } - privacy_pass_clients.push_back(*std::move(client)); - extended_token_requests.push_back(*extended_token_request); - privacy_pass_blinded_tokens.push_back(absl::Base64Escape( - extended_token_request->request.blinded_token_request)); + absl::StatusOr token_requests_data = + GenerateBlindedTokenRequests(num_tokens, *pp_context->rsa_public_key, + *token_challenge, pp_context->token_key_id, + pp_context->extensions); + if (!token_requests_data.ok()) { + std::move(callback)(token_requests_data.status()); + return; } - privacy::ppn::AuthAndSignRequest sign_request; + AuthAndSignRequest sign_request; sign_request.set_service_type(BlindSignAuthServiceTypeToString(service_type)); sign_request.set_key_type(privacy::ppn::AT_PUBLIC_METADATA_KEY_TYPE); sign_request.set_key_version( initial_data_response.at_public_metadata_public_key().key_version()); - sign_request.mutable_blinded_token()->Assign( - privacy_pass_blinded_tokens.begin(), privacy_pass_blinded_tokens.end()); + *sign_request.mutable_blinded_token() = { + token_requests_data->privacy_pass_blinded_tokens_b64.begin(), + token_requests_data->privacy_pass_blinded_tokens_b64.end()}; sign_request.mutable_public_metadata_extensions()->assign( initial_data_response.privacy_pass_data().public_metadata_extensions()); // TODO(b/295924807): deprecate this option after AT server defaults to it sign_request.set_do_not_use_rsa_public_exponent(true); sign_request.set_proxy_layer(QuicheProxyLayerToPpnProxyLayer(proxy_layer)); - absl::StatusOr - use_case = anonymous_tokens::ParseUseCase( - initial_data_response.at_public_metadata_public_key().use_case()); - if (!use_case.ok()) { - QUICHE_LOG(WARNING) << "Failed to parse use case: " << use_case.status(); - std::move(callback)(absl::InvalidArgumentError("Failed to parse use case")); - return; - } - BlindSignMessageCallback auth_and_sign_callback = absl::bind_front(&BlindSignAuth::PrivacyPassAuthAndSignCallback, this, - std::move(initial_data_response.privacy_pass_data() - .public_metadata_extensions()), - public_metadata_expiry_time, *geo_hint, *use_case, - std::move(privacy_pass_clients), std::move(callback)); + *std::move(pp_context), + std::move(token_requests_data->privacy_pass_clients), + std::move(callback)); // TODO(b/304811277): remove other usages of string.data() fetcher_->DoRequest(BlindSignMessageRequestType::kAuthAndSign, oauth_token, sign_request.SerializeAsString(), @@ -275,9 +191,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, + const PrivacyPassContext& pp_context, std::vector> privacy_pass_clients, @@ -299,7 +213,7 @@ void BlindSignAuth::PrivacyPassAuthAndSignCallback( } // Decode AuthAndSignResponse. - privacy::ppn::AuthAndSignResponse sign_response; + AuthAndSignResponse sign_response; if (!sign_response.ParseFromString(response->body())) { QUICHE_LOG(WARNING) << "Failed to parse AuthAndSignResponse"; std::move(callback)( @@ -328,7 +242,7 @@ void BlindSignAuth::PrivacyPassAuthAndSignCallback( return; } - absl::StatusOr token = + absl::StatusOr token = privacy_pass_clients[i]->FinalizeToken(unescaped_blinded_sig); if (!token.ok()) { QUICHE_LOG(WARNING) << "Failed to finalize token: " << token.status(); @@ -336,8 +250,7 @@ void BlindSignAuth::PrivacyPassAuthAndSignCallback( return; } - absl::StatusOr marshaled_token = - anonymous_tokens::MarshalToken(*token); + absl::StatusOr marshaled_token = MarshalToken(*token); if (!marshaled_token.ok()) { QUICHE_LOG(WARNING) << "Failed to marshal token: " << marshaled_token.status(); @@ -345,20 +258,385 @@ void BlindSignAuth::PrivacyPassAuthAndSignCallback( return; } - privacy::ppn::PrivacyPassTokenData privacy_pass_token_data; + PrivacyPassTokenData privacy_pass_token_data; privacy_pass_token_data.mutable_token()->assign( ConvertBase64ToWebSafeBase64(absl::Base64Escape(*marshaled_token))); privacy_pass_token_data.mutable_encoded_extensions()->assign( - 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, geo_hint}); + ConvertBase64ToWebSafeBase64( + absl::Base64Escape(pp_context.public_metadata_extensions_str))); + privacy_pass_token_data.set_use_case_override(pp_context.use_case); + tokens_vec.push_back(BlindSignToken{ + privacy_pass_token_data.SerializeAsString(), + pp_context.public_metadata_expiry_time, pp_context.geo_hint}); } std::move(callback)(absl::Span(tokens_vec)); } +void BlindSignAuth::GetAttestationTokens( + int num_tokens, ProxyLayer layer, + AttestationDataCallback attestation_data_callback, + SignedTokenCallback token_callback) { + GetInitialDataRequest request; + request.set_service_type(BlindSignAuthServiceTypeToString( + BlindSignAuthServiceType::kPrivateAratea)); + // Validation version must be 2 to use ProxyLayer. + request.set_validation_version(2); + request.set_proxy_layer(QuicheProxyLayerToPpnProxyLayer(layer)); + request.set_use_attestation(true); + + // Send GetAttestationData RPC on the BlindSignMessageInterface. + std::string body_bytes = request.SerializeAsString(); + BlindSignMessageCallback initial_data_callback = absl::bind_front( + &BlindSignAuth::GetAttestationTokensCallback, this, num_tokens, + std::move(attestation_data_callback), std::move(token_callback)); + fetcher_->DoRequest(BlindSignMessageRequestType::kGetInitialData, + /*authorization_header=*/std::nullopt, body_bytes, + std::move(initial_data_callback)); +} + +void BlindSignAuth::GetAttestationTokensCallback( + int num_tokens, AttestationDataCallback attestation_data_callback, + SignedTokenCallback token_callback, + absl::StatusOr response) { + absl::StatusOr initial_data_response = + ParseGetInitialDataResponseMessage(response); + if (!initial_data_response.ok()) { + std::move(token_callback)(initial_data_response.status()); + return; + } + + const bool use_privacy_pass_client = + auth_options_.enable_privacy_pass() && + initial_data_response->has_privacy_pass_data(); + if (use_privacy_pass_client) { + QUICHE_DVLOG(1) << "Using Privacy Pass client for GetAttestationTokens"; + } else { + QUICHE_LOG(ERROR) << "Non-Privacy Pass tokens are no longer supported"; + std::move(token_callback)(absl::UnimplementedError( + "Non-Privacy Pass tokens are no longer supported")); + return; + } + + // Return attestation nonce, caller will use it as the attestation challenge. + if (!initial_data_response->has_attestation()) { + QUICHE_LOG(WARNING) + << "GetInitialDataResponse does not have attestation data"; + std::move(token_callback)(absl::InternalError( + "GetInitialDataResponse does not have attestation data")); + return; + } + absl::string_view attestation_nonce = + initial_data_response->attestation().attestation_nonce(); + quiche::AttestAndSignCallback attest_and_sign_callback = absl::bind_front( + &BlindSignAuth::AttestAndSign, this, num_tokens, + *std::move(initial_data_response), std::move(token_callback)); + std::move(attestation_data_callback)(attestation_nonce, + std::move(attest_and_sign_callback)); +} + +void BlindSignAuth::AttestAndSign( + int num_tokens, privacy::ppn::GetInitialDataResponse initial_data_response, + SignedTokenCallback callback, absl::StatusOr attestation_data, + std::optional token_challenge) { + absl::StatusOr pp_context = + CreatePrivacyPassContext(initial_data_response); + if (!pp_context.ok()) { + std::move(callback)(pp_context.status()); + return; + } + + // Create token challenge if not provided. + std::string token_challenge_str; + if (!token_challenge.has_value()) { + TokenChallenge challenge; + challenge.issuer_name = kIssuerHostname; + if (absl::StatusOr constant_challenge = + MarshalTokenChallenge(challenge); + constant_challenge.ok()) { + token_challenge_str = *constant_challenge; + } else { + QUICHE_LOG(WARNING) << "Failed to marshal token challenge: " + << constant_challenge.status(); + std::move(callback)( + absl::InvalidArgumentError("Failed to marshal token challenge")); + return; + } + } else { + token_challenge_str = *token_challenge; + } + + absl::StatusOr token_requests_data = + GenerateBlindedTokenRequests( + num_tokens, *pp_context->rsa_public_key, token_challenge_str, + pp_context->token_key_id, pp_context->extensions); + if (!token_requests_data.ok()) { + std::move(callback)(token_requests_data.status()); + return; + } + + // Create AndroidAttestationData. + AndroidAttestationData android_attestation_data; + if (!attestation_data.ok()) { + std::move(callback)(attestation_data.status()); + return; + } + android_attestation_data.add_hardware_backed_certs(*attestation_data); + + Any attestation_data_proto_any; + attestation_data_proto_any.set_type_url(kAttestationProtoTypeUrl); + attestation_data_proto_any.set_value( + android_attestation_data.SerializeAsString()); + + AttestationData attestation_data_proto; + *attestation_data_proto.mutable_attestation_data() = + attestation_data_proto_any; + + // Create AttestAndSignRequest. + AttestAndSignRequest sign_request; + sign_request.set_service_type(BlindSignAuthServiceTypeToString( + BlindSignAuthServiceType::kPrivateAratea)); + sign_request.mutable_blinded_tokens()->Assign( + token_requests_data->privacy_pass_blinded_tokens_b64.begin(), + token_requests_data->privacy_pass_blinded_tokens_b64.end()); + sign_request.set_key_version( + initial_data_response.at_public_metadata_public_key().key_version()); + sign_request.mutable_public_metadata_extensions()->assign( + initial_data_response.privacy_pass_data().public_metadata_extensions()); + *sign_request.mutable_attestation() = attestation_data_proto; + + BlindSignMessageCallback attestation_data_callback = absl::bind_front( + &BlindSignAuth::AttestAndSignCallback, this, *std::move(pp_context), + std::move(token_requests_data->privacy_pass_clients), + std::move(callback)); + + fetcher_->DoRequest(BlindSignMessageRequestType::kAttestAndSign, + /*authorization_header=*/std::nullopt, + sign_request.SerializeAsString(), + std::move(attestation_data_callback)); +} + +void BlindSignAuth::AttestAndSignCallback( + PrivacyPassContext pp_context, + const std::vector>& privacy_pass_clients, + SignedTokenCallback callback, + absl::StatusOr response) { + // Validate response. + if (!response.ok()) { + QUICHE_LOG(WARNING) << "AttestAndSign failed: " << response.status(); + std::move(callback)( + absl::InvalidArgumentError("AttestAndSign failed: invalid response")); + return; + } + absl::StatusCode code = response->status_code(); + if (code != absl::StatusCode::kOk) { + std::string message = + absl::StrCat("AttestAndSign failed with code: ", code); + QUICHE_LOG(WARNING) << message; + std::move(callback)(absl::InvalidArgumentError(message)); + return; + } + + // Decode AttestAndSignResponse. + AttestAndSignResponse sign_response; + if (!sign_response.ParseFromString(response->body())) { + QUICHE_LOG(WARNING) << "Failed to parse AttestAndSignResponse"; + std::move(callback)( + absl::InternalError("Failed to parse AttestAndSignResponse")); + return; + } + if (static_cast(sign_response.blinded_token_signatures_size()) > + privacy_pass_clients.size()) { + QUICHE_LOG(WARNING) << "Number of signatures is greater than the number of " + "Privacy Pass tokens sent"; + std::move(callback)(absl::InternalError( + "Number of signatures is greater than the number of " + "Privacy Pass tokens sent")); + return; + } + + // Create tokens using blinded signatures. + std::vector tokens_vec; + for (int i = 0; i < sign_response.blinded_token_signatures_size(); i++) { + std::string unescaped_blinded_sig; + if (!absl::Base64Unescape(sign_response.blinded_token_signatures()[i], + &unescaped_blinded_sig)) { + QUICHE_LOG(WARNING) << "Failed to unescape blinded signature"; + std::move(callback)( + absl::InternalError("Failed to unescape blinded signature")); + return; + } + + absl::StatusOr token = + privacy_pass_clients[i]->FinalizeToken(unescaped_blinded_sig); + if (!token.ok()) { + QUICHE_LOG(WARNING) << "Failed to finalize token: " << token.status(); + std::move(callback)(absl::InternalError("Failed to finalize token")); + return; + } + + absl::StatusOr marshaled_token = MarshalToken(*token); + if (!marshaled_token.ok()) { + QUICHE_LOG(WARNING) << "Failed to marshal token: " + << marshaled_token.status(); + std::move(callback)(absl::InternalError("Failed to marshal token")); + return; + } + + PrivacyPassTokenData privacy_pass_token_data; + privacy_pass_token_data.mutable_token()->assign( + ConvertBase64ToWebSafeBase64(absl::Base64Escape(*marshaled_token))); + privacy_pass_token_data.mutable_encoded_extensions()->assign( + ConvertBase64ToWebSafeBase64( + absl::Base64Escape(pp_context.public_metadata_extensions_str))); + privacy_pass_token_data.set_use_case_override(pp_context.use_case); + tokens_vec.push_back(BlindSignToken{ + privacy_pass_token_data.SerializeAsString(), + pp_context.public_metadata_expiry_time, pp_context.geo_hint}); + } + + std::move(callback)(absl::Span(tokens_vec)); +} + +absl::StatusOr +BlindSignAuth::ParseGetInitialDataResponseMessage( + const absl::StatusOr& response) { + if (!response.ok()) { + QUICHE_LOG(WARNING) << "GetInitialDataRequest failed: " + << response.status(); + return absl::InvalidArgumentError( + "GetInitialDataRequest failed: invalid response"); + } + if (absl::StatusCode code = response->status_code(); + code != absl::StatusCode::kOk) { + std::string message = + absl::StrCat("GetInitialDataRequest failed with code: ", code); + QUICHE_LOG(WARNING) << message; + return absl::InvalidArgumentError(message); + } + // Parse GetInitialDataResponse. + GetInitialDataResponse initial_data_response; + if (!initial_data_response.ParseFromString(response->body())) { + QUICHE_LOG(WARNING) << "Failed to parse GetInitialDataResponse"; + return absl::InternalError("Failed to parse GetInitialDataResponse"); + } + return initial_data_response; +} + +absl::StatusOr +BlindSignAuth::CreatePrivacyPassContext( + const privacy::ppn::GetInitialDataResponse& initial_data_response) { + RSAPublicKey public_key_proto; + if (!public_key_proto.ParseFromString( + initial_data_response.at_public_metadata_public_key() + .serialized_public_key())) { + return absl::InvalidArgumentError( + "Failed to parse Privacy Pass public key"); + } + absl::StatusOr> bssl_rsa_key = + CreatePublicKeyRSA(public_key_proto.n(), public_key_proto.e()); + if (!bssl_rsa_key.ok()) { + return absl::InternalError(absl::StrCat("Failed to create RSA public key: ", + bssl_rsa_key.status().ToString())); + } + + PrivacyPassContext context; + context.rsa_public_key = *std::move(bssl_rsa_key); + context.key_version = + initial_data_response.at_public_metadata_public_key().key_version(); + context.token_key_id = + initial_data_response.privacy_pass_data().token_key_id(); + context.public_metadata_extensions_str = + initial_data_response.privacy_pass_data().public_metadata_extensions(); + + absl::StatusOr extensions = + DecodeExtensions(context.public_metadata_extensions_str); + if (!extensions.ok()) { + return absl::InvalidArgumentError(absl::StrCat( + "Failed to decode extensions: ", extensions.status().ToString())); + } + + if (absl::Status validation_result = ValidateExtensionsOrderAndValues( + *extensions, absl::MakeSpan(kExpectedExtensionTypes), absl::Now()); + validation_result.ok()) { + context.extensions = *std::move(extensions); + } else { + return absl::InvalidArgumentError(absl::StrCat( + "Failed to validate extensions: ", validation_result.ToString())); + } + + if (absl::StatusOr expiration_timestamp = + ExpirationTimestamp::FromExtension( + context.extensions.extensions.at(0)); + expiration_timestamp.ok()) { + context.public_metadata_expiry_time = + absl::FromUnixSeconds(expiration_timestamp->timestamp); + } else { + return absl::InvalidArgumentError( + absl::StrCat("Failed to parse expiration timestamp: ", + expiration_timestamp.status().ToString())); + } + + if (absl::StatusOr geo_hint = + GeoHint::FromExtension(context.extensions.extensions.at(1)); + geo_hint.ok()) { + context.geo_hint = *std::move(geo_hint); + } else { + return absl::InvalidArgumentError(absl::StrCat( + "Failed to parse geo hint: ", geo_hint.status().ToString())); + } + + if (absl::StatusOr use_case = ParseUseCase( + initial_data_response.at_public_metadata_public_key().use_case()); + use_case.ok()) { + context.use_case = *std::move(use_case); + } else { + return absl::InvalidArgumentError(absl::StrCat( + "Failed to parse use case: ", use_case.status().ToString())); + } + + return context; +} + +absl::StatusOr +BlindSignAuth::GenerateBlindedTokenRequests( + int num_tokens, const RSA& rsa_public_key, + absl::string_view token_challenge_str, absl::string_view token_key_id, + const anonymous_tokens::Extensions& extensions) { + GeneratedTokenRequests result; + result.privacy_pass_clients.reserve(num_tokens); + result.privacy_pass_blinded_tokens_b64.reserve(num_tokens); + QuicheRandom* random = QuicheRandom::GetInstance(); + + for (int i = 0; i < num_tokens; i++) { + absl::StatusOr> + client = PrivacyPassRsaBssaPublicMetadataClient::Create(rsa_public_key); + if (!client.ok()) { + return absl::InternalError( + absl::StrCat("Failed to create Privacy Pass client: ", + client.status().ToString())); + } + + std::string nonce_rand(32, '\0'); + random->RandBytes(nonce_rand.data(), nonce_rand.size()); + + absl::StatusOr extended_token_request = + (*client)->CreateTokenRequest(token_challenge_str, nonce_rand, + token_key_id, extensions); + if (!extended_token_request.ok()) { + return absl::InternalError( + absl::StrCat("Failed to create ExtendedTokenRequest: ", + extended_token_request.status().ToString())); + } + result.privacy_pass_clients.push_back(*std::move(client)); + result.privacy_pass_blinded_tokens_b64.push_back(absl::Base64Escape( + extended_token_request->request.blinded_token_request)); + } + return result; +} + privacy::ppn::ProxyLayer BlindSignAuth::QuicheProxyLayerToPpnProxyLayer( quiche::ProxyLayer proxy_layer) { switch (proxy_layer) { @@ -374,23 +652,6 @@ privacy::ppn::ProxyLayer BlindSignAuth::QuicheProxyLayerToPpnProxyLayer( } } -void BlindSignAuth::GetAttestationTokens(int /*num_tokens*/, - ProxyLayer /*layer*/, - AttestationDataCallback callback) { - // TODO(b/421236538): Implement GetAttestationTokens. - std::move(callback)( - absl::UnimplementedError("GetAttestationTokens is not implemented")); -} - -void BlindSignAuth::AttestAndSign( - int /*num_tokens*/, ProxyLayer /*layer*/, std::string /*attestation_data*/, - std::optional /*token_challenge*/, - SignedTokenCallback callback) { - // TODO(b/421236538): Implement AttestAndSign. - std::move(callback)( - absl::UnimplementedError("AttestAndSign is not implemented")); -} - std::string BlindSignAuth::ConvertBase64ToWebSafeBase64( std::string base64_string) { absl::c_replace(base64_string, /*old_value=*/'+', /*new_value=*/'-'); @@ -414,7 +675,7 @@ std::string BlindSignAuthServiceTypeToString( return "chromeipblinding"; } case BlindSignAuthServiceType::kPrivateAratea: { - return "pixel_private_aratea"; + return "privatearatea"; } } } 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 ccc3118ccb..d1398d7a96 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 @@ -38,49 +38,92 @@ class QUICHE_EXPORT BlindSignAuth : public BlindSignAuthInterface { ProxyLayer proxy_layer, BlindSignAuthServiceType service_type, SignedTokenCallback callback) override; - // Returns an attestation challenge in a callback. - // GetAttestationTokens callbacks will run on the same thread as the + // Returns signed unblinded tokens and their expiration time in a + // SignedTokenCallback. Errors will be returned in the SignedTokenCallback + // only. Tokens are single-use and restricted to the PI use case. + // GetAttestationTokens callback will run on the same thread as the // BlindSignMessageInterface callbacks. - // Callers can make multiple concurrent requests to GetTokens. - // AttestationDataCallback should call AttestAndSign with a separate callback - // in order to complete the token issuance protocol. + // Callers can make multiple concurrent requests to GetAttestationTokens. + // In the AttestationDataCallback, the caller must call the + // AttestAndSignCallback and provide AttestationData generated using Keystore + // and the challenge returned in AttestationDataCallback. If a token challenge + // is provided in the AttestAndSignCallback, it will be used in creating the + // token. Otherwise a default challenge will be used containing the issuer + // hostname. void GetAttestationTokens(int num_tokens, ProxyLayer layer, - AttestationDataCallback callback) override; - - // Returns signed unblinded tokens and their expiration time in a callback. - // Tokens are single-use and restricted to the PI use case. - // The GetTokens callback will run on the same thread as the - // BlindSignMessageInterface callbacks. - // This function should be called after the caller has generated - // AttestationData using Keystore and the challenge returned in - // AttestationDataCallback. If a token challenge is provided, it will be used - // in creating the token. Otherwise a default challenge will be used - // containing the issuer hostname. - void AttestAndSign(int num_tokens, ProxyLayer layer, - std::string attestation_data, - std::optional token_challenge, - SignedTokenCallback callback) override; + AttestationDataCallback attestation_data_callback, + SignedTokenCallback token_callback) override; private: + struct PrivacyPassContext { + bssl::UniquePtr rsa_public_key; + anonymous_tokens::Extensions extensions; + absl::Time public_metadata_expiry_time; + anonymous_tokens::GeoHint geo_hint; + anonymous_tokens::AnonymousTokensUseCase use_case; + std::string token_key_id; + uint32_t key_version = 0; + std::string public_metadata_extensions_str; + }; + + struct GeneratedTokenRequests { + std::vector> + privacy_pass_clients; + std::vector privacy_pass_blinded_tokens_b64; + }; + + // Helper functions for GetTokens flow without device attestation. void GetInitialDataCallback( std::optional oauth_token, int num_tokens, ProxyLayer proxy_layer, BlindSignAuthServiceType service_type, SignedTokenCallback callback, absl::StatusOr response); + void GeneratePrivacyPassTokens( privacy::ppn::GetInitialDataResponse initial_data_response, std::optional oauth_token, int num_tokens, ProxyLayer proxy_layer, BlindSignAuthServiceType service_type, SignedTokenCallback callback); + void PrivacyPassAuthAndSignCallback( - std::string encoded_extensions, absl::Time public_key_expiry_time, - anonymous_tokens::GeoHint geo_hint, - anonymous_tokens::AnonymousTokensUseCase use_case, + const PrivacyPassContext& pp_context, std::vector> privacy_pass_clients, SignedTokenCallback callback, absl::StatusOr response); + + // Helper functions for GetAttestationTokens flow. + void GetAttestationTokensCallback( + int num_tokens, AttestationDataCallback attestation_data_callback, + SignedTokenCallback token_callback, + absl::StatusOr response); + void AttestAndSign(int num_tokens, + privacy::ppn::GetInitialDataResponse initial_data_response, + SignedTokenCallback callback, + absl::StatusOr attestation_data, + std::optional token_challenge); + void AttestAndSignCallback( + PrivacyPassContext pp_context, + const std::vector>& privacy_pass_clients, + SignedTokenCallback callback, + absl::StatusOr response); + + absl::StatusOr + ParseGetInitialDataResponseMessage( + const absl::StatusOr& response_statusor); + + absl::StatusOr CreatePrivacyPassContext( + const privacy::ppn::GetInitialDataResponse& initial_data_response); + + absl::StatusOr GenerateBlindedTokenRequests( + int num_tokens, const RSA& rsa_public_key, + absl::string_view token_challenge_str, absl::string_view token_key_id, + const anonymous_tokens::Extensions& extensions); + privacy::ppn::ProxyLayer QuicheProxyLayerToPpnProxyLayer( quiche::ProxyLayer proxy_layer); // Replaces '+' and '/' with '-' and '_' in a Base64 string. 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 7fe3f4b487..59b2cdc9df 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 @@ -48,6 +48,11 @@ struct QUICHE_EXPORT BlindSignToken { using SignedTokenCallback = SingleUseCallback>)>; +// This callback is used by the caller to return generated +// attestation data and a token challenge to the BlindSignAuth library. +using AttestAndSignCallback = SingleUseCallback, std::optional)>; + // AttestationDataCallback returns a serialized // privacy::ppn::PrepareAttestationData proto, which contains an attestation // challenge from the issuer server. @@ -55,8 +60,10 @@ using SignedTokenCallback = // the response's HTTP status code. // If the request succeeds but the server does not issue a challenge, the // callback will return an absl::InternalError. +// The second callback is used by the caller to return the +// attestation data to the BlindSignAuth library. using AttestationDataCallback = - SingleUseCallback)>; + SingleUseCallback; // BlindSignAuth provides signed, unblinded tokens to callers. class QUICHE_EXPORT BlindSignAuthInterface { @@ -69,29 +76,22 @@ class QUICHE_EXPORT BlindSignAuthInterface { BlindSignAuthServiceType service_type, SignedTokenCallback callback) = 0; - // Returns an attestation challenge in a callback. - // GetAttestationTokens callbacks will run on the same thread as the + // Returns signed unblinded tokens and their expiration time in a + // SignedTokenCallback. Errors will be returned in the SignedTokenCallback + // only. Tokens are single-use and restricted to the PI use case. + // GetAttestationTokens callback will run on the same thread as the // BlindSignMessageInterface callbacks. - // Callers can make multiple concurrent requests to GetTokens. - // ProxyLayer must be either ProxyB or TerminalLayer, NOT ProxyA. - // AttestationDataCallback should call AttestAndSign with a separate callback - // in order to complete the token issuance protocol. - virtual void GetAttestationTokens(int num_tokens, ProxyLayer layer, - AttestationDataCallback callback) = 0; - - // Returns signed unblinded tokens and their expiration time in a callback. - // Tokens are single-use and restricted to the PI use case. - // The GetTokens callback will run on the same thread as the - // BlindSignMessageInterface callbacks. - // This function should be called after the caller has generated - // AttestationData using Keystore and the challenge returned in - // AttestationDataCallback. If a token challenge is provided, it will be used - // in creating the token. Otherwise a default challenge will be used - // containing the issuer hostname. - virtual void AttestAndSign(int num_tokens, ProxyLayer layer, - std::string attestation_data, - std::optional token_challenge, - SignedTokenCallback callback) = 0; + // Callers can make multiple concurrent requests to GetAttestationTokens. + // In the AttestationDataCallback, the caller must call the + // AttestAndSignCallback and provide AttestationData generated using Keystore + // and the challenge returned in AttestationDataCallback. If a token challenge + // is provided in the AttestAndSignCallback, it will be used in creating the + // token. Otherwise a default challenge will be used containing the issuer + // hostname. + virtual void GetAttestationTokens( + int num_tokens, ProxyLayer layer, + AttestationDataCallback attestation_data_callback, + SignedTokenCallback token_callback) = 0; }; } // namespace quiche diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth_protos.h b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth_protos.h index 9935fa65ef..d3cc3f2ee7 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth_protos.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth_protos.h @@ -1,7 +1,10 @@ #ifndef QUICHE_BLIND_SIGN_AUTH_BLIND_SIGN_AUTH_PROTOS_H_ #define QUICHE_BLIND_SIGN_AUTH_BLIND_SIGN_AUTH_PROTOS_H_ +#include "quiche/blind_sign_auth/proto/any.pb.h" // IWYU pragma: export #include "anonymous_tokens/proto/anonymous_tokens.pb.h" // IWYU pragma: export +#include "quiche/blind_sign_auth/proto/attestation.pb.h" // IWYU pragma: export +#include "quiche/blind_sign_auth/proto/attest_and_sign.pb.h" // IWYU pragma: export #include "quiche/blind_sign_auth/proto/auth_and_sign.pb.h" // IWYU pragma: export #include "quiche/blind_sign_auth/proto/blind_sign_auth_options.pb.h" // IWYU pragma: export #include "quiche/blind_sign_auth/proto/get_initial_data.pb.h" // IWYU pragma: export diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth_test_data.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth_test_data.cc new file mode 100644 index 0000000000..d9e1318e0a --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth_test_data.cc @@ -0,0 +1,221 @@ +// Copyright (c) 2025 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/blind_sign_auth/blind_sign_auth_test_data.h" + +#include +#include +#include + +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/escaping.h" +#include "absl/strings/string_view.h" +#include "absl/time/clock.h" +#include "absl/time/time.h" +#include "anonymous_tokens/cpp/crypto/crypto_utils.h" +#include "anonymous_tokens/cpp/privacy_pass/token_encodings.h" +#include "anonymous_tokens/cpp/testing/utils.h" +#include "openssl/base.h" +#include "openssl/digest.h" + +namespace quiche::test { + +using ::privacy::ppn::AttestAndSignResponse; +using ::privacy::ppn::GetInitialDataResponse; +using ::anonymous_tokens::AT_HASH_TYPE_SHA384; +using ::anonymous_tokens::AT_MESSAGE_MASK_NO_MASK; +using ::anonymous_tokens::AT_MGF_SHA384; +using ::anonymous_tokens::ComputeHash; +using ::anonymous_tokens::CreatePrivateKeyRSA; +using ::anonymous_tokens::CreatePublicKeyRSA; +using ::anonymous_tokens::DebugMode; +using ::anonymous_tokens::EncodeExtensions; +using ::anonymous_tokens::ExpirationTimestamp; +using ::anonymous_tokens::Extension; +using ::anonymous_tokens::Extensions; +using ::anonymous_tokens::GeoHint; +using ::anonymous_tokens::GetStrongTestRsaKeyPair2048; +using ::anonymous_tokens::ProxyLayer; +using ::anonymous_tokens::RSABlindSignaturePublicKey; +using ::anonymous_tokens::RSAPublicKey; +using ::anonymous_tokens::RsaSsaPssPublicKeyToDerEncoding; +using ::anonymous_tokens::ServiceType; +using ::anonymous_tokens::TestRsaPublicKey; + +namespace { + +// Helpers +absl::StatusOr CreateExtensions(); +RSABlindSignaturePublicKey CreatePublicKeyProto( + TestRsaPublicKey test_rsa_public_key); + +} // namespace + +absl::StatusOr> +BlindSignAuthTestData::Create() { + // Create keypair and populate protos. + auto [test_rsa_public_key, test_rsa_private_key] = + GetStrongTestRsaKeyPair2048(); + absl::StatusOr> rsa_public_key = + CreatePublicKeyRSA(test_rsa_public_key.n, test_rsa_public_key.e); + if (!rsa_public_key.ok()) { + return rsa_public_key.status(); + } + + absl::StatusOr> rsa_private_key = CreatePrivateKeyRSA( + test_rsa_private_key.n, test_rsa_private_key.e, test_rsa_private_key.d, + test_rsa_private_key.p, test_rsa_private_key.q, test_rsa_private_key.dp, + test_rsa_private_key.dq, test_rsa_private_key.crt); + if (!rsa_private_key.ok()) { + return rsa_private_key.status(); + } + + // token_key_id is derived from public key. + absl::StatusOr public_key_der = + RsaSsaPssPublicKeyToDerEncoding(rsa_public_key->get()); + if (!public_key_der.ok()) { + return public_key_der.status(); + } + + const EVP_MD *sha256 = EVP_sha256(); + absl::StatusOr token_key_id = + ComputeHash(*public_key_der, *sha256); + if (!token_key_id.ok()) { + return token_key_id.status(); + } + + absl::StatusOr extensions = CreateExtensions(); + if (!extensions.ok()) { + return extensions.status(); + } + + absl::StatusOr serialized_extensions = + EncodeExtensions(*extensions); + if (!serialized_extensions.ok()) { + return serialized_extensions.status(); + } + + GetInitialDataResponse::PrivacyPassData privacy_pass_data; + privacy_pass_data.set_token_key_id(*token_key_id); + privacy_pass_data.set_public_metadata_extensions(*serialized_extensions); + + return absl::WrapUnique(new BlindSignAuthTestData( + std::move(*rsa_public_key), std::move(*rsa_private_key), + CreatePublicKeyProto(test_rsa_public_key), privacy_pass_data)); +} + +GetInitialDataResponse BlindSignAuthTestData::CreateGetInitialDataResponse() { + GetInitialDataResponse response; + + *response.mutable_at_public_metadata_public_key() = public_key_proto_; + *response.mutable_privacy_pass_data() = privacy_pass_data_; + + // Create fake GetInitialDataResponse for attestation flow. + response.mutable_attestation()->set_attestation_nonce( + "test_attestation_nonce"); + return response; +} + +absl::StatusOr +BlindSignAuthTestData::CreateAttestAndSignResponse(absl::string_view body) { + privacy::ppn::AttestAndSignRequest request; + if (!request.ParseFromString(body)) { + return absl::InvalidArgumentError("Failed to parse AttestAndSignRequest"); + } + + privacy::ppn::AttestAndSignResponse response; + for (const auto &request_token : request.blinded_tokens()) { + std::string decoded_blinded_token; + if (!absl::Base64Unescape(request_token, &decoded_blinded_token)) { + return absl::InvalidArgumentError("Failed to decode blinded token"); + } + absl::StatusOr signature = + anonymous_tokens::TestSignWithPublicMetadata( + decoded_blinded_token, + privacy_pass_data_.public_metadata_extensions(), *rsa_private_key_, + false); + if (!signature.ok()) { + return signature.status(); + } + response.add_blinded_token_signatures(absl::Base64Escape(*signature)); + } + + return response; +} + +namespace { + +absl::StatusOr +CreateExtensions() { + // Create and serialize fake extensions. + Extensions extensions; + ExpirationTimestamp expiration_timestamp; + int64_t one_hour_away = absl::ToUnixSeconds(absl::Now() + absl::Hours(1)); + expiration_timestamp.timestamp = one_hour_away - (one_hour_away % 900); + expiration_timestamp.timestamp_precision = 900; + absl::StatusOr + expiration_extension = expiration_timestamp.AsExtension(); + if (!expiration_extension.ok()) { + return expiration_extension.status(); + } + extensions.extensions.push_back(*expiration_extension); + + GeoHint geo_hint; + geo_hint.geo_hint = "US,US-AL,ALABASTER"; + absl::StatusOr geo_hint_extension = geo_hint.AsExtension(); + if (!geo_hint_extension.ok()) { + return geo_hint_extension.status(); + } + extensions.extensions.push_back(*geo_hint_extension); + + ServiceType service_type; + service_type.service_type_id = ServiceType::kChromeIpBlinding; + absl::StatusOr service_type_extension = service_type.AsExtension(); + if (!service_type_extension.ok()) { + return service_type_extension.status(); + } + extensions.extensions.push_back(*service_type_extension); + + DebugMode debug_mode; + debug_mode.mode = DebugMode::kDebug; + absl::StatusOr debug_mode_extension = debug_mode.AsExtension(); + if (!debug_mode_extension.ok()) { + return debug_mode_extension.status(); + } + extensions.extensions.push_back(*debug_mode_extension); + + ProxyLayer proxy_layer; + proxy_layer.layer = ProxyLayer::kProxyA; + absl::StatusOr proxy_layer_extension = proxy_layer.AsExtension(); + if (!proxy_layer_extension.ok()) { + return proxy_layer_extension.status(); + } + extensions.extensions.push_back(*proxy_layer_extension); + + return extensions; +} + +RSABlindSignaturePublicKey CreatePublicKeyProto( + TestRsaPublicKey test_rsa_public_key) { + RSAPublicKey public_key; + public_key.set_n(test_rsa_public_key.n); + public_key.set_e(test_rsa_public_key.e); + RSABlindSignaturePublicKey public_key_proto; + public_key_proto.set_key_version(1); + public_key_proto.set_use_case("TEST_USE_CASE"); + public_key_proto.set_serialized_public_key(public_key.SerializeAsString()); + public_key_proto.set_sig_hash_type(AT_HASH_TYPE_SHA384); + public_key_proto.set_mask_gen_function(AT_MGF_SHA384); + public_key_proto.set_salt_length(48); + public_key_proto.set_key_size(256); + public_key_proto.set_message_mask_type(AT_MESSAGE_MASK_NO_MASK); + public_key_proto.set_message_mask_size(0); + + return public_key_proto; +} + +} // namespace + +} // namespace quiche::test diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth_test_data.h b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth_test_data.h new file mode 100644 index 0000000000..389afe17bc --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth_test_data.h @@ -0,0 +1,50 @@ +// Copyright (c) 2025 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_BLIND_SIGN_AUTH_BLIND_SIGN_AUTH_TEST_DATA_H_ +#define QUICHE_BLIND_SIGN_AUTH_BLIND_SIGN_AUTH_TEST_DATA_H_ + +#include +#include +#include + +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" +#include "anonymous_tokens/cpp/crypto/crypto_utils.h" // IWYU pragma: keep +#include "openssl/base.h" +#include "quiche/blind_sign_auth/blind_sign_auth_protos.h" +#include "quiche/common/platform/api/quiche_export.h" + +namespace quiche::test { + +class QUICHE_NO_EXPORT BlindSignAuthTestData { + public: + static absl::StatusOr> Create(); + + privacy::ppn::GetInitialDataResponse CreateGetInitialDataResponse(); + + absl::StatusOr + CreateAttestAndSignResponse(absl::string_view body); + + private: + BlindSignAuthTestData( + bssl::UniquePtr rsa_public_key, bssl::UniquePtr rsa_private_key, + anonymous_tokens::RSABlindSignaturePublicKey + public_key_proto, + privacy::ppn::GetInitialDataResponse::PrivacyPassData privacy_pass_data) + : rsa_public_key_(std::move(rsa_public_key)), + rsa_private_key_(std::move(rsa_private_key)), + public_key_proto_(std::move(public_key_proto)), + privacy_pass_data_(std::move(privacy_pass_data)) {} + + bssl::UniquePtr rsa_public_key_; + bssl::UniquePtr rsa_private_key_; + anonymous_tokens::RSABlindSignaturePublicKey + public_key_proto_; + privacy::ppn::GetInitialDataResponse::PrivacyPassData privacy_pass_data_; +}; + +} // namespace quiche::test + +#endif // QUICHE_BLIND_SIGN_AUTH_BLIND_SIGN_AUTH_TEST_DATA_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_message_interface.h b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_message_interface.h index 8004a0eca1..dc89165e97 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_message_interface.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_message_interface.h @@ -23,6 +23,7 @@ enum class BlindSignMessageRequestType { kUnknown = 0, kGetInitialData, kAuthAndSign, + kAttestAndSign, }; // Interface for async requests in BlindSignAuth. Implementers must send a diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/cached_blind_sign_auth.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/cached_blind_sign_auth.cc index ee5e675c20..61c08a1593 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/cached_blind_sign_auth.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/cached_blind_sign_auth.cc @@ -134,19 +134,11 @@ void CachedBlindSignAuth::RemoveExpiredTokens() { void CachedBlindSignAuth::GetAttestationTokens( int /*num_tokens*/, ProxyLayer /*layer*/, - AttestationDataCallback callback) { + AttestationDataCallback /*attestation_data_callback*/, + SignedTokenCallback token_callback) { // TODO(b/421236538): Implement GetAttestationTokens. - std::move(callback)( + std::move(token_callback)( absl::UnimplementedError("GetAttestationTokens is not implemented")); } -void CachedBlindSignAuth::AttestAndSign( - int /*num_tokens*/, ProxyLayer /*layer*/, std::string /*attestation_data*/, - std::optional /*token_challenge*/, - SignedTokenCallback callback) { - // TODO(b/421236538): Implement AttestAndSign. - std::move(callback)( - absl::UnimplementedError("AttestAndSign is not implemented")); -} - } // namespace quiche diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/cached_blind_sign_auth.h b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/cached_blind_sign_auth.h index 15ee48aa7f..7af5a1cde2 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/cached_blind_sign_auth.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/cached_blind_sign_auth.h @@ -58,21 +58,8 @@ class QUICHE_EXPORT CachedBlindSignAuth : public BlindSignAuthInterface { // AttestationDataCallback should call AttestAndSign with a separate callback // in order to complete the token issuance protocol. void GetAttestationTokens(int num_tokens, ProxyLayer layer, - AttestationDataCallback callback) override; - - // Returns signed unblinded tokens and their expiration time in a callback. - // Tokens are single-use and restricted to the PI use case. - // The GetTokens callback will run on the same thread as the - // BlindSignMessageInterface callbacks. - // This function should be called after the caller has generated - // AttestationData using Keystore and the challenge returned in - // AttestationDataCallback. If a token challenge is provided, it will be used - // in creating the token. Otherwise a default challenge will be used - // containing the issuer hostname. - void AttestAndSign(int num_tokens, ProxyLayer layer, - std::string attestation_data, - std::optional token_challenge, - SignedTokenCallback callback) override; + AttestationDataCallback callback, + SignedTokenCallback token_callback) override; private: void HandleGetTokensResponse( diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/proto/attest_and_sign.proto b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/proto/attest_and_sign.proto new file mode 100644 index 0000000000..c9a90214f5 --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/proto/attest_and_sign.proto @@ -0,0 +1,49 @@ +// Copyright 2023 Google LLC +// +// 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. + +syntax = "proto3"; + +package privacy.ppn; + +import "quiche/blind_sign_auth/proto/attestation.proto"; + +option java_multiple_files = true; +option java_package = "com.google.privacy.ppn.proto"; + +// Client is requesting to auth using the provided auth token. +// Next ID: 6 +message AttestAndSignRequest { + + // A string uniquely identifying the strategy this client should be + // authenticated with. + string service_type = 1; + + // A set of blinded tokens to be signed by phosphor, passed as raw binary + // bytes. + repeated bytes blinded_tokens = 2; + + privacy.ppn.AttestationData attestation = 3; + + // Indicates which key to use for signing. + uint64 key_version = 4; + + // Uses IETF privacy pass extensions spec for format. + bytes public_metadata_extensions = 5; +} + +message AttestAndSignResponse { + // A set of signatures corresponding by index to `blinded_tokens` in the + // request, as raw binary bytes. + repeated bytes blinded_token_signatures = 1; +} diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/proto/spend_token_data.proto b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/proto/spend_token_data.proto index f47cc983d1..1102e7dbe8 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/proto/spend_token_data.proto +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/proto/spend_token_data.proto @@ -19,6 +19,9 @@ package privacy.ppn; import "quiche/blind_sign_auth/proto/public_metadata.proto"; import "anonymous_tokens/proto/anonymous_tokens.proto"; +option java_package = "com.google.privacy.ppn.proto"; +option java_multiple_files = true; + message SpendTokenData { // Public metadata associated with the token being spent. // See go/ppn-token-spend and go/ppn-phosphor-at-service for details. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/test_tools/mock_blind_sign_auth_interface.h b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/test_tools/mock_blind_sign_auth_interface.h index 22c171ff4c..691b729409 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/test_tools/mock_blind_sign_auth_interface.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/test_tools/mock_blind_sign_auth_interface.h @@ -24,12 +24,8 @@ class QUICHE_NO_EXPORT MockBlindSignAuthInterface (override)); MOCK_METHOD(void, GetAttestationTokens, (int num_tokens, ProxyLayer layer, - AttestationDataCallback callback), - (override)); - MOCK_METHOD(void, AttestAndSign, - (int num_tokens, ProxyLayer layer, std::string attestation_data, - std::optional token_challenge, - SignedTokenCallback callback), + AttestationDataCallback attestation_data_callback, + SignedTokenCallback token_callback), (override)); }; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/common/capsule.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/common/capsule.cc index ad25bbcfc9..62fdde645b 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/common/capsule.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/common/capsule.cc @@ -376,7 +376,9 @@ absl::StatusOr SerializeCapsuleWithStatus( capsule.capsule_type(), allocator, WireVarInt62(capsule.web_transport_max_streams().max_stream_count)); case CapsuleType::COMPRESSION_ASSIGN: - QUICHE_DCHECK(capsule.compression_assign_capsule() + QUICHE_DCHECK(capsule.compression_assign_capsule().ip_address_port == + quiche::QuicheSocketAddress() || + capsule.compression_assign_capsule() .ip_address_port.host() .ToPackedString() .size() == QuicheIpAddress::kIPv4AddressSize || @@ -385,8 +387,7 @@ absl::StatusOr SerializeCapsuleWithStatus( .ToPackedString() .size() == QuicheIpAddress::kIPv6AddressSize); if (capsule.compression_assign_capsule() - .ip_address_port.host() - .address_family() != IpAddressFamily::IP_UNSPEC) { + .ip_address_port.IsInitialized()) { return SerializeCapsuleFields( capsule.capsule_type(), allocator, WireVarInt62(capsule.compression_assign_capsule().context_id), @@ -404,11 +405,7 @@ absl::StatusOr SerializeCapsuleWithStatus( return SerializeCapsuleFields( capsule.capsule_type(), allocator, WireVarInt62(capsule.compression_assign_capsule().context_id), - WireUint8(capsule.compression_assign_capsule() - .ip_address_port.host() - .AddressFamilyToInt() == AF_INET - ? 4 - : 6)); + WireUint8(0)); case CapsuleType::COMPRESSION_CLOSE: return SerializeCapsuleFields( capsule.capsule_type(), allocator, diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/common/capsule.h b/naiveproxy/src/net/third_party/quiche/src/quiche/common/capsule.h index 45970dbebc..c7fbbb6f9e 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/common/capsule.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/common/capsule.h @@ -35,10 +35,10 @@ enum class CapsuleType : uint64_t { CLOSE_WEBTRANSPORT_SESSION = 0x2843, DRAIN_WEBTRANSPORT_SESSION = 0x78ae, - // draft-ietf-masque-connect-ip-03. - ADDRESS_ASSIGN = 0x1ECA6A00, - ADDRESS_REQUEST = 0x1ECA6A01, - ROUTE_ADVERTISEMENT = 0x1ECA6A02, + // RFC 9484 - Proxying IP in HTTP. + ADDRESS_ASSIGN = 0x01, + ADDRESS_REQUEST = 0x02, + ROUTE_ADVERTISEMENT = 0x03, // draft-ietf-masque-connect-udp-listen-04. COMPRESSION_ASSIGN = 0x1C0FE323, 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 1e52ff00e6..17eed4a269 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 @@ -12,13 +12,12 @@ QUICHE_FLAG(bool, quiche_reloadable_flag_enable_h3_origin_frame, false, true, "I QUICHE_FLAG(bool, quiche_reloadable_flag_enable_tls_trust_anchor_ids, true, true, "When true, QUIC client and server will support TLS Trust Anchor IDs.") 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_2x_initial_cwnd, false, false, "Doubles the initial congestion window for QUIC connections when initiated by the client") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_allow_client_enabled_2x_initial_cwnd, true, true, "Doubles the initial congestion window for QUIC connections when initiated by the client") 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_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, false, false, "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.") @@ -38,15 +37,12 @@ QUICHE_FLAG(bool, quiche_reloadable_flag_quic_enable_version_rfcv2, false, false QUICHE_FLAG(bool, quiche_reloadable_flag_quic_enobufs_blocked, false, false, "If true, ENOBUFS socket errors are reported as socket blocked instead of socket failure.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_fin_before_completed_http_headers, false, true, "If true, close the connection with error if FIN is received before finish receiving the whole HTTP headers.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_fix_timeouts, true, true, "If true, postpone setting handshake timeout to infinite to handshake complete.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_heapless_key_derivation, false, false, "If true, QUIC key derivation uses heapless crypto utils.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_heapless_obfuscator, true, true, "If true, generates QUIC initial obfuscators with no heap allocations.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_heapless_static_parser, true, true, "If true, stops parsing immediately on unknown version, to avoid a potential malloc when parsing the connection ID") 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_least_unacked_plus_1, false, false, "If true, sets peer_least_packet_awaiting_ack to one more than the highest confirmed acknowledgment to fix an off-by-one error.") 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_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_no_write_control_frame_upon_connection_close2, false, true, "If true, QuicSession will block outgoing control frames when the connection is closed.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_notify_ack_listener_earlier, true, true, "If true, call QuicAckListenerInterface::OnPacketAcked() before moving the stream to closed stream list.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_notify_stream_soon_to_destroy, true, true, "If true, notify each QUIC stream before it gets destroyed and update ACK listener before that.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_on_packet_header_return_connected, false, true, "If true, QuicConnection::OnPacketHeader will return connected_ at the end of the function.") @@ -55,7 +51,6 @@ QUICHE_FLAG(bool, quiche_reloadable_flag_quic_pacing_remove_non_initial_burst, f QUICHE_FLAG(bool, quiche_reloadable_flag_quic_parse_cert_compression_algos_from_chlo, true, true, "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_receive_ack_frequency, false, false, "When true, advertises support for ACK_FREQUENCY and IMMEDIATE_ACK from draft-ietf-quic-ack-frequency-10 and processes them correctly.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_record_tos_byte, false, true, "If true, record TOS byte at QuicPacketReader.") 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_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.") diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/common/quiche_stream.h b/naiveproxy/src/net/third_party/quiche/src/quiche/common/quiche_stream.h index 5a8a1f7798..c8718bd95b 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/common/quiche_stream.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/common/quiche_stream.h @@ -15,6 +15,7 @@ #include "absl/types/span.h" #include "quiche/common/platform/api/quiche_export.h" #include "quiche/common/quiche_callbacks.h" +#include "quiche/common/quiche_mem_slice.h" namespace quiche { @@ -161,42 +162,51 @@ class QUICHE_EXPORT WriteStream { public: virtual ~WriteStream() {} - // Writes |data| into the stream. - virtual absl::Status Writev(absl::Span data, + // Writes `data` into the stream. If the write succeeds, the ownership is + // transferred to the stream; if it does not, the behavior is undefined -- the + // users of this API should check `CanWrite()` before calling `Writev()`. + virtual absl::Status Writev(absl::Span data, const StreamWriteOptions& options) = 0; // Indicates whether it is possible to write into stream right now. virtual bool CanWrite() const = 0; // Legacy convenience method for writing a single string_view. New users - // should use quiche::WriteIntoStream instead, since this method does not + // should use quiche::SendFinOnStream instead, since this method does not // return useful failure information. [[nodiscard]] bool SendFin() { StreamWriteOptions options; options.set_send_fin(true); - return Writev(absl::Span(), options).ok(); + return Writev(absl::Span(), options).ok(); } // Legacy convenience method for writing a single string_view. New users // should use quiche::WriteIntoStream instead, since this method does not // return useful failure information. [[nodiscard]] bool Write(absl::string_view data) { - return Writev(absl::MakeSpan(&data, 1), kDefaultStreamWriteOptions).ok(); + QuicheMemSlice slice = QuicheMemSlice::Copy(data); + return Writev(absl::MakeSpan(&slice, 1), kDefaultStreamWriteOptions).ok(); } }; // Convenience methods to write a single chunk of data into the stream. +inline absl::Status WriteIntoStream( + WriteStream& stream, QuicheMemSlice slice, + const StreamWriteOptions& options = kDefaultStreamWriteOptions) { + return stream.Writev(absl::MakeSpan(&slice, 1), options); +} inline absl::Status WriteIntoStream( WriteStream& stream, absl::string_view data, const StreamWriteOptions& options = kDefaultStreamWriteOptions) { - return stream.Writev(absl::MakeSpan(&data, 1), options); + QuicheMemSlice slice = QuicheMemSlice::Copy(data); + return stream.Writev(absl::MakeSpan(&slice, 1), options); } // Convenience methods to send a FIN on the stream. inline absl::Status SendFinOnStream(WriteStream& stream) { StreamWriteOptions options; options.set_send_fin(true); - return stream.Writev(absl::Span(), options); + return stream.Writev(absl::Span(), options); } } // namespace quiche diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/common/test_tools/mock_streams.h b/naiveproxy/src/net/third_party/quiche/src/quiche/common/test_tools/mock_streams.h index 577a324bc8..7290490331 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/common/test_tools/mock_streams.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/common/test_tools/mock_streams.h @@ -14,6 +14,7 @@ #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "quiche/common/platform/api/quiche_test.h" +#include "quiche/common/quiche_mem_slice.h" #include "quiche/common/quiche_stream.h" namespace quiche::test { @@ -24,22 +25,22 @@ class MockWriteStream : public quiche::WriteStream { MockWriteStream() { ON_CALL(*this, CanWrite()).WillByDefault(testing::Return(true)); ON_CALL(*this, Writev(testing::_, testing::_)) - .WillByDefault([&](absl::Span data, + .WillByDefault([&](absl::Span data, const StreamWriteOptions& options) { return AppendToData(data, options); }); } MOCK_METHOD(absl::Status, Writev, - (absl::Span data, + (absl::Span data, const StreamWriteOptions& options), (override)); MOCK_METHOD(bool, CanWrite, (), (const, override)); - absl::Status AppendToData(absl::Span data, + absl::Status AppendToData(absl::Span data, const StreamWriteOptions& options) { - for (absl::string_view fragment : data) { - data_.append(fragment.data(), fragment.size()); + for (const quiche::QuicheMemSlice& fragment : data) { + data_.append(fragment.data(), fragment.length()); } ProcessOptions(options); return absl::OkStatus(); 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 f00ac6109a..fffd59a261 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 @@ -290,6 +290,17 @@ class QUICHE_EXPORT Http2VisitorInterface { return {-1, false}; } + // Invoked when this endpoint is no longer able to send data to the peer + // because the stream or connection flow control send window has been + // exhausted. A `stream_id` of zero indicates the connection level flow + // control window. + virtual void OnLocalFlowControlExhausted(Http2StreamId /*stream_id*/) {} + + // Invoked when the peer is no longer able to send data to this endpoint + // because the flow control receive window has been exhausted. A `stream_id` + // of zero indicates the connection level flow control window. + virtual void OnRemoteFlowControlExhausted(Http2StreamId /*stream_id*/) {} + // 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 2e68cb2ba7..78e8d7af50 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 @@ -124,6 +124,12 @@ class QUICHE_NO_EXPORT MockHttp2Visitor : public Http2VisitorInterface { (Http2StreamId stream_id, uint8_t* dest, size_t dest_len), (override)); + MOCK_METHOD(void, OnLocalFlowControlExhausted, (Http2StreamId stream_id), + (override)); + + MOCK_METHOD(void, OnRemoteFlowControlExhausted, (Http2StreamId stream_id), + (override)); + MOCK_METHOD(void, OnErrorDebug, (absl::string_view message), (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 c25b2917b5..f757a2ca90 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 @@ -841,11 +841,13 @@ OgHttp2Session::SendResult OgHttp2Session::WriteForStream( } return SendResult::SEND_OK; } + bool wrote_data = false; int32_t available_window = std::min({connection_send_window_, state.send_window, static_cast(max_frame_payload_)}); while (connection_can_write == SendResult::SEND_OK && available_window > 0 && IsReadyToWriteData(state)) { + wrote_data = true; DataFrameHeaderInfo info = GetDataFrameInfo(stream_id, available_window, state); QUICHE_VLOG(3) << "WriteForStream | length: " << info.payload_length @@ -925,10 +927,19 @@ OgHttp2Session::SendResult OgHttp2Session::WriteForStream( } // If the stream still exists and has data to send, it should be marked as // ready in the write scheduler. - if (stream_map_.contains(stream_id) && !state.data_deferred && - state.send_window > 0 && HasMoreData(state)) { + const bool stream_exists = stream_map_.contains(stream_id); + if (stream_exists && !state.data_deferred && state.send_window > 0 && + HasMoreData(state)) { write_scheduler_.MarkStreamReady(stream_id, false); } + if (wrote_data) { + if (connection_send_window_ <= 0) { + visitor_.OnLocalFlowControlExhausted(0); + } + if (stream_exists && state.send_window <= 0) { + visitor_.OnLocalFlowControlExhausted(stream_id); + } + } // Streams can continue writing as long as the connection is not write-blocked // and there is additional flow control quota available. if (connection_can_write != SendResult::SEND_OK) { @@ -1152,11 +1163,15 @@ void OgHttp2Session::OnDataFrameHeader(spdy::SpdyStreamId stream_id, void OgHttp2Session::OnStreamFrameData(spdy::SpdyStreamId stream_id, const char* data, size_t len) { - // Count the data against flow control, even if the stream is unknown. + // Count the data against flow control, even if the stream is unknown, so that + // the connection flow control window is in sync with peer's. MarkDataBuffered(stream_id, len); auto iter = stream_map_.find(stream_id); if (iter == stream_map_.end()) { + // Mark the data consumed immediately as we are dropping them. This will + // allow the connection flow control window to shift. + Consume(stream_id, len); return; } // Validate against the content-length if it exists. @@ -1171,6 +1186,9 @@ void OgHttp2Session::OnStreamFrameData(spdy::SpdyStreamId stream_id, if (streams_reset_.contains(stream_id)) { // If the stream was unknown due to a protocol error, the visitor was // informed in OnDataFrameHeader(). + // Mark the data consumed immediately as we are dropping them. This will + // allow the connection flow control window to shift. + Consume(stream_id, len); return; } @@ -1836,9 +1854,17 @@ void OgHttp2Session::MaybeFinWithRstStream(StreamStateMap::iterator iter) { } void OgHttp2Session::MarkDataBuffered(Http2StreamId stream_id, size_t bytes) { - connection_window_manager_.MarkDataBuffered(bytes); + const bool peer_connection_window_available = + connection_window_manager_.MarkDataBuffered(bytes); + if (!peer_connection_window_available) { + visitor_.OnRemoteFlowControlExhausted(0); + } if (auto it = stream_map_.find(stream_id); it != stream_map_.end()) { - it->second.window_manager.MarkDataBuffered(bytes); + const bool peer_stream_window_available = + it->second.window_manager.MarkDataBuffered(bytes); + if (!peer_stream_window_available) { + visitor_.OnRemoteFlowControlExhausted(stream_id); + } } } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/window_manager.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/window_manager.h index ffe1a7f623..c843fa7857 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/window_manager.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/window_manager.h @@ -68,11 +68,11 @@ class QUICHE_EXPORT WindowManager { void MaybeNotifyListener(); - // The upper bound on the flow control window. The GFE attempts to maintain a - // window of this size at the peer as data is proxied through. + // The upper bound on the flow control window. This endpoint attempts to + // maintain a window of this size at the peer as data is proxied through. int64_t limit_; - // The current flow control window that has not been advertised to the peer + // The current flow control window that has been advertised to the peer // and not yet consumed. The peer can send this many bytes before becoming // blocked. int64_t window_; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_misc.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_misc.cc index 1e646829cb..c2bafd2ae7 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_misc.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_misc.cc @@ -156,11 +156,11 @@ void Bbr2NetworkModel::OnCongestionEventStart( congestion_event->prior_bytes_in_flight - congestion_event->bytes_acked - congestion_event->bytes_lost; } else { - QUIC_BUG(quic_bbr2_prior_in_flight_too_small) - << "prior_bytes_in_flight:" << congestion_event->prior_bytes_in_flight - << " is smaller than the sum of bytes_acked:" - << congestion_event->bytes_acked - << " and bytes_lost:" << congestion_event->bytes_lost; + QUIC_LOG(ERROR) << "prior_bytes_in_flight:" + << congestion_event->prior_bytes_in_flight + << " is smaller than the sum of bytes_acked:" + << congestion_event->bytes_acked + << " and bytes_lost:" << congestion_event->bytes_lost; congestion_event->bytes_in_flight = 0; } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/cert_compressor.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/cert_compressor.cc index 514e211eb7..5e336c21ba 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/cert_compressor.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/cert_compressor.cc @@ -4,17 +4,16 @@ #include "quiche/quic/core/crypto/cert_compressor.h" +#include #include +#include #include #include -#include #include #include "absl/strings/string_view.h" #include "quiche/quic/core/quic_utils.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" #include namespace quic { @@ -155,7 +154,7 @@ static const unsigned char kCommonCertSubstrings[] = { // the three types enumerated in |Type|. struct CertEntry { public: - enum Type { + enum Type : uint8_t { // Type 0 is reserved to mean "end of list" in the wire format. // COMPRESSED means that the certificate is included in the trailing zlib @@ -168,8 +167,6 @@ struct CertEntry { Type type; uint64_t hash; - uint64_t set_hash; - uint32_t index; }; // MatchCerts returns a vector of CertEntries describing how to most @@ -332,6 +329,8 @@ bool ParseEntries(absl::string_view* in_out, break; } + // Casting out-of-range values to an enum can be undefined behavior. This + // cast is safe `CertEntry::Type`'s underlying type is fixed. entry.type = static_cast(type_byte); switch (entry.type) { 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 9056c47b28..c8dd332f34 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 @@ -217,6 +217,8 @@ DEFINE_STATIC_QUIC_TAG(AFF1); // Use SRTT in building // AckFrequencyFrame. DEFINE_STATIC_QUIC_TAG(AFF2); // Send AckFrequencyFrame upon // handshake completion. +DEFINE_STATIC_QUIC_TAG(AFIA); // Send MinAckDelay transport parameter to allow + // receipt of ACK_FREQUENCY and IMMEDIATE_ACK DEFINE_STATIC_QUIC_TAG(SSLR); // Slow Start Large Reduction. DEFINE_STATIC_QUIC_TAG(NPRR); // Pace at unity instead of PRR DEFINE_STATIC_QUIC_TAG(5RTO); // Close connection on 5 RTOs @@ -445,6 +447,13 @@ DEFINE_STATIC_QUIC_TAG(ROWF); // Send first 1-RTT packet on // ROWP timeout. DEFINE_STATIC_QUIC_TAG(ROWR); // Send random bytes on ROWP // timeout. + +// Retransmittable on wire timeout experiment. +// TODO: b/427246911 - Remove these tags once the experiment is complete. +DEFINE_STATIC_QUIC_TAG(ROW1); // Set retransmittable on wire timeout to 1*PTO. +DEFINE_STATIC_QUIC_TAG(ROW2); // Set retransmittable on wire timeout to 2*PTO. +DEFINE_STATIC_QUIC_TAG(ROW3); // Set retransmittable on wire timeout to 3*PTO. + // Selective Resumption variants. DEFINE_STATIC_QUIC_TAG(GSR0); DEFINE_STATIC_QUIC_TAG(GSR1); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_utils.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_utils.cc index 8aecaef0cf..5fb548057e 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_utils.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_utils.cc @@ -10,7 +10,6 @@ #include #include #include -#include #include "absl/base/macros.h" #include "absl/strings/str_cat.h" @@ -40,8 +39,6 @@ #include "quiche/quic/core/quic_utils.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/quic/platform/api/quic_logging.h" #include "quiche/common/quiche_endian.h" #include "quiche/common/wire_serialization.h" @@ -68,7 +65,6 @@ inline constexpr size_t kMaxIVSize = 12; // |out_len|, respectively. The resulting expanded secret is returned. bool HkdfExpandLabel(const EVP_MD* prf, absl::Span secret, absl::string_view label, absl::Span out) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_heapless_obfuscator, 2, 7); constexpr absl::string_view kLabelPrefix = "tls13 "; constexpr size_t kMaxLabelLength = 10; // "quicv2 key" is the longest QUICHE_DCHECK_LE(label.length(), kMaxLabelLength); @@ -94,48 +90,6 @@ bool HkdfExpandLabel(const EVP_MD* prf, absl::Span secret, } return true; } -// Legacy overloaded version that accepts string and returns vector, which leads -// to heap allocations. -// TODO(martinduke): Delete this. -std::vector HkdfExpandLabel(const EVP_MD* prf, - absl::Span secret, - const std::string& label, size_t out_len) { - if (GetQuicReloadableFlag(quic_heapless_key_derivation)) { - // This value should be zero; the flag should eliminate all paths to here. - QUIC_RELOADABLE_FLAG_COUNT_N(quic_heapless_key_derivation, 1, 10); - } - bssl::ScopedCBB quic_hkdf_label; - CBB inner_label; - const char label_prefix[] = "tls13 "; - // 20 = size(u16) + size(u8) + len("tls13 ") + - // max_len("client in", "server in", "quicv2 key", ... ) + - // size(u8); - static const size_t max_quic_hkdf_label_length = 20; - if (!CBB_init(quic_hkdf_label.get(), max_quic_hkdf_label_length) || - !CBB_add_u16(quic_hkdf_label.get(), out_len) || - !CBB_add_u8_length_prefixed(quic_hkdf_label.get(), &inner_label) || - !CBB_add_bytes(&inner_label, - reinterpret_cast(label_prefix), - ABSL_ARRAYSIZE(label_prefix) - 1) || - !CBB_add_bytes(&inner_label, - reinterpret_cast(label.data()), - label.size()) || - // Zero length |Context|. - !CBB_add_u8(quic_hkdf_label.get(), 0) || - !CBB_flush(quic_hkdf_label.get())) { - QUIC_LOG(ERROR) << "Building HKDF label failed"; - return std::vector(); - } - std::vector out; - out.resize(out_len); - if (!HKDF_expand(out.data(), out_len, prf, secret.data(), secret.size(), - CBB_data(quic_hkdf_label.get()), - CBB_len(quic_hkdf_label.get()))) { - QUIC_LOG(ERROR) << "Running HKDF-Expand-Label failed"; - return std::vector(); - } - return out; -} // "quicv2 key" is the longest string for a version label. constexpr size_t kMaxVersionLabelLength = 10; @@ -147,7 +101,6 @@ constexpr size_t kMaxVersionLabelLength = 10; absl::string_view GetLabelForVersion(const ParsedQuicVersion& version, absl::string_view predicate, absl::Span out) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_heapless_obfuscator, 3, 7); static_assert(SupportedVersions().size() == 4u, "Supported versions out of sync with HKDF labels"); QuicDataWriter writer(out.size(), out.data()); @@ -161,30 +114,13 @@ absl::string_view GetLabelForVersion(const ParsedQuicVersion& version, writer.WriteStringPiece(predicate); return absl::string_view(out.data(), writer.length()); } -// Legacy overloaded version that returns string, leading to a heap allocation. -// TODO(martinduke): Delete this. -std::string getLabelForVersion(const ParsedQuicVersion& version, - const absl::string_view& predicate) { - if (GetQuicReloadableFlag(quic_heapless_key_derivation)) { - // This value should be zero; the flag should eliminate all paths to here. - QUIC_RELOADABLE_FLAG_COUNT_N(quic_heapless_key_derivation, 2, 10); - } - static_assert(SupportedVersions().size() == 4u, - "Supported versions out of sync with HKDF labels"); - if (version == ParsedQuicVersion::RFCv2()) { - return absl::StrCat("quicv2 ", predicate); - } else { - return absl::StrCat("quic ", predicate); - } -} // static void CryptoUtils::InitializeCrypterSecrets(const EVP_MD* prf, absl::Span pp_secret, const ParsedQuicVersion& version, QuicCrypter* crypter) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_heapless_obfuscator, 4, 7); - SetKeyAndIVHeapless(prf, pp_secret, version, crypter); + SetKeyAndIV(prf, pp_secret, version, crypter); uint8_t header_protection_key[kMaxKeySize]; QUIC_BUG_IF(quic_bug_hp_length_mismatch, crypter->GetKeySize() > sizeof(header_protection_key)) @@ -195,29 +131,12 @@ void CryptoUtils::InitializeCrypterSecrets(const EVP_MD* prf, crypter->SetHeaderProtectionKey(absl::string_view( reinterpret_cast(header_protection_key), crypter->GetKeySize())); } -// Version that uses the heap. -// TODO(martinduke): Delete this. -void CryptoUtils::InitializeCrypterSecrets( - const EVP_MD* prf, const std::vector& pp_secret, - const ParsedQuicVersion& version, QuicCrypter* crypter) { - if (GetQuicReloadableFlag(quic_heapless_key_derivation)) { - // This value should be zero; the flag should eliminate all paths to here. - QUIC_RELOADABLE_FLAG_COUNT_N(quic_heapless_key_derivation, 3, 10); - } - SetKeyAndIV(prf, pp_secret, version, crypter); - std::vector header_protection_key = GenerateHeaderProtectionKey( - prf, pp_secret, version, crypter->GetKeySize()); - crypter->SetHeaderProtectionKey( - absl::string_view(reinterpret_cast(header_protection_key.data()), - header_protection_key.size())); -} // static -void CryptoUtils::SetKeyAndIVHeapless(const EVP_MD* prf, - absl::Span pp_secret, - const ParsedQuicVersion& version, - QuicCrypter* crypter) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_heapless_obfuscator, 5, 7); +void CryptoUtils::SetKeyAndIV(const EVP_MD* prf, + absl::Span pp_secret, + const ParsedQuicVersion& version, + QuicCrypter* crypter) { uint8_t key[kMaxKeySize]; QUIC_BUG_IF(quic_bug_key_length_mismatch, crypter->GetKeySize() > sizeof(key)) << "Key length does not match crypter"; @@ -243,31 +162,11 @@ void CryptoUtils::SetKeyAndIVHeapless(const EVP_MD* prf, crypter->SetIV( absl::string_view(reinterpret_cast(iv), crypter->GetIVSize())); } -// TODO(martinduke): Delete this. -void CryptoUtils::SetKeyAndIV(const EVP_MD* prf, - absl::Span pp_secret, - const ParsedQuicVersion& version, - QuicCrypter* crypter) { - if (GetQuicReloadableFlag(quic_heapless_key_derivation)) { - // This value should be zero; the flag should eliminate all paths to here. - QUIC_RELOADABLE_FLAG_COUNT_N(quic_heapless_key_derivation, 4, 10); - } - std::vector key = - HkdfExpandLabel(prf, pp_secret, getLabelForVersion(version, "key"), - crypter->GetKeySize()); - std::vector iv = HkdfExpandLabel( - prf, pp_secret, getLabelForVersion(version, "iv"), crypter->GetIVSize()); - crypter->SetKey( - absl::string_view(reinterpret_cast(key.data()), key.size())); - crypter->SetIV( - absl::string_view(reinterpret_cast(iv.data()), iv.size())); -} // static bool CryptoUtils::GenerateHeaderProtectionKey( const EVP_MD* prf, absl::Span pp_secret, const ParsedQuicVersion& version, absl::Span out) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_heapless_obfuscator, 6, 7); char version_label_raw[kMaxVersionLabelLength]; constexpr absl::string_view kHeaderProtectionPredicate = "hp"; absl::string_view version_label = GetLabelForVersion( @@ -275,23 +174,11 @@ bool CryptoUtils::GenerateHeaderProtectionKey( absl::Span(version_label_raw, kMaxVersionLabelLength)); return HkdfExpandLabel(prf, pp_secret, version_label, out); } -// TODO(martinduke): Delete this. -std::vector CryptoUtils::GenerateHeaderProtectionKey( - const EVP_MD* prf, absl::Span pp_secret, - const ParsedQuicVersion& version, size_t out_len) { - if (GetQuicReloadableFlag(quic_heapless_key_derivation)) { - // This value should be zero; the flag should eliminate all paths to here. - QUIC_RELOADABLE_FLAG_COUNT_N(quic_heapless_key_derivation, 5, 10); - } - return HkdfExpandLabel(prf, pp_secret, getLabelForVersion(version, "hp"), - out_len); -} // static bool CryptoUtils::GenerateNextKeyPhaseSecret( const EVP_MD* prf, const ParsedQuicVersion& version, const absl::Span current_secret, absl::Span out) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_heapless_obfuscator, 7, 7); char version_label_raw[kMaxVersionLabelLength]; constexpr absl::string_view kKeyUpdatePredicate = "ku"; absl::string_view version_label = GetLabelForVersion( @@ -299,17 +186,6 @@ bool CryptoUtils::GenerateNextKeyPhaseSecret( absl::Span(version_label_raw, kMaxVersionLabelLength)); return HkdfExpandLabel(prf, current_secret, version_label, out); } -// TODO(martinduke): Delete this. -std::vector CryptoUtils::GenerateNextKeyPhaseSecret( - const EVP_MD* prf, const ParsedQuicVersion& version, - const std::vector& current_secret) { - if (GetQuicReloadableFlag(quic_heapless_key_derivation)) { - // This value should be zero; the flag should eliminate all paths to here. - QUIC_RELOADABLE_FLAG_COUNT_N(quic_heapless_key_derivation, 6, 10); - } - return HkdfExpandLabel(prf, current_secret, getLabelForVersion(version, "ku"), - current_secret.size()); -} namespace { @@ -497,16 +373,15 @@ void CryptoUtils::PopulateInitialObfuscators(Perspective perspective, } // static -void CryptoUtils::CreateInitialObfuscatorsNew(Perspective perspective, - ParsedQuicVersion version, - QuicConnectionId connection_id, - CrypterPair* crypters) { +void CryptoUtils::CreateInitialObfuscators(Perspective perspective, + ParsedQuicVersion version, + QuicConnectionId connection_id, + CrypterPair* crypters) { if (!version.UsesInitialObfuscators()) { crypters->encrypter = std::make_unique(perspective); crypters->decrypter = std::make_unique(perspective); return; } - QUIC_RELOADABLE_FLAG_COUNT_N(quic_heapless_obfuscator, 1, 7); crypters->encrypter = std::make_unique(); crypters->decrypter = std::make_unique(); @@ -514,66 +389,6 @@ void CryptoUtils::CreateInitialObfuscatorsNew(Perspective perspective, crypters->encrypter.get(), crypters->decrypter.get()); } -// static -void CryptoUtils::CreateInitialObfuscators(Perspective perspective, - ParsedQuicVersion version, - QuicConnectionId connection_id, - CrypterPair* crypters) { - if (GetQuicReloadableFlag(quic_heapless_obfuscator)) { - CreateInitialObfuscatorsNew(perspective, version, connection_id, crypters); - return; - } - QUIC_DLOG(INFO) << "Creating " - << (perspective == Perspective::IS_CLIENT ? "client" - : "server") - << " crypters for version " << version << " with CID " - << connection_id; - if (!version.UsesInitialObfuscators()) { - crypters->encrypter = std::make_unique(perspective); - crypters->decrypter = std::make_unique(perspective); - return; - } - QUIC_BUG_IF(quic_bug_12871_1, !QuicUtils::IsConnectionIdValidForVersion( - connection_id, version.transport_version)) - << "CreateTlsInitialCrypters: attempted to use connection ID " - << connection_id << " which is invalid with version " << version; - const EVP_MD* hash = EVP_sha256(); - - size_t salt_len; - const uint8_t* salt = InitialSaltForVersion(version, &salt_len); - std::vector handshake_secret; - handshake_secret.resize(EVP_MAX_MD_SIZE); - size_t handshake_secret_len; - const bool hkdf_extract_success = - HKDF_extract(handshake_secret.data(), &handshake_secret_len, hash, - reinterpret_cast(connection_id.data()), - connection_id.length(), salt, salt_len); - QUIC_BUG_IF(quic_bug_12871_2, !hkdf_extract_success) - << "HKDF_extract failed when creating initial crypters"; - handshake_secret.resize(handshake_secret_len); - - const std::string client_label = "client in"; - const std::string server_label = "server in"; - std::string encryption_label, decryption_label; - if (perspective == Perspective::IS_CLIENT) { - encryption_label = client_label; - decryption_label = server_label; - } else { - encryption_label = server_label; - decryption_label = client_label; - } - std::vector encryption_secret = HkdfExpandLabel( - hash, handshake_secret, encryption_label, EVP_MD_size(hash)); - crypters->encrypter = std::make_unique(); - InitializeCrypterSecrets(hash, encryption_secret, version, - crypters->encrypter.get()); - - std::vector decryption_secret = HkdfExpandLabel( - hash, handshake_secret, decryption_label, EVP_MD_size(hash)); - crypters->decrypter = std::make_unique(); - InitializeCrypterSecrets(hash, decryption_secret, version, - crypters->decrypter.get()); -} // static bool CryptoUtils::ValidateRetryIntegrityTag( diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_utils.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_utils.h index f1541abd01..d496fbf860 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_utils.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_utils.h @@ -10,7 +10,6 @@ #include #include #include -#include #include "absl/strings/string_view.h" #include "absl/types/span.h" @@ -84,23 +83,11 @@ class QUICHE_EXPORT CryptoUtils { absl::Span pp_secret, const ParsedQuicVersion& version, QuicCrypter* crypter); - // Overloaded legacy version that takes a vector. - // TODO(martinduke): Delete this. - static void InitializeCrypterSecrets(const EVP_MD* prf, - const std::vector& pp_secret, - const ParsedQuicVersion& version, - QuicCrypter* crypter); // Derives the key and IV from the packet protection secret and sets those // fields on the given QuicCrypter |*crypter|, but does not set the header // protection key. GenerateHeaderProtectionKey/SetHeaderProtectionKey must be // called before using |crypter|. - static void SetKeyAndIVHeapless(const EVP_MD* prf, - absl::Span pp_secret, - const ParsedQuicVersion& version, - QuicCrypter* crypter); - // TODO(martinduke): Delete this legacy version that allocates more from the - // heap. static void SetKeyAndIV(const EVP_MD* prf, absl::Span pp_secret, const ParsedQuicVersion& version, @@ -113,20 +100,12 @@ class QUICHE_EXPORT CryptoUtils { absl::Span pp_secret, const ParsedQuicVersion& version, absl::Span out); - // Overloaded legacy version that allocates the vector. - static std::vector GenerateHeaderProtectionKey( - const EVP_MD* prf, absl::Span pp_secret, - const ParsedQuicVersion& version, size_t out_len); // Given a secret for key phase n, return the secret for phase n+1 in |out|. // Returns true if the derivation was successful, false otherwise. static bool GenerateNextKeyPhaseSecret( const EVP_MD* prf, const ParsedQuicVersion& version, absl::Span current_secret, absl::Span out); - // Overloaded legacy version that allocates the vector. - static std::vector GenerateNextKeyPhaseSecret( - const EVP_MD* prf, const ParsedQuicVersion& version, - const std::vector& current_secret); // Assumes Initial crypters have already been allocated, to create a path // with heap allocations limited to those inherited from OpenSSL. |encrypter| @@ -147,10 +126,6 @@ class QUICHE_EXPORT CryptoUtils { // as setting the key and IV on those crypters. For older versions of QUIC // that do not use the new IETF style ENCRYPTION_INITIAL obfuscators, this // function puts a NullEncrypter and NullDecrypter in |*crypters|. - static void CreateInitialObfuscatorsNew(Perspective perspective, - ParsedQuicVersion version, - QuicConnectionId connection_id, - CrypterPair* crypters); static void CreateInitialObfuscators(Perspective perspective, ParsedQuicVersion version, QuicConnectionId connection_id, diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_ack_frame.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_ack_frame.cc index b2f7a58244..b2746729b1 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_ack_frame.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_ack_frame.cc @@ -7,10 +7,9 @@ #include #include -#include "quiche/quic/core/quic_constants.h" #include "quiche/quic/core/quic_interval.h" +#include "quiche/quic/core/quic_packet_number.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" -#include "quiche/quic/platform/api/quic_flag_utils.h" namespace quic { @@ -150,6 +149,11 @@ PacketNumberQueue::const_reverse_iterator PacketNumberQueue::rend() const { return packet_number_intervals_.rend(); } +PacketNumberQueue::const_iterator PacketNumberQueue::LowerBound( + QuicPacketNumber packet_number) const { + return packet_number_intervals_.LowerBound(packet_number); +} + QuicPacketCount PacketNumberQueue::LastIntervalLength() const { QUICHE_DCHECK(!Empty()); return packet_number_intervals_.rbegin()->Length(); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_ack_frame.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_ack_frame.h index bafc755d67..d4ccb66541 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_ack_frame.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_ack_frame.h @@ -7,11 +7,10 @@ #include -#include "quiche/quic/core/quic_interval.h" #include "quiche/quic/core/quic_interval_set.h" +#include "quiche/quic/core/quic_packet_number.h" #include "quiche/quic/core/quic_types.h" -#include "quiche/quic/platform/api/quic_export.h" -#include "quiche/quic/platform/api/quic_flags.h" +#include "quiche/common/platform/api/quiche_export.h" namespace quic { @@ -80,6 +79,9 @@ class QUICHE_EXPORT PacketNumberQueue { const_iterator end() const; const_reverse_iterator rbegin() const; const_reverse_iterator rend() const; + // Returns the iterator to the first interval that contains or is greater than + // |packet_number|. + const_iterator LowerBound(QuicPacketNumber packet_number) const; friend QUICHE_EXPORT std::ostream& operator<<(std::ostream& os, const PacketNumberQueue& q); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base.cc index 2ee027b3ff..e7fc445944 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base.cc @@ -254,21 +254,6 @@ bool QuicServerSessionBase::ShouldCreateOutgoingBidirectionalStream() { return CanOpenNextOutgoingBidirectionalStream(); } -bool QuicServerSessionBase::ShouldCreateOutgoingUnidirectionalStream() { - if (!connection()->connected()) { - QUIC_BUG(quic_bug_12513_3) - << "ShouldCreateOutgoingUnidirectionalStream called when disconnected"; - return false; - } - if (!crypto_stream_->encryption_established()) { - QUIC_BUG(quic_bug_10393_5) - << "Encryption not established so no outgoing stream created."; - return false; - } - - return CanOpenNextOutgoingUnidirectionalStream(); -} - QuicCryptoServerStreamBase* QuicServerSessionBase::GetMutableCryptoStream() { return crypto_stream_.get(); } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base.h index 527ee931cf..c38c6152ae 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base.h @@ -87,7 +87,6 @@ class QUICHE_EXPORT QuicServerSessionBase : public QuicSpdySession { // established yet or number of server initiated streams already reaches the // upper limit. bool ShouldCreateOutgoingBidirectionalStream() override; - bool ShouldCreateOutgoingUnidirectionalStream() override; // If we should create an incoming stream, returns true. Otherwise // does error handling, including communicating the error to the client and diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session.cc index 07828be00b..901dbd4b25 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session.cc @@ -69,12 +69,6 @@ bool QuicSpdyClientSession::ShouldCreateOutgoingBidirectionalStream() { return CanOpenNextOutgoingBidirectionalStream(); } -bool QuicSpdyClientSession::ShouldCreateOutgoingUnidirectionalStream() { - QUIC_BUG(quic_bug_10396_1) - << "Try to create outgoing unidirectional client data streams"; - return false; -} - QuicSpdyClientStream* QuicSpdyClientSession::CreateOutgoingBidirectionalStream() { if (!ShouldCreateOutgoingBidirectionalStream()) { @@ -86,13 +80,6 @@ QuicSpdyClientSession::CreateOutgoingBidirectionalStream() { return stream_ptr; } -QuicSpdyClientStream* -QuicSpdyClientSession::CreateOutgoingUnidirectionalStream() { - QUIC_BUG(quic_bug_10396_2) - << "Try to create outgoing unidirectional client data streams"; - return nullptr; -} - std::unique_ptr QuicSpdyClientSession::CreateClientStream() { return std::make_unique( diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session.h index da320bb167..fc9838ab1b 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session.h @@ -45,7 +45,6 @@ class QUICHE_EXPORT QuicSpdyClientSession : public QuicSpdyClientSessionBase { // QuicSession methods: QuicSpdyClientStream* CreateOutgoingBidirectionalStream() override; - QuicSpdyClientStream* CreateOutgoingUnidirectionalStream() override; QuicCryptoClientStreamBase* GetMutableCryptoStream() override; const QuicCryptoClientStreamBase* GetCryptoStream() const override; @@ -100,7 +99,6 @@ class QUICHE_EXPORT QuicSpdyClientSession : public QuicSpdyClientSessionBase { QuicSpdyStream* CreateIncomingStream(PendingStream* pending) override; // If an outgoing stream can be created, return true. bool ShouldCreateOutgoingBidirectionalStream() override; - bool ShouldCreateOutgoingUnidirectionalStream() override; // If an incoming stream can be created, return true. // TODO(fayang): move this up to QuicSpdyClientSessionBase. 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 f0cf2cab19..91f81750ab 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 @@ -609,6 +609,10 @@ void QuicSpdySession::Initialize() { // Limit HPACK buffering to 2x header list size limit. h2_deframer_.GetHpackDecoder().set_max_decode_buffer_size_bytes( 2 * max_inbound_header_list_size_); + + if (ShouldNegotiateWebTransport()) { + connection()->sent_packet_manager().EnableOverheadMeasurement(); + } } void QuicSpdySession::FillSettingsFrame() { 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 4369cca734..e303c4d97a 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 @@ -93,7 +93,7 @@ class QUICHE_EXPORT Http3DebugVisitor { QuicStreamId /*stream_id*/, QuicByteCount /*compressed_headers_length*/) = 0; virtual void OnHeadersDecoded(QuicStreamId /*stream_id*/, - QuicHeaderList /*headers*/) = 0; + const QuicHeaderList& /*headers*/) = 0; // Incoming HTTP/3 frames of unknown type on any stream. virtual void OnUnknownFrameReceived(QuicStreamId /*stream_id*/, @@ -115,6 +115,12 @@ class QUICHE_EXPORT Http3DebugVisitor { // 0-RTT related events. virtual void OnSettingsFrameResumed(const SettingsFrame& /*frame*/) = 0; + + // Metadata related events. + virtual void OnMetadataFrameStart(QuicByteCount /*header_length*/, + QuicByteCount /*payload_length*/) {} + virtual void OnMetadataFramePayload(absl::string_view /*payload*/) {} + virtual void OnMetadataFrameEnd() {} }; // Whether HTTP Datagrams are supported on this session and if so which version @@ -484,13 +490,12 @@ class QUICHE_EXPORT QuicSpdySession bool settings_received() const { return settings_received_; } protected: - // Override CreateIncomingStream(), CreateOutgoingBidirectionalStream() and - // CreateOutgoingUnidirectionalStream() with QuicSpdyStream return type to - // make sure that all data streams are QuicSpdyStreams. + // Override CreateIncomingStream() with QuicSpdyStream return type to + // ensure that all data streams are QuicSpdyStreams. QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override = 0; QuicSpdyStream* CreateIncomingStream(PendingStream* pending) override = 0; + // Called to create a new outgoing bidirectional stream. virtual QuicSpdyStream* CreateOutgoingBidirectionalStream() = 0; - virtual QuicSpdyStream* CreateOutgoingUnidirectionalStream() = 0; // If an incoming stream can be created, return true. virtual bool ShouldCreateIncomingStream(QuicStreamId id) = 0; @@ -498,7 +503,6 @@ class QUICHE_EXPORT QuicSpdySession // If an outgoing bidirectional/unidirectional stream can be created, return // true. virtual bool ShouldCreateOutgoingBidirectionalStream() = 0; - virtual bool ShouldCreateOutgoingUnidirectionalStream() = 0; // Indicates whether the underlying backend can accept and process // WebTransport sessions over HTTP/3. 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 bc00e87dbe..f3b07ed6cf 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 @@ -1249,6 +1249,11 @@ void QuicSpdyStream::OnWebTransportStreamFrameType( bool QuicSpdyStream::OnMetadataFrameStart(QuicByteCount header_length, QuicByteCount payload_length) { + if (spdy_session_->debug_visitor()) { + spdy_session_->debug_visitor()->OnMetadataFrameStart(header_length, + payload_length); + } + if (metadata_visitor_ == nullptr) { return OnUnknownFrameStart( static_cast(quic::HttpFrameType::METADATA), header_length, @@ -1268,6 +1273,10 @@ bool QuicSpdyStream::OnMetadataFrameStart(QuicByteCount header_length, } bool QuicSpdyStream::OnMetadataFramePayload(absl::string_view payload) { + if (spdy_session_->debug_visitor()) { + spdy_session_->debug_visitor()->OnMetadataFramePayload(payload); + } + if (metadata_visitor_ == nullptr) { return OnUnknownFramePayload(payload); } @@ -1286,6 +1295,10 @@ bool QuicSpdyStream::OnMetadataFramePayload(absl::string_view payload) { } bool QuicSpdyStream::OnMetadataFrameEnd() { + if (spdy_session_->debug_visitor()) { + spdy_session_->debug_visitor()->OnMetadataFrameEnd(); + } + if (metadata_visitor_ == nullptr) { return OnUnknownFrameEnd(); } 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 86d60860f9..e2d1466589 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 @@ -188,12 +188,7 @@ void WebTransportHttp3::HeadersReceived( rejection_reason_ = WebTransportHttp3RejectionReason::kWrongStatusCode; return; } - WebTransportHttp3RejectionReason subprotocol_result = - MaybeSetSubprotocolFromResponseHeaders(headers); - if (subprotocol_result != WebTransportHttp3RejectionReason::kNone) { - rejection_reason_ = subprotocol_result; - return; - } + MaybeSetSubprotocolFromResponseHeaders(headers); } QUIC_DVLOG(1) << ENDPOINT << "WebTransport session " << id_ << " ready."; @@ -483,12 +478,11 @@ uint64_t WebTransportErrorToHttp3( webtransport_error_code / 0x1e; } -WebTransportHttp3RejectionReason -WebTransportHttp3::MaybeSetSubprotocolFromResponseHeaders( +void WebTransportHttp3::MaybeSetSubprotocolFromResponseHeaders( const quiche::HttpHeaderBlock& headers) { auto subprotocol_it = headers.find(webtransport::kSubprotocolResponseHeader); if (subprotocol_it == headers.end()) { - return WebTransportHttp3RejectionReason::kNone; + return; } absl::StatusOr subprotocol = @@ -496,8 +490,8 @@ WebTransportHttp3::MaybeSetSubprotocolFromResponseHeaders( if (!subprotocol.ok()) { QUIC_DVLOG(1) << ENDPOINT << "WebTransport server has malformed WT-Protocol " - "header, rejecting."; - return WebTransportHttp3RejectionReason::kSubprotocolParseError; + "header, ignoring."; + return; } if (session_->perspective() == Perspective::IS_CLIENT && @@ -505,12 +499,11 @@ WebTransportHttp3::MaybeSetSubprotocolFromResponseHeaders( QUIC_DVLOG(1) << ENDPOINT << "WebTransport server has offered a subprotocol value \"" << *subprotocol - << "\", which was not one of the ones offered, rejecting."; - return WebTransportHttp3RejectionReason::kSubprotocolMismatch; + << "\", which was not one of the ones offered, ignoring."; + return; } subprotocol_selected_ = *std::move(subprotocol); - return WebTransportHttp3RejectionReason::kNone; } } // namespace quic 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 789dc521f7..a360986dd2 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 @@ -38,8 +38,6 @@ enum class WebTransportHttp3RejectionReason { kWrongStatusCode, kMissingDraftVersion, kUnsupportedDraftVersion, - kSubprotocolMismatch, - kSubprotocolParseError, }; // A session of WebTransport over HTTP/3. The session is owned by @@ -132,7 +130,7 @@ class QUICHE_EXPORT WebTransportHttp3 std::optional GetNegotiatedSubprotocol() const override { return subprotocol_selected_; } - WebTransportHttp3RejectionReason MaybeSetSubprotocolFromResponseHeaders( + void MaybeSetSubprotocolFromResponseHeaders( const quiche::HttpHeaderBlock& headers); private: diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/web_transport_stream_adapter.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/web_transport_stream_adapter.cc index 4c26f37648..fe68dfa602 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/web_transport_stream_adapter.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/web_transport_stream_adapter.cc @@ -8,10 +8,8 @@ #include #include #include -#include #include "absl/status/status.h" -#include "absl/status/statusor.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "quiche/quic/core/http/web_transport_http3.h" @@ -21,15 +19,13 @@ #include "quiche/quic/core/quic_stream_priority.h" #include "quiche/quic/core/quic_stream_sequencer.h" #include "quiche/quic/core/quic_types.h" +#include "quiche/quic/core/quic_utils.h" #include "quiche/quic/core/web_transport_interface.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" -#include "quiche/quic/platform/api/quic_flags.h" #include "quiche/quic/platform/api/quic_logging.h" #include "quiche/common/platform/api/quiche_logging.h" -#include "quiche/common/quiche_buffer_allocator.h" #include "quiche/common/quiche_mem_slice.h" #include "quiche/common/quiche_stream.h" -#include "quiche/common/vectorized_io_utils.h" #include "quiche/web_transport/web_transport.h" namespace quic { @@ -69,7 +65,7 @@ WebTransportStream::ReadResult WebTransportStreamAdapter::Read( } absl::Status WebTransportStreamAdapter::Writev( - absl::Span data, + absl::Span data, const quiche::StreamWriteOptions& options) { if (data.empty() && !options.send_fin()) { return absl::InvalidArgumentError( @@ -82,21 +78,10 @@ absl::Status WebTransportStreamAdapter::Writev( return initial_check_status; } - size_t total_size = quiche::TotalStringViewSpanSize(data); - quiche::QuicheMemSlice slice; - if (total_size > 0) { - quiche::QuicheBuffer buffer( - session_->connection()->helper()->GetStreamSendBufferAllocator(), - total_size); - size_t bytes_copied = quiche::GatherStringViewSpan(data, buffer.AsSpan()); - QUICHE_DCHECK_EQ(total_size, bytes_copied); - slice = quiche::QuicheMemSlice(std::move(buffer)); - } + size_t total_size = MemSliceSpanTotalSize(data); QuicConsumedData consumed = stream_->WriteMemSlices( - slice.empty() ? absl::Span() - : absl::MakeSpan(&slice, 1), - /*fin=*/options.send_fin(), - /*buffer_uncondtionally=*/options.buffer_unconditionally()); + data, /*fin=*/options.send_fin(), + /*buffer_unconditionally=*/options.buffer_unconditionally()); if (consumed.bytes_consumed == total_size) { return absl::OkStatus(); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/web_transport_stream_adapter.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/web_transport_stream_adapter.h index 94f3ba4b0b..7107dd9e01 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/web_transport_stream_adapter.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/web_transport_stream_adapter.h @@ -23,6 +23,7 @@ #include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/web_transport_interface.h" #include "quiche/common/platform/api/quiche_export.h" +#include "quiche/common/quiche_mem_slice.h" #include "quiche/common/quiche_stream.h" #include "quiche/web_transport/web_transport.h" @@ -39,7 +40,7 @@ class QUICHE_EXPORT WebTransportStreamAdapter : public webtransport::Stream { // WebTransportStream implementation. ABSL_MUST_USE_RESULT ReadResult Read(absl::Span output) override; ABSL_MUST_USE_RESULT ReadResult Read(std::string* output) override; - absl::Status Writev(absl::Span data, + absl::Status Writev(absl::Span data, const quiche::StreamWriteOptions& options) override; bool CanWrite() const override; void AbruptlyTerminate(absl::Status error) override; 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 6d78007283..f70acb0dd6 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 @@ -137,7 +137,7 @@ EnqueuePacketResult QuicBufferedPacketStore::EnqueuePacket( 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 ietf_quic = packet_info.form != GOOGLE_QUIC_Q043_PACKET; const bool is_chlo = parsed_chlo.has_value(); const bool is_ietf_initial_packet = (version.IsKnown() && packet_info.form == IETF_QUIC_LONG_HEADER_PACKET && 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 fa8330af6c..7b40eda90d 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 @@ -109,9 +109,6 @@ class QuicEncrypter; namespace { -// Maximum number of consecutive sent nonretransmittable packets. -const QuicPacketCount kMaxConsecutiveNonRetransmittablePackets = 19; - // The minimum release time into future in ms. const int kMinReleaseTimeIntoFutureMs = 1; @@ -200,62 +197,23 @@ QuicConnection::QuicConnection( ConnectionIdGeneratorInterface& generator) : framer_(supported_versions, helper->GetClock()->ApproximateNow(), perspective, server_connection_id.length()), - current_packet_content_(NO_FRAMES_RECEIVED), - is_current_packet_connectivity_probing_(false), - has_path_challenge_in_current_packet_(false), - current_effective_peer_migration_type_(NO_CHANGE), helper_(helper), alarm_factory_(alarm_factory), - per_packet_options_(nullptr), writer_(writer), - owns_writer_(owns_writer), - encryption_level_(ENCRYPTION_INITIAL), clock_(helper->GetClock()), random_generator_(helper->GetRandomGenerator()), - client_connection_id_is_set_(false), direct_peer_address_(initial_peer_address), default_path_(initial_self_address, QuicSocketAddress(), /*client_connection_id=*/EmptyQuicConnectionId(), server_connection_id, /*stateless_reset_token=*/std::nullopt), - active_effective_peer_migration_type_(NO_CHANGE), - support_key_update_for_connection_(false), - current_packet_data_(nullptr), - should_last_packet_instigate_acks_(false), - max_undecryptable_packets_(0), max_tracked_packets_(GetQuicFlag(quic_max_tracked_packet_count)), - idle_timeout_connection_close_behavior_( - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET), - num_rtos_for_blackhole_detection_(0), uber_received_packet_manager_(&stats_), - pending_retransmission_alarm_(false), - defer_send_in_response_to_packets_(false), - arena_(), alarms_(this, arena_, *alarm_factory_), - visitor_(nullptr), - debug_visitor_(nullptr), packet_creator_(server_connection_id, &framer_, random_generator_, this), last_received_packet_info_(clock_->ApproximateNow()), sent_packet_manager_(perspective, clock_, random_generator_, &stats_, GetDefaultCongestionControlType()), - version_negotiated_(false), - perspective_(perspective), - connected_(true), - can_truncate_connection_ids_(perspective == Perspective::IS_SERVER), - mtu_probe_count_(0), - previous_validated_mtu_(0), - peer_max_packet_size_(kDefaultMaxPacketSizeTransportParam), - largest_received_packet_size_(0), - write_error_occurred_(false), - consecutive_num_packets_with_no_retransmittable_frames_(0), - max_consecutive_num_packets_with_no_retransmittable_frames_( - kMaxConsecutiveNonRetransmittablePackets), - bundle_retransmittable_with_pto_ack_(false), - last_control_frame_id_(kInvalidControlFrameId), - is_path_degrading_(false), - flow_label_has_changed_(false), - processing_ack_frame_(false), - supports_release_time_(false), release_time_into_future_(QuicTime::Delta::Zero()), blackhole_detector_( this, @@ -270,6 +228,10 @@ QuicConnection::QuicConnection( multi_port_probing_interval_(kDefaultMultiPortProbingInterval), connection_id_generator_(generator), received_client_addresses_cache_(kMaxReceivedClientAddressSize), + current_packet_content_(NO_FRAMES_RECEIVED), + perspective_(perspective), + owns_writer_(owns_writer), + can_truncate_connection_ids_(perspective == Perspective::IS_SERVER), least_unacked_plus_1_(GetQuicReloadableFlag(quic_least_unacked_plus_1)) { QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT || default_path_.self_address.IsInitialized()); @@ -549,6 +511,20 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) { retransmittable_on_wire_behavior_ = SEND_RANDOM_BYTES; } } + + // Set retransmittable-on-wire timeout to different PTO based values. + if (perspective_ == Perspective::IS_CLIENT && version().HasIetfQuicFrames()) { + if (config.HasClientRequestedIndependentOption(kROW1, perspective_)) { + ping_manager_.set_num_ptos_for_retransmittable_on_wire_timeout(1); + } + if (config.HasClientRequestedIndependentOption(kROW2, perspective_)) { + ping_manager_.set_num_ptos_for_retransmittable_on_wire_timeout(2); + } + if (config.HasClientRequestedIndependentOption(kROW3, perspective_)) { + ping_manager_.set_num_ptos_for_retransmittable_on_wire_timeout(3); + } + } + if (config.HasClientRequestedIndependentOption(k3AFF, perspective_)) { anti_amplification_factor_ = 3; } @@ -3134,7 +3110,8 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) { if (!version_negotiated_) { if (perspective_ == Perspective::IS_CLIENT) { - QUICHE_DCHECK(!header.version_flag || header.form != GOOGLE_QUIC_PACKET); + QUICHE_DCHECK(!header.version_flag || + header.form != GOOGLE_QUIC_Q043_PACKET); version_negotiated_ = true; OnSuccessfulVersionNegotiation(); } @@ -3282,7 +3259,6 @@ void QuicConnection::MaybeBundleOpportunistically( 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); @@ -4122,7 +4098,6 @@ void QuicConnection::OnHandshakeComplete() { } if (send_ack_frequency_on_handshake_completion_ && sent_packet_manager_.CanSendAckFrequency()) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_can_send_ack_frequency, 2, 3); auto ack_frequency_frame = sent_packet_manager_.GetUpdatedAckFrequencyFrame(); // This AckFrequencyFrame is meant to only update the max_ack_delay. All @@ -4891,7 +4866,8 @@ void QuicConnection::SetPingAlarm() { } ping_manager_.SetAlarm(clock_->ApproximateNow(), visitor_->ShouldKeepConnectionAlive(), - sent_packet_manager_.HasInFlightPackets()); + sent_packet_manager_.HasInFlightPackets(), + sent_packet_manager_.GetPtoDelay()); } void QuicConnection::SetRetransmissionAlarm() { @@ -6579,9 +6555,9 @@ void QuicConnection::OnRetransmittableOnWireTimeout() { if (connected_) { // Always reset PING alarm with has_in_flight_packets=true. This is used // to avoid re-arming the alarm in retransmittable-on-wire mode. - ping_manager_.SetAlarm(clock_->ApproximateNow(), - visitor_->ShouldKeepConnectionAlive(), - /*has_in_flight_packets=*/true); + ping_manager_.SetAlarm( + clock_->ApproximateNow(), visitor_->ShouldKeepConnectionAlive(), + /*has_in_flight_packets=*/true, sent_packet_manager_.GetPtoDelay()); } 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 8c7055d4ad..c9ebfe3c1a 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 @@ -1617,7 +1617,7 @@ class QUICHE_EXPORT QuicConnection private: friend class test::QuicConnectionPeer; - enum RetransmittableOnWireBehavior { + enum RetransmittableOnWireBehavior : uint8_t { DEFAULT, // Send packet containing a PING frame. SEND_FIRST_FORWARD_SECURE_PACKET, // Send 1st 1-RTT packet. SEND_RANDOM_BYTES // Send random bytes which is an unprocessable packet. @@ -2224,44 +2224,15 @@ class QUICHE_EXPORT QuicConnection QuicFramer framer_; - // TODO(danzh) remove below fields once quic_ignore_gquic_probing_ gets - // deprecated. Contents received in the current packet, especially used to - // identify whether the current packet is a padded PING packet. - PacketContent current_packet_content_; - // Set to true as soon as the packet currently being processed has been - // detected as a connectivity probing. - // Always false outside the context of ProcessUdpPacket(). - bool is_current_packet_connectivity_probing_; - - bool has_path_challenge_in_current_packet_; - - // Caches the current effective peer migration type if a effective peer - // migration might be initiated. As soon as the current packet is confirmed - // not a connectivity probe, effective peer migration will start. - AddressChangeType current_effective_peer_migration_type_; QuicConnectionHelperInterface* helper_; // Not owned. QuicAlarmFactory* alarm_factory_; // Not owned. - PerPacketOptions* per_packet_options_; // Not owned. + PerPacketOptions* per_packet_options_ = nullptr; // Not owned. QuicPacketWriterParams packet_writer_params_; QuicPacketWriter* writer_; // Owned or not depending on |owns_writer_|. - bool owns_writer_; - // Encryption level for new packets. Should only be changed via - // SetDefaultEncryptionLevel(). - EncryptionLevel encryption_level_; const QuicClock* clock_; QuicRandom* random_generator_; - - // On the server, the connection ID is set when receiving the first packet. - // This variable ensures we only set it this way once. - bool client_connection_id_is_set_; - - // Whether we've already replaced our server connection ID due to receiving an - // INITIAL packet with a different source connection ID. Only used on client. - bool server_connection_id_replaced_by_initial_ = false; - // Address on the last successfully processed packet received from the - // direct peer. - - // Other than initialization, do not modify it directly, use + // Address on the last successfully processed packet received from the direct + // peer. Other than initialization, do not modify it directly, use // UpdatePeerAddress() instead. QuicSocketAddress direct_peer_address_; // The default path on which the endpoint sends non-probing packets. @@ -2269,26 +2240,18 @@ class QUICHE_EXPORT QuicConnection // |sent_packet_manager_| instead of in this object. PathState default_path_; - // Records change type when the effective peer initiates migration to a new - // address. Reset to NO_CHANGE after effective peer migration is validated. - AddressChangeType active_effective_peer_migration_type_; - // Records highest sent packet number when effective peer migration is // started. QuicPacketNumber highest_packet_sent_before_effective_peer_migration_; - // True if Key Update is supported on this connection. - bool support_key_update_for_connection_; - // Tracks the lowest packet sent in the current key phase. Will be // uninitialized before the first one-RTT packet has been sent or after a // key update but before the first packet has been sent. QuicPacketNumber lowest_packet_sent_in_current_key_phase_; + // UDP payload of packet currently being parsed or nullptr. // TODO(rch): remove this when b/27221014 is fixed. - const char* current_packet_data_; // UDP payload of packet currently being - // parsed or nullptr. - bool should_last_packet_instigate_acks_; + const char* current_packet_data_ = nullptr; // Track some peer state so we can do less bookkeeping // Largest sequence sent by the peer which had an ack frame (latest ack info). @@ -2315,7 +2278,7 @@ class QUICHE_EXPORT QuicConnection received_coalesced_packets_; // Maximum number of undecryptable packets the connection will store. - size_t max_undecryptable_packets_; + size_t max_undecryptable_packets_ = 0; // Maximum number of tracked packets. QuicPacketCount max_tracked_packets_; @@ -2323,26 +2286,14 @@ class QUICHE_EXPORT QuicConnection // Contains the connection close packets if the connection has been closed. std::unique_ptr termination_info_; - // Determines whether or not a connection close packet is sent to the peer - // after idle timeout due to lack of network activity. During the handshake, - // a connection close packet is sent, but not after. - ConnectionCloseBehavior idle_timeout_connection_close_behavior_; - // When > 0, close the QUIC connection after this number of RTOs. - size_t num_rtos_for_blackhole_detection_; + size_t num_rtos_for_blackhole_detection_ = 0; // Statistics for this session. QuicConnectionStats stats_; UberReceivedPacketManager uber_received_packet_manager_; - // Indicates the retransmission alarm needs to be set. - bool pending_retransmission_alarm_; - - // If true, defer sending data in response to received packets to the - // SendAlarm. - bool defer_send_in_response_to_packets_; - // Arena to store class implementations within the QuicConnection. QuicConnectionArena arena_; @@ -2350,8 +2301,8 @@ class QUICHE_EXPORT QuicConnection QuicAlarmMultiplexer alarms_; // Neither visitor is owned by this class. - QuicConnectionVisitorInterface* visitor_; - QuicConnectionDebugVisitor* debug_visitor_; + QuicConnectionVisitorInterface* visitor_ = nullptr; + QuicConnectionDebugVisitor* debug_visitor_ = nullptr; QuicPacketCreator packet_creator_; @@ -2364,38 +2315,13 @@ class QUICHE_EXPORT QuicConnection // to send packets. QuicSentPacketManager sent_packet_manager_; - // Indicates whether connection version has been negotiated. - // Always true for server connections. - bool version_negotiated_; - - // Tracks if the connection was created by the server or the client. - Perspective perspective_; - - // True by default. False if we've received or sent an explicit connection - // close. - bool connected_; - - // True if the connection is in the CloseConnection stack. - bool in_close_connection_ = false; - - // Set to false if the connection should not send truncated connection IDs to - // the peer, even if the peer supports it. - bool can_truncate_connection_ids_; - // If non-empty this contains the set of versions received in a // version negotiation packet. ParsedQuicVersionVector server_supported_versions_; // The number of MTU probes already sent. - size_t mtu_probe_count_; + size_t mtu_probe_count_ = 0; - // The value of |long_term_mtu_| prior to the last successful MTU increase. - // 0 means either - // - MTU discovery has never been enabled, or - // - MTU discovery has been enabled, but the connection got a packet write - // error with a new (successfully probed) MTU, so it reverted - // |long_term_mtu_| to the value before the last increase. - QuicPacketLength previous_validated_mtu_; // The value of the MTU regularly used by the connection. This is different // from the value returned by max_packet_size(), as max_packet_size() returns // the value of the MTU as currently used by the serializer, so if @@ -2405,41 +2331,18 @@ class QUICHE_EXPORT QuicConnection // The maximum UDP payload size that our peer has advertised support for. // Defaults to kDefaultMaxPacketSizeTransportParam until received from peer. - QuicByteCount peer_max_packet_size_; + QuicByteCount peer_max_packet_size_ = kDefaultMaxPacketSizeTransportParam; // The size of the largest packet received from peer. - QuicByteCount largest_received_packet_size_; - - // Indicates whether a write error is encountered currently. This is used to - // avoid infinite write errors. - bool write_error_occurred_; - + QuicByteCount largest_received_packet_size_ = 0; // Consecutive number of sent packets which have no retransmittable frames. - size_t consecutive_num_packets_with_no_retransmittable_frames_; + size_t consecutive_num_packets_with_no_retransmittable_frames_ = 0; // After this many packets sent without retransmittable frames, an artificial // retransmittable frame(a WINDOW_UPDATE) will be created to solicit an ack - // from the peer. Default to kMaxConsecutiveNonRetransmittablePackets. - size_t max_consecutive_num_packets_with_no_retransmittable_frames_; - - // If true, bundle an ack-eliciting frame with an ACK if the PTO alarm have - // previously fired. - bool bundle_retransmittable_with_pto_ack_; - - // Id of latest sent control frame. 0 if no control frame has been sent. - QuicControlFrameId last_control_frame_id_; - - // True if the peer is unreachable on the current path. - bool is_path_degrading_; - - // True if the outgoing flow label has changed since the last foward progress. - bool flow_label_has_changed_; - - // True if an ack frame is being processed. - bool processing_ack_frame_; - - // True if the writer supports release timestamp. - bool supports_release_time_; + // from the peer. + size_t max_consecutive_num_packets_with_no_retransmittable_frames_ = + kMaxConsecutiveNonRetransmittablePackets; std::unique_ptr peer_issued_cid_manager_; std::unique_ptr self_issued_cid_manager_; @@ -2486,45 +2389,6 @@ class QUICHE_EXPORT QuicConnection QuicIdleNetworkDetector idle_network_detector_; - bool blackhole_detection_disabled_ = false; - - const bool default_enable_5rto_blackhole_detection_ = - GetQuicReloadableFlag(quic_default_enable_5rto_blackhole_detection2); - - // True if next packet is intended to consume remaining space in the - // coalescer. - bool fill_coalesced_packet_ = false; - - size_t anti_amplification_factor_ = - GetQuicFlag(quic_anti_amplification_factor); - - // True if AckFrequencyFrame is supported. - bool can_receive_ack_frequency_immediate_ack_ = false; - - // Indicate whether coalescing is done. - bool coalescing_done_ = false; - - // Indicate whether any ENCRYPTION_HANDSHAKE packet has been sent. - bool handshake_packet_sent_ = false; - - // Indicate whether to send an AckFrequencyFrame upon handshake completion. - // The AckFrequencyFrame sent will updates client's max_ack_delay, which if - // chosen properly can reduce the CPU and bandwidth usage for ACK frames. - bool send_ack_frequency_on_handshake_completion_ = false; - - // Indicate whether AckFrequency frame has been sent. - bool ack_frequency_sent_ = false; - - // True if a 0-RTT decrypter was or is installed at some point in the - // connection's lifetime. - bool had_zero_rtt_decrypter_ = false; - - // True after the first 1-RTT packet has successfully decrypted. - bool have_decrypted_first_one_rtt_packet_ = false; - - // True if we are currently processing OnRetransmissionTimeout. - bool in_probe_time_out_ = false; - QuicPathValidator path_validator_; // Stores information of a path which maybe used as default path in the @@ -2539,18 +2403,8 @@ class QUICHE_EXPORT QuicConnection // 2), do not override it on receiving PATH_CHALLENGE (case 1). PathState alternative_path_; - // If true, upon seeing a new client address, validate the client address. - bool validate_client_addresses_ = false; - - // Indicates whether we should proactively validate peer address on a - // PATH_CHALLENGE received. - bool should_proactively_validate_peer_address_on_path_challenge_ = false; - - // If true, send connection close packet on INVALID_VERSION. - bool send_connection_close_for_invalid_version_ = false; - - // If true, disable liveness testing. - bool liveness_testing_disabled_ = false; + size_t anti_amplification_factor_ = + GetQuicFlag(quic_anti_amplification_factor); QuicPingManager ping_manager_; @@ -2566,23 +2420,6 @@ class QUICHE_EXPORT QuicConnection std::unique_ptr multi_port_stats_; - // If true, connection will migrate to multi-port path upon path degrading. - bool multi_port_migration_enabled_ = false; - - // If true, connection will probe for multi-port path on RTO. This is only - // used on the client side. If false, connection will probe for multi-port - // path on receiving a new connection ID frame. See OnNewConnectionIdFrame() - // for more details. - bool multi_port_probing_on_rto_ = false; - - // Client side only. - bool active_migration_disabled_ = false; - - const bool ignore_gquic_probing_ = - GetQuicReloadableFlag(quic_ignore_gquic_probing); - - RetransmittableOnWireBehavior retransmittable_on_wire_behavior_ = DEFAULT; - // Server addresses that are known to the client. std::vector known_server_addresses_; @@ -2596,16 +2433,6 @@ class QUICHE_EXPORT QuicConnection // a DNAT. QuicSocketAddress expected_server_preferred_address_; - // If true, kicks off validation of server_preferred_address_ once it is - // received. Also, send all coalesced packets on both paths until handshake is - // confirmed. - bool accelerated_server_preferred_address_ = false; - - // If true, throttle sending if next created packet will exceed amplification - // limit. - const bool enforce_strict_amplification_factor_ = - GetQuicFlag(quic_enforce_strict_amplification_factor); - ConnectionIdGeneratorInterface& connection_id_generator_; // This LRU cache records source addresses of packets received on server's @@ -2613,17 +2440,6 @@ class QUICHE_EXPORT QuicConnection QuicLRUCache received_client_addresses_cache_; - // Endpoints should never mark packets with Congestion Experienced (CE), as - // this is only done by routers. Endpoints cannot send ECT(0) or ECT(1) if - // their congestion control cannot respond to these signals in accordance with - // the spec, or ECN feedback doesn't conform to the spec. When true, the - // connection will not verify that the requested codepoint adheres to these - // policies. This is only accessible through QuicConnectionPeer. - bool disable_ecn_codepoint_validation_ = false; - - // The ECN codepoint of the last packet to be sent to the writer, which - // might be different from the next codepoint in per_packet_options_. - QuicEcnCodepoint last_ecn_codepoint_sent_ = ECN_NOT_ECT; // The flow label of the last packet to be sent to the writer, which // might be different from the next flow label in per_packet_options_. uint32_t last_flow_label_sent_ = 0; @@ -2632,21 +2448,171 @@ class QUICHE_EXPORT QuicConnection // The flow label of the packet with the largest packet number received // from the peer. uint32_t last_flow_label_received_ = 0; + + // Id of latest sent control frame. 0 if no control frame has been sent. + QuicControlFrameId last_control_frame_id_ = kInvalidControlFrameId; + + RetransmittableOnWireBehavior retransmittable_on_wire_behavior_ = DEFAULT; + + // TODO(danzh) remove `current_packet_content_` and + // `is_current_packet_connectivity_probing_` fields once + // quic_ignore_gquic_probing_ gets deprecated. Contents received in the + // current packet, especially used to identify whether the current packet is a + // padded PING packet. + PacketContent current_packet_content_; + + // Caches the current effective peer migration type if a effective peer + // migration might be initiated. As soon as the current packet is confirmed + // not a connectivity probe, effective peer migration will start. + AddressChangeType current_effective_peer_migration_type_ = NO_CHANGE; + + // Records change type when the effective peer initiates migration to a new + // address. Reset to NO_CHANGE after effective peer migration is validated. + AddressChangeType active_effective_peer_migration_type_ = NO_CHANGE; + + // The value of |long_term_mtu_| prior to the last successful MTU increase. + // 0 means either + // - MTU discovery has never been enabled, or + // - MTU discovery has been enabled, but the connection got a packet write + // error with a new (successfully probed) MTU, so it reverted + // |long_term_mtu_| to the value before the last increase. + QuicPacketLength previous_validated_mtu_ = 0; + + // Determines whether or not a connection close packet is sent to the peer + // after idle timeout due to lack of network activity. During the handshake, + // a connection close packet is sent, but not after. + ConnectionCloseBehavior idle_timeout_connection_close_behavior_ = + ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET; + + // Encryption level for new packets. Should only be changed via + // SetDefaultEncryptionLevel(). + EncryptionLevel encryption_level_ = ENCRYPTION_INITIAL; + + // Tracks if the connection was created by the server or the client. + Perspective perspective_; + + // The ECN codepoint of the last packet to be sent to the writer, which + // might be different from the next codepoint in per_packet_options_. + QuicEcnCodepoint last_ecn_codepoint_sent_ = ECN_NOT_ECT; + + // Set to true as soon as the packet currently being processed has been + // detected as a connectivity probing. + // Always false outside the context of ProcessUdpPacket(). + bool is_current_packet_connectivity_probing_ : 1 = false; + bool has_path_challenge_in_current_packet_ : 1 = false; + bool owns_writer_ : 1; + // On the server, the connection ID is set when receiving the first packet. + // This variable ensures we only set it this way once. + bool client_connection_id_is_set_ : 1 = false; + // Whether we've already replaced our server connection ID due to receiving an + // INITIAL packet with a different source connection ID. Only used on client. + bool server_connection_id_replaced_by_initial_ : 1 = false; + // Indicates whether connection version has been negotiated. + // Always true for server connections. + bool version_negotiated_ : 1 = false; + // True if Key Update is supported on this connection. + bool support_key_update_for_connection_ : 1 = false; + bool should_last_packet_instigate_acks_ : 1 = false; + // Indicates the retransmission alarm needs to be set. + bool pending_retransmission_alarm_ : 1 = false; + // If true, defer sending data in response to received packets to the + // SendAlarm. + bool defer_send_in_response_to_packets_ : 1 = false; + // True by default. False if we've received or sent an explicit connection + // close. + bool connected_ : 1 = true; + // True if the connection is in the CloseConnection stack. + bool in_close_connection_ : 1 = false; + // Set to false if the connection should not send truncated connection IDs to + // the peer, even if the peer supports it. + bool can_truncate_connection_ids_ : 1; + // Indicates whether a write error is encountered currently. This is used to + // avoid infinite write errors. + bool write_error_occurred_ : 1 = false; + // If true, bundle an ack-eliciting frame with an ACK if the PTO alarm have + // previously fired. + bool bundle_retransmittable_with_pto_ack_ : 1 = false; + // True if the peer is unreachable on the current path. + bool is_path_degrading_ : 1 = false; + // True if the outgoing flow label has changed since the last foward progress. + bool flow_label_has_changed_ : 1 = false; + // True if an ack frame is being processed. + bool processing_ack_frame_ : 1 = false; + // True if the writer supports release timestamp. + bool supports_release_time_ : 1 = false; + bool blackhole_detection_disabled_ : 1 = false; + const bool default_enable_5rto_blackhole_detection_ : 1 = + GetQuicReloadableFlag(quic_default_enable_5rto_blackhole_detection2); + // True if next packet is intended to consume remaining space in the + // coalescer. + bool fill_coalesced_packet_ : 1 = false; + // True if AckFrequencyFrame is supported. + bool can_receive_ack_frequency_immediate_ack_ : 1 = false; + // Indicate whether coalescing is done. + bool coalescing_done_ : 1 = false; + // Indicate whether any ENCRYPTION_HANDSHAKE packet has been sent. + bool handshake_packet_sent_ : 1 = false; + // Indicate whether to send an AckFrequencyFrame upon handshake completion. + // The AckFrequencyFrame sent will updates client's max_ack_delay, which if + // chosen properly can reduce the CPU and bandwidth usage for ACK frames. + bool send_ack_frequency_on_handshake_completion_ : 1 = false; + // Indicate whether AckFrequency frame has been sent. + bool ack_frequency_sent_ : 1 = false; + // True if a 0-RTT decrypter was or is installed at some point in the + // connection's lifetime. + bool had_zero_rtt_decrypter_ : 1 = false; + // True after the first 1-RTT packet has successfully decrypted. + bool have_decrypted_first_one_rtt_packet_ : 1 = false; + // True if we are currently processing OnRetransmissionTimeout. + bool in_probe_time_out_ : 1 = false; + // If true, upon seeing a new client address, validate the client address. + bool validate_client_addresses_ : 1 = false; + // Indicates whether we should proactively validate peer address on a + // PATH_CHALLENGE received. + bool should_proactively_validate_peer_address_on_path_challenge_ : 1 = false; + // If true, send connection close packet on INVALID_VERSION. + bool send_connection_close_for_invalid_version_ : 1 = false; + // If true, disable liveness testing. + bool liveness_testing_disabled_ : 1 = false; + // If true, connection will migrate to multi-port path upon path degrading. + bool multi_port_migration_enabled_ : 1 = false; + // If true, connection will probe for multi-port path on RTO. This is only + // used on the client side. If false, connection will probe for multi-port + // path on receiving a new connection ID frame. See OnNewConnectionIdFrame() + // for more details. + bool multi_port_probing_on_rto_ : 1 = false; + // Client side only. + bool active_migration_disabled_ : 1 = false; + const bool ignore_gquic_probing_ : 1 = + GetQuicReloadableFlag(quic_ignore_gquic_probing); + // If true, kicks off validation of server_preferred_address_ once it is + // received. Also, send all coalesced packets on both paths until handshake is + // confirmed. + bool accelerated_server_preferred_address_ : 1 = false; + // If true, throttle sending if next created packet will exceed amplification + // limit. + const bool enforce_strict_amplification_factor_ : 1 = + GetQuicFlag(quic_enforce_strict_amplification_factor); + // Endpoints should never mark packets with Congestion Experienced (CE), as + // this is only done by routers. Endpoints cannot send ECT(0) or ECT(1) if + // their congestion control cannot respond to these signals in accordance with + // the spec, or ECN feedback doesn't conform to the spec. When true, the + // connection will not verify that the requested codepoint adheres to these + // policies. This is only accessible through QuicConnectionPeer. + bool disable_ecn_codepoint_validation_ : 1 = false; // True if the peer is expected to change their flow label in response to // a flow label change made by this connection. - bool expect_peer_flow_label_change_ = false; + bool expect_peer_flow_label_change_ : 1 = false; // If true then flow labels will be changed when a PTO fires, or when // a PTO'd packet from a peer is detected. - bool enable_black_hole_avoidance_via_flow_label_ = false; + bool enable_black_hole_avoidance_via_flow_label_ : 1 = false; // If true, fixes a off-by-one error in the least unacked packet calculation. - bool least_unacked_plus_1_; - const bool quic_limit_new_streams_per_loop_2_ = + bool least_unacked_plus_1_ : 1; + const bool quic_limit_new_streams_per_loop_2_ : 1 = GetQuicReloadableFlag(quic_limit_new_streams_per_loop_2); - - const bool quic_test_peer_addr_change_after_normalize_ = + const bool quic_test_peer_addr_change_after_normalize_ : 1 = GetQuicReloadableFlag(quic_test_peer_addr_change_after_normalize); - - const bool quic_fix_timeouts_ = GetQuicReloadableFlag(quic_fix_timeouts); + const bool quic_fix_timeouts_ : 1 = GetQuicReloadableFlag(quic_fix_timeouts); }; } // namespace quic diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection_stats.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection_stats.cc index 8e511bfc45..d616818bec 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection_stats.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection_stats.cc @@ -33,7 +33,6 @@ std::ostream& operator<<(std::ostream& os, const QuicConnectionStats& s) { os << " crypto_retransmit_count: " << s.crypto_retransmit_count; os << " loss_timeout_count: " << s.loss_timeout_count; os << " tlp_count: " << s.tlp_count; - os << " rto_count: " << s.rto_count; os << " pto_count: " << s.pto_count; os << " min_rtt_us: " << s.min_rtt_us; os << " srtt_us: " << s.srtt_us; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection_stats.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection_stats.h index dfe9babdb3..0c21aca637 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection_stats.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection_stats.h @@ -5,14 +5,17 @@ #ifndef QUICHE_QUIC_CORE_QUIC_CONNECTION_STATS_H_ #define QUICHE_QUIC_CORE_QUIC_CONNECTION_STATS_H_ +#include #include +#include #include #include "quiche/quic/core/quic_bandwidth.h" -#include "quiche/quic/core/quic_packets.h" +#include "quiche/quic/core/quic_packet_number.h" #include "quiche/quic/core/quic_time.h" #include "quiche/quic/core/quic_time_accumulator.h" -#include "quiche/quic/platform/api/quic_export.h" +#include "quiche/quic/core/quic_types.h" +#include "quiche/common/platform/api/quiche_export.h" namespace quic { @@ -99,7 +102,6 @@ struct QUICHE_EXPORT QuicConnectionStats { // be lost when the alarm fires. size_t loss_timeout_count = 0; size_t tlp_count = 0; - size_t rto_count = 0; // Count of times the rto timer fired. size_t pto_count = 0; int64_t min_rtt_us = 0; // Minimum RTT in microseconds. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_constants.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_constants.h index cc5d0ccbc9..a412738e04 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_constants.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_constants.h @@ -8,10 +8,11 @@ #include #include -#include +#include "quiche/quic/core/quic_packet_number.h" +#include "quiche/quic/core/quic_time.h" #include "quiche/quic/core/quic_types.h" -#include "quiche/quic/platform/api/quic_export.h" +#include "quiche/common/platform/api/quiche_export.h" // Definitions of constant values used throughout the QUIC code. @@ -300,6 +301,8 @@ inline constexpr QuicPacketCount kMaxRetransmittablePacketsBeforeAck = 10; inline constexpr QuicPacketCount kMinReceivedBeforeAckDecimation = 100; // Ask peer to use one quarter RTT delay when doing ack decimation. inline constexpr float kPeerAckDecimationDelay = 0.25; +// Maximum number of consecutive sent nonretransmittable packets. +inline constexpr QuicPacketCount kMaxConsecutiveNonRetransmittablePackets = 19; // The default alarm granularity assumed by QUIC code. inline constexpr QuicTime::Delta kAlarmGranularity = 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 e27a5222ea..3ba39c07e6 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 @@ -279,28 +279,17 @@ void QuicDispatcher::ProcessPacket(const QuicSocketAddress& self_address, ++stats_.packets_processed; ReceivedPacketInfo packet_info(self_address, peer_address, packet); std::string detailed_error; - QuicErrorCode error; - if (GetQuicReloadableFlag(quic_heapless_static_parser)) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_heapless_static_parser, 2, 3); - absl::string_view destination_connection_id, source_connection_id; - error = QuicFramer::ParsePublicHeaderDispatcherShortHeaderLengthUnknown( - packet, &packet_info.form, &packet_info.long_packet_type, - &packet_info.version_flag, &packet_info.use_length_prefix, - &packet_info.version_label, &packet_info.version, - &destination_connection_id, &source_connection_id, - &packet_info.retry_token, &detailed_error, connection_id_generator_); - packet_info.destination_connection_id = - QuicConnectionId(destination_connection_id); - packet_info.source_connection_id = QuicConnectionId(source_connection_id); - } else { - error = QuicFramer::ParsePublicHeaderDispatcherShortHeaderLengthUnknown( - packet, &packet_info.form, &packet_info.long_packet_type, - &packet_info.version_flag, &packet_info.use_length_prefix, - &packet_info.version_label, &packet_info.version, - &packet_info.destination_connection_id, - &packet_info.source_connection_id, &packet_info.retry_token, - &detailed_error, connection_id_generator_); - } + absl::string_view destination_connection_id, source_connection_id; + QuicErrorCode error = + QuicFramer::ParsePublicHeaderDispatcherShortHeaderLengthUnknown( + packet, &packet_info.form, &packet_info.long_packet_type, + &packet_info.version_flag, &packet_info.use_length_prefix, + &packet_info.version_label, &packet_info.version, + &destination_connection_id, &source_connection_id, + &packet_info.retry_token, &detailed_error, connection_id_generator_); + packet_info.destination_connection_id = + QuicConnectionId(destination_connection_id); + packet_info.source_connection_id = QuicConnectionId(source_connection_id); if (error != QUIC_NO_ERROR) { // Packet has framing error. SetLastError(error); @@ -363,32 +352,17 @@ void QuicDispatcher::ProcessPacket(const QuicSocketAddress& self_address, IsSupportedVersion(ParsedQuicVersion::Q046())) { ReceivedPacketInfo gquic_packet_info(self_address, peer_address, packet); // Try again without asking |connection_id_generator_| for the length. - QuicErrorCode gquic_error; - if (GetQuicReloadableFlag(quic_heapless_static_parser)) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_heapless_static_parser, 3, 3); - absl::string_view destination_connection_id, source_connection_id; - gquic_error = QuicFramer::ParsePublicHeaderDispatcher( - packet, expected_server_connection_id_length_, - &gquic_packet_info.form, &gquic_packet_info.long_packet_type, - &gquic_packet_info.version_flag, &gquic_packet_info.use_length_prefix, - &gquic_packet_info.version_label, &gquic_packet_info.version, - &destination_connection_id, &source_connection_id, - &gquic_packet_info.retry_token, &detailed_error); - if (gquic_error == QUIC_NO_ERROR) { - gquic_packet_info.destination_connection_id = - QuicConnectionId(destination_connection_id); - gquic_packet_info.source_connection_id = - QuicConnectionId(source_connection_id); - } - } else { - gquic_error = QuicFramer::ParsePublicHeaderDispatcher( - packet, expected_server_connection_id_length_, - &gquic_packet_info.form, &gquic_packet_info.long_packet_type, - &gquic_packet_info.version_flag, &gquic_packet_info.use_length_prefix, - &gquic_packet_info.version_label, &gquic_packet_info.version, - &gquic_packet_info.destination_connection_id, - &gquic_packet_info.source_connection_id, - &gquic_packet_info.retry_token, &detailed_error); + QuicErrorCode gquic_error = QuicFramer::ParsePublicHeaderDispatcher( + packet, expected_server_connection_id_length_, &gquic_packet_info.form, + &gquic_packet_info.long_packet_type, &gquic_packet_info.version_flag, + &gquic_packet_info.use_length_prefix, &gquic_packet_info.version_label, + &gquic_packet_info.version, &destination_connection_id, + &source_connection_id, &gquic_packet_info.retry_token, &detailed_error); + if (gquic_error == QUIC_NO_ERROR) { + gquic_packet_info.destination_connection_id = + QuicConnectionId(destination_connection_id); + gquic_packet_info.source_connection_id = + QuicConnectionId(source_connection_id); } if (gquic_error == QUIC_NO_ERROR) { if (MaybeDispatchPacket(gquic_packet_info)) { @@ -1081,8 +1055,8 @@ void QuicDispatcher::StatelesslyTerminateConnection( << ", error_code:" << error_code << ", error_details:" << error_details; time_wait_list_manager_->AddConnectionIdToTimeWait( - action, TimeWaitConnectionInfo(format != GOOGLE_QUIC_PACKET, nullptr, - {server_connection_id})); + action, TimeWaitConnectionInfo(format != GOOGLE_QUIC_Q043_PACKET, + nullptr, {server_connection_id})); return; } @@ -1112,7 +1086,7 @@ void QuicDispatcher::StatelesslyTerminateConnection( } // This also adds the connection to time wait list. terminator.CloseConnection(error_code, error_details, - format != GOOGLE_QUIC_PACKET, + format != GOOGLE_QUIC_Q043_PACKET, /*active_connection_ids=*/ std::move(active_connection_ids)); @@ -1137,11 +1111,11 @@ void QuicDispatcher::StatelesslyTerminateConnection( std::vector> termination_packets; termination_packets.push_back(QuicFramer::BuildVersionNegotiationPacket( server_connection_id, EmptyQuicConnectionId(), - /*ietf_quic=*/format != GOOGLE_QUIC_PACKET, use_length_prefix, + /*ietf_quic=*/format != GOOGLE_QUIC_Q043_PACKET, use_length_prefix, /*versions=*/{})); time_wait_list_manager()->AddConnectionIdToTimeWait( QuicTimeWaitListManager::SEND_TERMINATION_PACKETS, - TimeWaitConnectionInfo(/*ietf_quic=*/format != GOOGLE_QUIC_PACKET, + TimeWaitConnectionInfo(/*ietf_quic=*/format != GOOGLE_QUIC_Q043_PACKET, &termination_packets, {server_connection_id})); } @@ -1163,7 +1137,7 @@ void QuicDispatcher::OnExpiredPackets( StatelesslyTerminateConnection( self_address, peer_address, early_arrived_packets.original_connection_id, early_arrived_packets.ietf_quic ? IETF_QUIC_LONG_HEADER_PACKET - : GOOGLE_QUIC_PACKET, + : GOOGLE_QUIC_Q043_PACKET, /*version_flag=*/true, early_arrived_packets.version.HasLengthPrefixedConnectionIds(), early_arrived_packets.version, error_code, @@ -1509,7 +1483,7 @@ void QuicDispatcher::MaybeResetPacketsWithNoVersion( QUIC_CODE_COUNT(quic_donot_send_reset_repeatedly); return; } - if (packet_info.form != GOOGLE_QUIC_PACKET) { + if (packet_info.form != GOOGLE_QUIC_Q043_PACKET) { // Drop IETF packets smaller than the minimal stateless reset length. if (packet_info.packet.length() <= QuicFramer::GetMinStatelessResetPacketLength()) { @@ -1545,7 +1519,7 @@ void QuicDispatcher::MaybeResetPacketsWithNoVersion( time_wait_list_manager()->SendPublicReset( packet_info.self_address, packet_info.peer_address, packet_info.destination_connection_id, - packet_info.form != GOOGLE_QUIC_PACKET, packet_info.packet.length(), + packet_info.form != GOOGLE_QUIC_Q043_PACKET, packet_info.packet.length(), GetPerPacketContext()); } @@ -1561,9 +1535,10 @@ bool QuicDispatcher::MaybeSendVersionNegotiationPacket( } time_wait_list_manager()->SendVersionNegotiationPacket( packet_info.destination_connection_id, packet_info.source_connection_id, - packet_info.form != GOOGLE_QUIC_PACKET, packet_info.use_length_prefix, - GetSupportedVersions(), packet_info.self_address, - packet_info.peer_address, GetPerPacketContext()); + packet_info.form != GOOGLE_QUIC_Q043_PACKET, + packet_info.use_length_prefix, GetSupportedVersions(), + packet_info.self_address, packet_info.peer_address, + GetPerPacketContext()); return true; } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_framer.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_framer.cc index e99d996ff7..977082a50a 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_framer.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_framer.cc @@ -228,7 +228,7 @@ QuicPacketNumberLength GetLongHeaderPacketNumberLength(uint8_t type) { // Used to get packet number space before packet gets decrypted. PacketNumberSpace GetPacketNumberSpace(const QuicPacketHeader& header) { switch (header.form) { - case GOOGLE_QUIC_PACKET: + case GOOGLE_QUIC_Q043_PACKET: QUIC_BUG(quic_bug_10850_5) << "Try to get packet number space of Google QUIC packet"; break; @@ -257,7 +257,7 @@ PacketNumberSpace GetPacketNumberSpace(const QuicPacketHeader& header) { EncryptionLevel GetEncryptionLevel(const QuicPacketHeader& header) { switch (header.form) { - case GOOGLE_QUIC_PACKET: + case GOOGLE_QUIC_Q043_PACKET: QUIC_BUG(quic_bug_10850_7) << "Cannot determine EncryptionLevel from Google QUIC header"; break; @@ -1728,7 +1728,7 @@ bool QuicFramer::ProcessIetfDataPacket(QuicDataReader* encrypted_reader, const QuicEncryptedPacket& packet, char* decrypted_buffer, size_t buffer_length) { - QUICHE_DCHECK_NE(GOOGLE_QUIC_PACKET, header->form); + QUICHE_DCHECK_NE(GOOGLE_QUIC_Q043_PACKET, header->form); QUICHE_DCHECK(!header->has_possible_stateless_reset_token); header->length_length = quiche::VARIABLE_LENGTH_INTEGER_LENGTH_0; header->remaining_packet_length = 0; @@ -2408,38 +2408,22 @@ bool QuicFramer::ProcessIetfPacketHeader(QuicDataReader* reader, QuicVersionLabel version_label; bool has_length_prefix; std::string detailed_error; - if (GetQuicReloadableFlag(quic_heapless_static_parser)) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_heapless_static_parser, 1, 3); - absl::string_view destination_connection_id; - absl::string_view source_connection_id; - QuicErrorCode parse_result = QuicFramer::ParsePublicHeader( - reader, expected_destination_connection_id_length, - /*ietf_format=*/true, &header->type_byte, &header->form, - &header->version_flag, &has_length_prefix, &version_label, - &header->version, &destination_connection_id, &source_connection_id, - &header->long_packet_type, &header->retry_token_length_length, - &header->retry_token, &detailed_error); - if (parse_result != QUIC_NO_ERROR) { - set_detailed_error(detailed_error); - return false; - } - header->destination_connection_id = - QuicConnectionId(destination_connection_id); - header->source_connection_id = QuicConnectionId(source_connection_id); - } else { - QuicErrorCode parse_result = QuicFramer::ParsePublicHeader( - reader, expected_destination_connection_id_length, - /*ietf_format=*/true, &header->type_byte, &header->form, - &header->version_flag, &has_length_prefix, &version_label, - &header->version, &header->destination_connection_id, - &header->source_connection_id, &header->long_packet_type, - &header->retry_token_length_length, &header->retry_token, - &detailed_error); - if (parse_result != QUIC_NO_ERROR) { - set_detailed_error(detailed_error); - return false; - } + absl::string_view destination_connection_id; + absl::string_view source_connection_id; + QuicErrorCode parse_result = QuicFramer::ParsePublicHeader( + reader, expected_destination_connection_id_length, + /*ietf_format=*/true, &header->type_byte, &header->form, + &header->version_flag, &has_length_prefix, &version_label, + &header->version, &destination_connection_id, &source_connection_id, + &header->long_packet_type, &header->retry_token_length_length, + &header->retry_token, &detailed_error); + if (parse_result != QUIC_NO_ERROR) { + set_detailed_error(detailed_error); + return false; } + header->destination_connection_id = + QuicConnectionId(destination_connection_id); + header->source_connection_id = QuicConnectionId(source_connection_id); header->destination_connection_id_included = CONNECTION_ID_PRESENT; header->source_connection_id_included = header->version_flag ? CONNECTION_ID_PRESENT : CONNECTION_ID_ABSENT; @@ -4551,9 +4535,9 @@ bool QuicFramer::DecryptPayload(size_t udp_packet_length, bool key_phase; bool attempt_key_update = false; if (version().KnowsWhichDecrypterToUse()) { - if (header.form == GOOGLE_QUIC_PACKET) { + if (header.form == GOOGLE_QUIC_Q043_PACKET) { QUIC_BUG(quic_bug_10850_68) - << "Attempted to decrypt GOOGLE_QUIC_PACKET with a version that " + << "Attempted to decrypt GOOGLE_QUIC_Q043_PACKET with a version that " "knows which decrypter to use"; return false; } @@ -6486,57 +6470,6 @@ QuicErrorCode QuicFramer::ParsePublicHeaderDispatcher( } return error_code; } -QuicErrorCode QuicFramer::ParsePublicHeaderDispatcher( - const QuicEncryptedPacket& packet, - uint8_t expected_destination_connection_id_length, - PacketHeaderFormat* format, QuicLongHeaderType* long_packet_type, - bool* version_present, bool* has_length_prefix, - QuicVersionLabel* version_label, ParsedQuicVersion* parsed_version, - QuicConnectionId* destination_connection_id, - QuicConnectionId* source_connection_id, - std::optional* retry_token, - std::string* detailed_error) { - QuicDataReader reader(packet.data(), packet.length()); - if (reader.IsDoneReading()) { - *detailed_error = "Unable to read first byte."; - return QUIC_INVALID_PACKET_HEADER; - } - const uint8_t first_byte = reader.PeekByte(); - if ((first_byte & FLAGS_LONG_HEADER) == 0 && - (first_byte & FLAGS_FIXED_BIT) == 0 && - (first_byte & FLAGS_DEMULTIPLEXING_BIT) == 0) { - // All versions of Google QUIC up to and including Q043 set - // FLAGS_DEMULTIPLEXING_BIT to one on all client-to-server packets. Q044 - // and Q045 were never default-enabled in production. All subsequent - // versions of Google QUIC (starting with Q046) require FLAGS_FIXED_BIT to - // be set to one on all packets. All versions of IETF QUIC (since - // draft-ietf-quic-transport-17 which was earlier than the first IETF QUIC - // version that was deployed in production by any implementation) also - // require FLAGS_FIXED_BIT to be set to one on all packets. If a packet - // has the FLAGS_LONG_HEADER bit set to one, it could be a first flight - // from an unknown future version that allows the other two bits to be set - // to zero. Based on this, packets that have all three of those bits set - // to zero are known to be invalid. - *detailed_error = "Invalid flags."; - return QUIC_INVALID_PACKET_HEADER; - } - const bool ietf_format = QuicUtils::IsIetfPacketHeader(first_byte); - uint8_t unused_first_byte; - quiche::QuicheVariableLengthIntegerLength retry_token_length_length; - absl::string_view maybe_retry_token; - QuicErrorCode error_code = ParsePublicHeader( - &reader, expected_destination_connection_id_length, ietf_format, - &unused_first_byte, format, version_present, has_length_prefix, - version_label, parsed_version, destination_connection_id, - source_connection_id, long_packet_type, &retry_token_length_length, - &maybe_retry_token, detailed_error); - if (retry_token_length_length != quiche::VARIABLE_LENGTH_INTEGER_LENGTH_0) { - *retry_token = maybe_retry_token; - } else { - retry_token->reset(); - } - return error_code; -} // static QuicErrorCode QuicFramer::ParsePublicHeaderDispatcherShortHeaderLengthUnknown( @@ -6568,34 +6501,6 @@ QuicErrorCode QuicFramer::ParsePublicHeaderDispatcherShortHeaderLengthUnknown( parsed_version, destination_connection_id, source_connection_id, retry_token, detailed_error); } -QuicErrorCode QuicFramer::ParsePublicHeaderDispatcherShortHeaderLengthUnknown( - const QuicEncryptedPacket& packet, PacketHeaderFormat* format, - QuicLongHeaderType* long_packet_type, bool* version_present, - bool* has_length_prefix, QuicVersionLabel* version_label, - ParsedQuicVersion* parsed_version, - QuicConnectionId* destination_connection_id, - QuicConnectionId* source_connection_id, - std::optional* retry_token, std::string* detailed_error, - ConnectionIdGeneratorInterface& generator) { - QuicDataReader reader(packet.data(), packet.length()); - // Get the first two bytes. - if (reader.BytesRemaining() < 2) { - *detailed_error = "Unable to read first two bytes."; - return QUIC_INVALID_PACKET_HEADER; - } - uint8_t two_bytes[2]; - reader.ReadBytes(two_bytes, 2); - uint8_t expected_destination_connection_id_length = - (!QuicUtils::IsIetfPacketHeader(two_bytes[0]) || - two_bytes[0] & FLAGS_LONG_HEADER) - ? 0 - : generator.ConnectionIdLength(two_bytes[1]); - return ParsePublicHeaderDispatcher( - packet, expected_destination_connection_id_length, format, - long_packet_type, version_present, has_length_prefix, version_label, - parsed_version, destination_connection_id, source_connection_id, - retry_token, detailed_error); -} QuicErrorCode QuicFramer::TryDecryptInitialPacketDispatcher( const QuicEncryptedPacket& packet, const ParsedQuicVersion& version, @@ -6710,7 +6615,7 @@ QuicErrorCode QuicFramer::ParsePublicHeaderGoogleQuic( bool* version_present, QuicVersionLabel* version_label, ParsedQuicVersion* parsed_version, absl::string_view* destination_connection_id, std::string* detailed_error) { - *format = GOOGLE_QUIC_PACKET; + *format = GOOGLE_QUIC_Q043_PACKET; *version_present = (*first_byte & PACKET_PUBLIC_FLAGS_VERSION) != 0; uint8_t destination_connection_id_length = 0; if ((*first_byte & PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID) != 0) { @@ -6731,31 +6636,6 @@ QuicErrorCode QuicFramer::ParsePublicHeaderGoogleQuic( } return QUIC_NO_ERROR; } -QuicErrorCode QuicFramer::ParsePublicHeaderGoogleQuic( - QuicDataReader* reader, uint8_t* first_byte, PacketHeaderFormat* format, - bool* version_present, QuicVersionLabel* version_label, - ParsedQuicVersion* parsed_version, - QuicConnectionId* destination_connection_id, std::string* detailed_error) { - *format = GOOGLE_QUIC_PACKET; - *version_present = (*first_byte & PACKET_PUBLIC_FLAGS_VERSION) != 0; - uint8_t destination_connection_id_length = 0; - if ((*first_byte & PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID) != 0) { - destination_connection_id_length = kQuicDefaultConnectionIdLength; - } - if (!reader->ReadConnectionId(destination_connection_id, - destination_connection_id_length)) { - *detailed_error = "Unable to read ConnectionId."; - return QUIC_INVALID_PACKET_HEADER; - } - if (*version_present) { - if (!ProcessVersionLabel(reader, version_label)) { - *detailed_error = "Unable to read protocol version."; - return QUIC_INVALID_PACKET_HEADER; - } - *parsed_version = ParseQuicVersionLabel(*version_label); - } - return QUIC_NO_ERROR; -} namespace { @@ -6857,62 +6737,6 @@ inline bool ParseLongHeaderConnectionIds( } return true; } -// Deprecated version that uses QuicConnectionId instead of string_view. -inline bool ParseLongHeaderConnectionIds( - QuicDataReader& reader, bool has_length_prefix, - QuicVersionLabel version_label, QuicConnectionId& destination_connection_id, - QuicConnectionId& source_connection_id, std::string& detailed_error) { - if (has_length_prefix) { - if (!reader.ReadLengthPrefixedConnectionId(&destination_connection_id)) { - detailed_error = "Unable to read destination connection ID."; - return false; - } - if (!reader.ReadLengthPrefixedConnectionId(&source_connection_id)) { - if (version_label == kProxVersionLabel) { - // The "PROX" version does not follow the length-prefixed invariants, - // and can therefore attempt to read a payload byte and interpret it - // as the source connection ID length, which could fail to parse. - // In that scenario we keep the source connection ID empty but mark - // parsing as successful. - return true; - } - detailed_error = "Unable to read source connection ID."; - return false; - } - } else { - // Parse connection ID lengths. - uint8_t connection_id_lengths_byte; - if (!reader.ReadUInt8(&connection_id_lengths_byte)) { - detailed_error = "Unable to read connection ID lengths."; - return false; - } - uint8_t destination_connection_id_length = - (connection_id_lengths_byte & kDestinationConnectionIdLengthMask) >> 4; - if (destination_connection_id_length != 0) { - destination_connection_id_length += kConnectionIdLengthAdjustment; - } - uint8_t source_connection_id_length = - connection_id_lengths_byte & kSourceConnectionIdLengthMask; - if (source_connection_id_length != 0) { - source_connection_id_length += kConnectionIdLengthAdjustment; - } - - // Read destination connection ID. - if (!reader.ReadConnectionId(&destination_connection_id, - destination_connection_id_length)) { - detailed_error = "Unable to read destination connection ID."; - return false; - } - - // Read source connection ID. - if (!reader.ReadConnectionId(&source_connection_id, - source_connection_id_length)) { - detailed_error = "Unable to read source connection ID."; - return false; - } - } - return true; -} } // namespace @@ -7025,110 +6849,6 @@ QuicErrorCode QuicFramer::ParsePublicHeader( return QUIC_NO_ERROR; } -QuicErrorCode QuicFramer::ParsePublicHeader( - QuicDataReader* reader, uint8_t expected_destination_connection_id_length, - bool ietf_format, uint8_t* first_byte, PacketHeaderFormat* format, - bool* version_present, bool* has_length_prefix, - QuicVersionLabel* version_label, ParsedQuicVersion* parsed_version, - QuicConnectionId* destination_connection_id, - QuicConnectionId* source_connection_id, - QuicLongHeaderType* long_packet_type, - quiche::QuicheVariableLengthIntegerLength* retry_token_length_length, - absl::string_view* retry_token, std::string* detailed_error) { - *version_present = false; - *has_length_prefix = false; - *version_label = 0; - *parsed_version = UnsupportedQuicVersion(); - *source_connection_id = EmptyQuicConnectionId(); - *long_packet_type = INVALID_PACKET_TYPE; - *retry_token_length_length = quiche::VARIABLE_LENGTH_INTEGER_LENGTH_0; - *retry_token = absl::string_view(); - *detailed_error = ""; - - if (!reader->ReadUInt8(first_byte)) { - *detailed_error = "Unable to read first byte."; - return QUIC_INVALID_PACKET_HEADER; - } - - if (!ietf_format) { - return ParsePublicHeaderGoogleQuic( - reader, first_byte, format, version_present, version_label, - parsed_version, destination_connection_id, detailed_error); - } - - *format = GetIetfPacketHeaderFormat(*first_byte); - - if (*format == IETF_QUIC_SHORT_HEADER_PACKET) { - if (!reader->ReadConnectionId(destination_connection_id, - expected_destination_connection_id_length)) { - *detailed_error = "Unable to read destination connection ID."; - return QUIC_INVALID_PACKET_HEADER; - } - return QUIC_NO_ERROR; - } - - QUICHE_DCHECK_EQ(IETF_QUIC_LONG_HEADER_PACKET, *format); - *version_present = true; - if (!ProcessVersionLabel(reader, version_label)) { - *detailed_error = "Unable to read protocol version."; - return QUIC_INVALID_PACKET_HEADER; - } - - if (*version_label == 0) { - *long_packet_type = VERSION_NEGOTIATION; - } - - // Parse version. - *parsed_version = ParseQuicVersionLabel(*version_label); - - // Figure out which IETF QUIC invariants this packet follows. - *has_length_prefix = PacketHasLengthPrefixedConnectionIds( - *reader, *parsed_version, *version_label, *first_byte); - - // Parse connection IDs. - if (!ParseLongHeaderConnectionIds(*reader, *has_length_prefix, *version_label, - *destination_connection_id, - *source_connection_id, *detailed_error)) { - return QUIC_INVALID_PACKET_HEADER; - } - - if (!parsed_version->IsKnown()) { - // Skip parsing of long packet type and retry token for unknown versions. - return QUIC_NO_ERROR; - } - - // Parse long packet type. - *long_packet_type = GetLongHeaderType(*first_byte, *parsed_version); - - switch (*long_packet_type) { - case INVALID_PACKET_TYPE: - *detailed_error = "Unable to parse long packet type."; - return QUIC_INVALID_PACKET_HEADER; - case INITIAL: - if (!parsed_version->SupportsRetry()) { - // Retry token is only present on initial packets for some versions. - return QUIC_NO_ERROR; - } - break; - default: - return QUIC_NO_ERROR; - } - - *retry_token_length_length = reader->PeekVarInt62Length(); - uint64_t retry_token_length; - if (!reader->ReadVarInt62(&retry_token_length)) { - *retry_token_length_length = quiche::VARIABLE_LENGTH_INTEGER_LENGTH_0; - *detailed_error = "Unable to read retry token length."; - return QUIC_INVALID_PACKET_HEADER; - } - - if (!reader->ReadStringPiece(retry_token, retry_token_length)) { - *detailed_error = "Unable to read retry token."; - return QUIC_INVALID_PACKET_HEADER; - } - - return QUIC_NO_ERROR; -} // static bool QuicFramer::WriteClientVersionNegotiationProbePacket( diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_framer.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_framer.h index 374b24b83d..7cacc3f4da 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_framer.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_framer.h @@ -463,17 +463,6 @@ class QUICHE_EXPORT QuicFramer { QuicLongHeaderType* long_packet_type, quiche::QuicheVariableLengthIntegerLength* retry_token_length_length, absl::string_view* retry_token, std::string* detailed_error); - // Deprecated version that uses QuicConnectionId instead of string_view. - static QuicErrorCode ParsePublicHeader( - QuicDataReader* reader, uint8_t expected_destination_connection_id_length, - bool ietf_format, uint8_t* first_byte, PacketHeaderFormat* format, - bool* version_present, bool* has_length_prefix, - QuicVersionLabel* version_label, ParsedQuicVersion* parsed_version, - QuicConnectionId* destination_connection_id, - QuicConnectionId* source_connection_id, - QuicLongHeaderType* long_packet_type, - quiche::QuicheVariableLengthIntegerLength* retry_token_length_length, - absl::string_view* retry_token, std::string* detailed_error); // Parses the unencrypted fields in |packet| and stores them in the other // parameters. This can only be called on the server. @@ -492,17 +481,6 @@ class QUICHE_EXPORT QuicFramer { absl::string_view* source_connection_id, std::optional* retry_token, std::string* detailed_error); - // Deprecated version that uses QuicConnectionId instead of string_view. - static QuicErrorCode ParsePublicHeaderDispatcher( - const QuicEncryptedPacket& packet, - uint8_t expected_destination_connection_id_length, - PacketHeaderFormat* format, QuicLongHeaderType* long_packet_type, - bool* version_present, bool* has_length_prefix, - QuicVersionLabel* version_label, ParsedQuicVersion* parsed_version, - QuicConnectionId* destination_connection_id, - QuicConnectionId* source_connection_id, - std::optional* retry_token, - std::string* detailed_error); // Parses the unencrypted fields in |packet| and stores them in the other // parameters. The only callers that should use this method are ones where @@ -521,16 +499,6 @@ class QUICHE_EXPORT QuicFramer { absl::string_view* source_connection_id, std::optional* retry_token, std::string* detailed_error, ConnectionIdGeneratorInterface& generator); - // Deprecated version that uses QuicConnectionId instead of string_view. - static QuicErrorCode ParsePublicHeaderDispatcherShortHeaderLengthUnknown( - const QuicEncryptedPacket& packet, PacketHeaderFormat* format, - QuicLongHeaderType* long_packet_type, bool* version_present, - bool* has_length_prefix, QuicVersionLabel* version_label, - ParsedQuicVersion* parsed_version, - QuicConnectionId* destination_connection_id, - QuicConnectionId* source_connection_id, - std::optional* retry_token, - std::string* detailed_error, ConnectionIdGeneratorInterface& generator); // Attempts to parse the packet number and decrypt the packet payload at // server for IETF Initial packets. Returns an error code if parsing or @@ -998,12 +966,6 @@ class QUICHE_EXPORT QuicFramer { ParsedQuicVersion* parsed_version, absl::string_view* destination_connection_id, std::string* detailed_error); - // Deprecated version that uses QuicConnectionId instead of string_view. - static QuicErrorCode ParsePublicHeaderGoogleQuic( - QuicDataReader* reader, uint8_t* first_byte, PacketHeaderFormat* format, - bool* version_present, QuicVersionLabel* version_label, - ParsedQuicVersion* parsed_version, - QuicConnectionId* destination_connection_id, std::string* detailed_error); bool ValidateReceivedConnectionIds(const QuicPacketHeader& header); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_generic_session.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_generic_session.cc index f142190276..f0edb3f07f 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_generic_session.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_generic_session.cc @@ -97,6 +97,11 @@ QuicGenericSessionBase::~QuicGenericSessionBase() { } } +void QuicGenericSessionBase::Initialize() { + QuicSession::Initialize(); + connection()->sent_packet_manager().EnableOverheadMeasurement(); +} + QuicStream* QuicGenericSessionBase::CreateIncomingStream(QuicStreamId id) { QUIC_DVLOG(1) << "Creating incoming QuicGenricStream " << id; QuicGenericStream* stream = CreateStream(id); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_generic_session.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_generic_session.h index d8c220a429..a3e7a0c324 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_generic_session.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_generic_session.h @@ -55,6 +55,7 @@ class QUICHE_EXPORT QuicGenericSessionBase : public QuicSession, ~QuicGenericSessionBase(); // QuicSession implementation. + void Initialize() override; std::vector GetAlpnsToOffer() const override { return std::vector({alpn_}); } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_packet_reader.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_packet_reader.cc index 8b36e40f6a..230460ab56 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_packet_reader.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_packet_reader.cc @@ -55,66 +55,61 @@ bool QuicPacketReader::ReadAndDispatchPackets( QuicUdpPacketInfoBit::V6_SELF_IP, QuicUdpPacketInfoBit::RECV_TIMESTAMP, QuicUdpPacketInfoBit::TTL, QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER, QuicUdpPacketInfoBit::V6_FLOW_LABEL}); - if (GetQuicReloadableFlag(quic_record_tos_byte)) { QUIC_CODE_COUNT(quic_record_tos_byte); - // TODO: martinduke - Consolidate ECN and TOS bits. // Note ToS bit will also populate ECN codepoint. info_bits.Set(QuicUdpPacketInfoBit::TOS); - } else { - info_bits.Set(QuicUdpPacketInfoBit::ECN); - } - size_t packets_read = - socket_api_.ReadMultiplePackets(fd, info_bits, &read_results_); - for (size_t i = 0; i < packets_read; ++i) { - auto& result = read_results_[i]; - if (!result.ok) { - QUIC_CODE_COUNT(quic_packet_reader_read_failure); - continue; - } + size_t packets_read = + socket_api_.ReadMultiplePackets(fd, info_bits, &read_results_); + for (size_t i = 0; i < packets_read; ++i) { + auto& result = read_results_[i]; + if (!result.ok) { + QUIC_CODE_COUNT(quic_packet_reader_read_failure); + continue; + } - if (!result.packet_info.HasValue(QuicUdpPacketInfoBit::PEER_ADDRESS)) { - QUIC_BUG(quic_bug_10329_1) << "Unable to get peer socket address."; - continue; - } + if (!result.packet_info.HasValue(QuicUdpPacketInfoBit::PEER_ADDRESS)) { + QUIC_BUG(quic_bug_10329_1) << "Unable to get peer socket address."; + continue; + } - QuicSocketAddress peer_address = - result.packet_info.peer_address().Normalized(); + QuicSocketAddress peer_address = + result.packet_info.peer_address().Normalized(); - QuicIpAddress self_ip = GetSelfIpFromPacketInfo( - result.packet_info, peer_address.host().IsIPv6()); - if (!self_ip.IsInitialized()) { - QUIC_BUG(quic_bug_10329_2) << "Unable to get self IP address."; - continue; - } + QuicIpAddress self_ip = GetSelfIpFromPacketInfo( + result.packet_info, peer_address.host().IsIPv6()); + if (!self_ip.IsInitialized()) { + QUIC_BUG(quic_bug_10329_2) << "Unable to get self IP address."; + continue; + } - bool has_ttl = result.packet_info.HasValue(QuicUdpPacketInfoBit::TTL); - int ttl = has_ttl ? result.packet_info.ttl() : 0; - if (!has_ttl) { - QUIC_CODE_COUNT(quic_packet_reader_no_ttl); - } + bool has_ttl = result.packet_info.HasValue(QuicUdpPacketInfoBit::TTL); + int ttl = has_ttl ? result.packet_info.ttl() : 0; + if (!has_ttl) { + QUIC_CODE_COUNT(quic_packet_reader_no_ttl); + } - char* headers = nullptr; - size_t headers_length = 0; - if (result.packet_info.HasValue( - QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER)) { - headers = result.packet_info.google_packet_headers().buffer; - headers_length = result.packet_info.google_packet_headers().buffer_len; - } else { - QUIC_CODE_COUNT(quic_packet_reader_no_google_packet_header); - } - uint32_t flow_label = 0; - if (result.packet_info.HasValue(QuicUdpPacketInfoBit::V6_FLOW_LABEL)) { - flow_label = result.packet_info.flow_label(); - } + char* headers = nullptr; + size_t headers_length = 0; + if (result.packet_info.HasValue( + QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER)) { + headers = result.packet_info.google_packet_headers().buffer; + headers_length = result.packet_info.google_packet_headers().buffer_len; + } else { + QUIC_CODE_COUNT(quic_packet_reader_no_google_packet_header); + } + uint32_t flow_label = 0; + if (result.packet_info.HasValue(QuicUdpPacketInfoBit::V6_FLOW_LABEL)) { + flow_label = result.packet_info.flow_label(); + } - QuicReceivedPacket packet( - result.packet_buffer.buffer, result.packet_buffer.buffer_len, now, - /*owns_buffer=*/false, ttl, has_ttl, headers, headers_length, - /*owns_header_buffer=*/false, result.packet_info.ecn_codepoint(), - result.packet_info.GetTos(), flow_label); - QuicSocketAddress self_address(self_ip, port); - processor->ProcessPacket(self_address, peer_address, packet); - } + QuicReceivedPacket packet( + result.packet_buffer.buffer, result.packet_buffer.buffer_len, now, + /*owns_buffer=*/false, ttl, has_ttl, headers, headers_length, + /*owns_header_buffer=*/false, result.packet_info.ecn_codepoint(), + result.packet_info.GetTos(), flow_label); + QuicSocketAddress self_address(self_ip, port); + processor->ProcessPacket(self_address, peer_address, packet); + } // We may not have read all of the packets available on the socket. return packets_read == kNumPacketsPerReadMmsgCall; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_packets.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_packets.cc index d127cea02e..0346ae1036 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_packets.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_packets.cc @@ -162,7 +162,7 @@ QuicPacketHeader::QuicPacketHeader() : destination_connection_id(EmptyQuicConnectionId()), possible_stateless_reset_token({}), packet_number_length(PACKET_4BYTE_PACKET_NUMBER), - form(GOOGLE_QUIC_PACKET), + form(GOOGLE_QUIC_Q043_PACKET), type_byte(0), destination_connection_id_included(CONNECTION_ID_PRESENT), source_connection_id_included(CONNECTION_ID_ABSENT), @@ -551,7 +551,7 @@ ReceivedPacketInfo::ReceivedPacketInfo(const QuicSocketAddress& self_address, : self_address(self_address), peer_address(peer_address), packet(packet), - form(GOOGLE_QUIC_PACKET), + form(GOOGLE_QUIC_Q043_PACKET), long_packet_type(INVALID_PACKET_TYPE), version_flag(false), use_length_prefix(false), diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_ping_manager.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_ping_manager.cc index 533dd10bd9..52a5cd4101 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_ping_manager.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_ping_manager.cc @@ -25,8 +25,9 @@ QuicPingManager::QuicPingManager(Perspective perspective, Delegate* delegate, : perspective_(perspective), delegate_(delegate), alarm_(alarm) {} void QuicPingManager::SetAlarm(QuicTime now, bool should_keep_alive, - bool has_in_flight_packets) { - UpdateDeadlines(now, should_keep_alive, has_in_flight_packets); + bool has_in_flight_packets, + QuicTime::Delta pto_delay) { + UpdateDeadlines(now, should_keep_alive, has_in_flight_packets, pto_delay); const QuicTime earliest_deadline = GetEarliestDeadline(); if (!earliest_deadline.IsInitialized()) { alarm_.Cancel(); @@ -72,7 +73,8 @@ void QuicPingManager::Stop() { } void QuicPingManager::UpdateDeadlines(QuicTime now, bool should_keep_alive, - bool has_in_flight_packets) { + bool has_in_flight_packets, + QuicTime::Delta pto_delay) { // Reset keep-alive deadline given it will be set later (with left edge // |now|). keep_alive_deadline_ = QuicTime::Zero(); @@ -96,7 +98,8 @@ void QuicPingManager::UpdateDeadlines(QuicTime now, bool should_keep_alive, // Clients send 15s PINGs to avoid NATs from timing out. keep_alive_deadline_ = now + keep_alive_timeout_; } - if (initial_retransmittable_on_wire_timeout_.IsInfinite() || + if ((num_ptos_for_retransmittable_on_wire_timeout_ == 0 && + initial_retransmittable_on_wire_timeout_.IsInfinite()) || has_in_flight_packets || retransmittable_on_wire_count_ > GetQuicFlag(quic_max_retransmittable_on_wire_ping_count)) { @@ -105,10 +108,18 @@ void QuicPingManager::UpdateDeadlines(QuicTime now, bool should_keep_alive, return; } - QUICHE_DCHECK_LT(initial_retransmittable_on_wire_timeout_, - keep_alive_timeout_); - QuicTime::Delta retransmittable_on_wire_timeout = - initial_retransmittable_on_wire_timeout_; + QuicTime::Delta retransmittable_on_wire_timeout = QuicTime::Delta::Zero(); + if (num_ptos_for_retransmittable_on_wire_timeout_ > 0) { + QUICHE_DCHECK_NE(pto_delay, QuicTime::Delta::Zero()); + retransmittable_on_wire_timeout = + static_cast(num_ptos_for_retransmittable_on_wire_timeout_) * + pto_delay; + } else { + QUICHE_DCHECK_LT(initial_retransmittable_on_wire_timeout_, + keep_alive_timeout_); + retransmittable_on_wire_timeout = initial_retransmittable_on_wire_timeout_; + } + const int max_aggressive_retransmittable_on_wire_count = GetQuicFlag(quic_max_aggressive_retransmittable_on_wire_ping_count); QUICHE_DCHECK_LE(0, max_aggressive_retransmittable_on_wire_count); @@ -120,8 +131,9 @@ void QuicPingManager::UpdateDeadlines(QuicTime now, bool should_keep_alive, max_aggressive_retransmittable_on_wire_count, kMaxRetransmittableOnWireDelayShift); retransmittable_on_wire_timeout = - initial_retransmittable_on_wire_timeout_ * (1 << shift); + retransmittable_on_wire_timeout * (1 << shift); } + if (retransmittable_on_wire_deadline_.IsInitialized() && retransmittable_on_wire_deadline_ < now + retransmittable_on_wire_timeout) { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_ping_manager.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_ping_manager.h index 3250416e33..4cf98105c5 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_ping_manager.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_ping_manager.h @@ -5,6 +5,8 @@ #ifndef QUICHE_QUIC_CORE_QUIC_PING_MANAGER_H_ #define QUICHE_QUIC_CORE_QUIC_PING_MANAGER_H_ +#include + #include "quiche/quic/core/quic_alarm.h" #include "quiche/quic/core/quic_alarm_factory.h" #include "quiche/quic/core/quic_connection_alarms.h" @@ -43,7 +45,7 @@ class QUICHE_EXPORT QuicPingManager { // Called to set |alarm_|. void SetAlarm(QuicTime now, bool should_keep_alive, - bool has_in_flight_packets); + bool has_in_flight_packets, QuicTime::Delta pto_delay); // Called when |alarm_| fires. void OnAlarm(); @@ -66,13 +68,19 @@ class QUICHE_EXPORT QuicPingManager { consecutive_retransmittable_on_wire_count_ = 0; } + void set_num_ptos_for_retransmittable_on_wire_timeout( + uint8_t num_ptos_for_retransmittable_on_wire_timeout) { + num_ptos_for_retransmittable_on_wire_timeout_ = + num_ptos_for_retransmittable_on_wire_timeout; + } + private: friend class test::QuicConnectionPeer; friend class test::QuicPingManagerPeer; // Update |retransmittable_on_wire_deadline_| and |keep_alive_deadline_|. void UpdateDeadlines(QuicTime now, bool should_keep_alive, - bool has_in_flight_packets); + bool has_in_flight_packets, QuicTime::Delta pto_delay); // Get earliest deadline of |retransmittable_on_wire_deadline_| and // |keep_alive_deadline_|. Returns 0 if both deadlines are not initialized. @@ -101,6 +109,8 @@ class QUICHE_EXPORT QuicPingManager { QuicTime keep_alive_deadline_ = QuicTime::Zero(); QuicAlarmProxy alarm_; + + uint8_t num_ptos_for_retransmittable_on_wire_timeout_ = 0; }; } // namespace quic diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager.cc index 5e18cab11e..6bca5a94f4 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager.cc @@ -6,12 +6,15 @@ #include #include +#include #include #include "quiche/quic/core/congestion_control/rtt_stats.h" #include "quiche/quic/core/crypto/crypto_protocol.h" #include "quiche/quic/core/quic_config.h" #include "quiche/quic/core/quic_connection_stats.h" +#include "quiche/quic/core/quic_constants.h" +#include "quiche/quic/core/quic_packet_number.h" #include "quiche/quic/core/quic_time.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" @@ -292,9 +295,11 @@ void QuicReceivedPacketManager::MaybeUpdateAckTimeout( return; } - // TODO(martinduke): If a missing packet is received, do we send it when - // reordering_threshold_ == 0? - if (was_last_packet_missing_ && last_sent_largest_acked_.IsInitialized() && + // Limiting this to reordering_threshold_ > 0 is not compliant with + // draft-ietf-quic-ack-frequency-11, but there is an issue to add this + // behavior. + if (reordering_threshold_ > 0 && was_last_packet_missing_ && + last_sent_largest_acked_.IsInitialized() && last_received_packet_number < last_sent_largest_acked_) { // Ack immediately if an ACK frame was sent with a larger largest acked than // the newly received packet number. @@ -321,9 +326,25 @@ void QuicReceivedPacketManager::MaybeUpdateAckTimeout( return; } - if (reordering_threshold_ == 1 && HasNewMissingPackets()) { // Fast path. - ack_timeout_ = now; - return; + if (reordering_threshold_ == 1) { + // Default behavior, not updated by ACK_FREQUENCY. + if (HasNewMissingPackets()) { + ack_timeout_ = now; + return; + } + } else { + if (ack_frame_.packets.NumIntervals() == max_ack_ranges_ && + (!last_sent_largest_acked_.IsInitialized() || + last_sent_largest_acked_ < ack_frame_.packets.begin()->max() - 1)) { + // If the lowest ACK range has not yet been reported, and might be trimmed + // on the next packet arrival, send an ACK. + ack_timeout_ = now; + return; + } + if (ReorderingExceedsThreshold()) { + ack_timeout_ = now; + return; + } } const QuicTime updated_ack_time = std::max( @@ -360,6 +381,54 @@ bool QuicReceivedPacketManager::HasNewMissingPackets() const { ack_frame_.packets.LastIntervalLength() <= kMaxPacketsAfterNewMissing; } +bool QuicReceivedPacketManager::ReorderingExceedsThreshold() const { + if (reordering_threshold_ <= 1) { // flag is not enabled, or there is no + // threshold. + return false; + } + if (!HasMissingPackets() || + GetLargestObserved() < QuicPacketNumber(reordering_threshold_)) { + return false; + } + // Find the next missing packet. + QuicPacketNumber smallest_unreported_missing; + if (last_sent_largest_acked_.IsInitialized() && + last_sent_largest_acked_ >= QuicPacketNumber(reordering_threshold_)) { + smallest_unreported_missing = + last_sent_largest_acked_ - reordering_threshold_ + 1; + } + // All ACK ranges before peer_least_packet_awaiting_ack_ have already been + // deleted, so this is the lowest packet number that has receive state. + if (peer_least_packet_awaiting_ack_.IsInitialized() && + (!smallest_unreported_missing.IsInitialized() || + smallest_unreported_missing < peer_least_packet_awaiting_ack_)) { + smallest_unreported_missing = peer_least_packet_awaiting_ack_; + if (!least_unacked_plus_1_) { + ++smallest_unreported_missing; + } + } + if (smallest_unreported_missing.IsInitialized()) { + auto it = ack_frame_.packets.LowerBound(smallest_unreported_missing); + if (it == ack_frame_.packets.end()) { + QUIC_BUG(quic_bug_764939479) + << "Checking reordering with improper ACK state"; + return false; + } + if (it->Contains(smallest_unreported_missing)) { + smallest_unreported_missing = it->max(); + } + } else { + // No ACK has been sent. Since HasMissingPackets() is true, there must be at + // least two ranges. Per RFC9000, ignore the range from zero to the first + // observed packet. Smallest_unreported_missing is therefore the max of the + // first range. + QUICHE_DCHECK(ack_frame_.packets.NumIntervals() > 1); + smallest_unreported_missing = ack_frame_.packets.begin()->max(); + } + return smallest_unreported_missing <= + (GetLargestObserved() - reordering_threshold_); +} + bool QuicReceivedPacketManager::ack_frame_updated() const { return ack_frame_updated_; } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager.h index 404d46d22d..221b16ac4f 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager.h @@ -11,6 +11,7 @@ #include "quiche/quic/core/frames/quic_ack_frequency_frame.h" #include "quiche/quic/core/quic_config.h" #include "quiche/quic/core/quic_constants.h" +#include "quiche/quic/core/quic_packet_number.h" #include "quiche/quic/core/quic_packets.h" #include "quiche/quic/core/quic_time.h" #include "quiche/quic/core/quic_types.h" @@ -86,6 +87,13 @@ class QUICHE_EXPORT QuicReceivedPacketManager { // packets of the largest observed. virtual bool HasNewMissingPackets() const; + // Returns true if the lowest packet number beyond largest_acked_ is more + // than reordering_threshold_ behind largest_unacked. Used only when + // reordering_threshold_ > 1. + // TODO(martinduke): This code can be used for reordering_threshold_ == 1 + // as well, once we have full confidence in it. + bool ReorderingExceedsThreshold() const; + virtual bool ack_frame_updated() const; QuicPacketNumber GetLargestObserved() const; @@ -225,6 +233,9 @@ class QUICHE_EXPORT QuicReceivedPacketManager { // should set the ack timeout to now. bool ack_now_ = false; + // Latch for the flag. + bool least_unacked_plus_1_ = GetQuicReloadableFlag(quic_least_unacked_plus_1); + // Last sent largest acked, which gets updated when ACK was successfully sent. QuicPacketNumber last_sent_largest_acked_; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager.cc index 2c60d236a8..ef8b7a9160 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager.cc @@ -72,6 +72,15 @@ static const uint32_t kConservativeUnpacedBurst = 2; // The default number of PTOs to trigger path degrading. static const uint32_t kNumProbeTimeoutsForPathDegradingDelay = 4; +// QUIC overhead returned if there is not enough data to provide an estimate. 5% +// is roughly the number one can get from a simulated unit test. +constexpr float kDefaultOverhead = 0.05f; + +// Minimum number of data bytes sent before the packet manager can provide an +// estimate of the QUIC overhead. +constexpr QuicByteCount kMinBytesForOverheadMeasurement = + kDefaultMaxPacketSize * 20; + } // namespace #define ENDPOINT \ @@ -106,7 +115,8 @@ QuicSentPacketManager::QuicSentPacketManager( one_rtt_packet_acked_(false), num_ptos_for_path_degrading_(kNumProbeTimeoutsForPathDegradingDelay), ignore_pings_(false), - ignore_ack_delay_(false) { + ignore_ack_delay_(false), + measure_overhead_(false) { SetSendAlgorithm(congestion_control_type); } @@ -131,16 +141,10 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) { peer_max_ack_delay_ = QuicTime::Delta::FromMilliseconds(config.ReceivedMaxAckDelayMs()); } - if (GetQuicReloadableFlag(quic_can_send_ack_frequency) && - perspective == Perspective::IS_SERVER) { - if (config.HasReceivedMinAckDelayDraft10Ms()) { - peer_min_ack_delay_ = QuicTime::Delta::FromMilliseconds( - config.ReceivedMinAckDelayDraft10Ms()); - } - if (config.HasClientSentConnectionOption(kAFF1, perspective)) { - use_smoothed_rtt_in_ack_delay_ = true; - } - } + // TODO(b/389762349): set peer_min_ack_delay_ if + // config.HasReceivedMinAckDelayDraft10Ms(). Set + // use_smoothed_rtt_in_ack_delay_ based on + // config.HasClientSentConnectionOption(kAFF1, perspective). if (config.HasClientSentConnectionOption(kMAD0, perspective)) { ignore_ack_delay_ = true; } @@ -675,7 +679,6 @@ QuicAckFrequencyFrame QuicSentPacketManager::GetUpdatedAckFrequencyFrame() return frame; } - QUIC_RELOADABLE_FLAG_COUNT_N(quic_can_send_ack_frequency, 1, 3); frame.ack_eliciting_threshold = kMaxRetransmittablePacketsBeforeAck; auto rtt = use_smoothed_rtt_in_ack_delay_ ? rtt_stats_.SmoothedOrInitialRtt() : rtt_stats_.MinOrInitialRtt(); @@ -727,6 +730,8 @@ bool QuicSentPacketManager::OnPacketSent( --pending_timer_transmission_count_; } + UpdateOverheadMeasurements(packet); + bool in_flight = has_retransmittable_data == HAS_RETRANSMITTABLE_DATA; if (ignore_pings_ && mutable_packet->retransmittable_frames.size() == 1 && mutable_packet->retransmittable_frames[0].type == PING_FRAME) { @@ -1674,5 +1679,37 @@ void QuicSentPacketManager::OnAckFrequencyFrameAcked( ->first; } +float QuicSentPacketManager::GetOverheadEstimate() const { + // `overhead_total_bytes_` check is a defense-in-depth again divide-by-zero. + if (overhead_total_bytes_ < kMinBytesForOverheadMeasurement || + overhead_good_bytes_ < kMinBytesForOverheadMeasurement) { + return kDefaultOverhead; + } + + return 1.0f - static_cast(overhead_good_bytes_) / + static_cast(overhead_total_bytes_); +} + +void QuicSentPacketManager::UpdateOverheadMeasurements( + const SerializedPacket& packet) { + if (!measure_overhead_) { + return; + } + // Ignore packets with the long header. + if (packet.encryption_level != ENCRYPTION_FORWARD_SECURE) { + return; + } + + overhead_total_bytes_ += packet.encrypted_length; + for (const QuicFrame& frame : packet.retransmittable_frames) { + if (frame.type == QuicFrameType::STREAM_FRAME) { + overhead_good_bytes_ += frame.stream_frame.data_length; + } + if (frame.type == QuicFrameType::MESSAGE_FRAME) { + overhead_good_bytes_ += frame.message_frame->message_length; + } + } +} + #undef ENDPOINT // undef for jumbo builds } // namespace quic diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager.h index 4b0dfe625f..f17c386644 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager.h @@ -512,6 +512,14 @@ class QUICHE_EXPORT QuicSentPacketManager { // kMinUntrustedInitialRoundTripTimeUs if not |trusted|. void SetInitialRtt(QuicTime::Delta rtt, bool trusted); + // Enables QUIC overhead measurement. + void EnableOverheadMeasurement() { measure_overhead_ = true; } + + // Returns an estimate of overhead added by QUIC as a fraction of application + // payload sent to total data sent (total data includes everything inside UDP + // packets sent by QUIC, but excludes UDP headers and above). + float GetOverheadEstimate() const; + private: friend class test::QuicConnectionPeer; friend class test::QuicSentPacketManagerPeer; @@ -623,6 +631,9 @@ class QUICHE_EXPORT QuicSentPacketManager { void RecordEcnMarkingSent(QuicEcnCodepoint ecn_codepoint, EncryptionLevel level); + // Updates the QUIC overhead measurements if those are enabled. + void UpdateOverheadMeasurements(const SerializedPacket& packet); + // Newly serialized retransmittable packets are added to this map, which // contains owning pointers to any contained frames. If a packet is // retransmitted, this map will contain entries for both the old and the new @@ -738,6 +749,9 @@ class QUICHE_EXPORT QuicSentPacketManager { // Whether to ignore the ack_delay in received ACKs. bool ignore_ack_delay_; + // Whether to record stats necessary for the QUIC overhead estimation. + bool measure_overhead_; + // The total number of packets sent with ECT(0) or ECT(1) in each packet // number space over the life of the connection. QuicPacketCount ect0_packets_sent_[NUM_PACKET_NUMBER_SPACES] = {0, 0, 0}; @@ -746,6 +760,11 @@ class QUICHE_EXPORT QuicSentPacketManager { // Most recent ECN codepoint counts received in an ACK frame sent by the peer. QuicEcnCounts peer_ack_ecn_counts_[NUM_PACKET_NUMBER_SPACES]; + // The numerator and denominator used for overhead measurements. Only recorded + // if `measure_overhead_` is true. + QuicByteCount overhead_good_bytes_ = 0; + QuicByteCount overhead_total_bytes_ = 0; + std::optional deferred_send_alarm_delay_; // If true, QuicConnection has called EnableECT0() or EnableECT1(). This is 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 be6aa0afaa..e3e5e708e3 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 @@ -179,6 +179,10 @@ void QuicSession::Initialize() { } else if (config_.HasClientSentConnectionOption(kCHP2, perspective_)) { config_.SetDiscardLengthToSend(kDefaultMaxPacketSize * 2); } + if (config_.HasClientRequestedIndependentOption(kAFIA, perspective_) && + connection_->version().HasIetfQuicFrames()) { + config_.SetMinAckDelayDraft10Ms(kDefaultMinAckDelayTimeMs); + } } else if (GetQuicReloadableFlag(quic_receive_ack_frequency) && connection_->version().HasIetfQuicFrames()) { config_.SetMinAckDelayDraft10Ms(kDefaultMinAckDelayTimeMs); @@ -704,7 +708,11 @@ void QuicSession::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) { } void QuicSession::OnBlockedFrame(const QuicBlockedFrame& frame) { - QUIC_CODE_COUNT(quic_session_blocked_frame_received); + if (frame.stream_id == QuicUtils::GetInvalidStreamId(transport_version())) { + QUIC_CODE_COUNT(quic_data_blocked_frame_received); + } else { + QUIC_CODE_COUNT(quic_stream_data_blocked_frame_received); + } // TODO(rjshade): Compare our flow control receive windows for specified // streams: if we have a large window then maybe something // had gone wrong with the flow control accounting. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_time_wait_list_manager.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_time_wait_list_manager.cc index 5727be4c26..45be2df372 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_time_wait_list_manager.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_time_wait_list_manager.cc @@ -205,7 +205,7 @@ void QuicTimeWaitListManager::ProcessPacket( connection_data->info.ietf_quic, received_packet_length, std::move(packet_context)); return; - case GOOGLE_QUIC_PACKET: + case GOOGLE_QUIC_Q043_PACKET: if (connection_data->info.ietf_quic) { QUIC_CODE_COUNT(quic_received_gquic_packet_for_ietf_quic); } 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 aa69d02a08..a974c40d01 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 @@ -240,7 +240,7 @@ std::string PacketHeaderFormatToString(PacketHeaderFormat format) { switch (format) { RETURN_STRING_LITERAL(IETF_QUIC_LONG_HEADER_PACKET); RETURN_STRING_LITERAL(IETF_QUIC_SHORT_HEADER_PACKET); - RETURN_STRING_LITERAL(GOOGLE_QUIC_PACKET); + RETURN_STRING_LITERAL(GOOGLE_QUIC_Q043_PACKET); default: return absl::StrCat("Unknown (", static_cast(format), ")"); } 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 836ee4f976..dbe7464774 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 @@ -8,9 +8,11 @@ #include #include #include -#include +#include #include #include +#include +#include #include #include "absl/container/inlined_vector.h" @@ -20,9 +22,8 @@ #include "quiche/quic/core/quic_error_codes.h" #include "quiche/quic/core/quic_packet_number.h" #include "quiche/quic/core/quic_time.h" -#include "quiche/quic/platform/api/quic_export.h" #include "quiche/quic/platform/api/quic_flags.h" -#include "quiche/common/quiche_endian.h" +#include "quiche/common/platform/api/quiche_export.h" #include "quiche/web_transport/web_transport.h" namespace quic { @@ -77,7 +78,7 @@ struct QUICHE_EXPORT QuicConsumedData { // By default, gtest prints the raw bytes of an object. The bool data // member causes this object to have padding bytes, which causes the - // default gtest object printer to read uninitialize memory. So we need + // default gtest object printer to read uninitialized memory. So we need // to teach gtest how to print this object. QUICHE_EXPORT friend std::ostream& operator<<(std::ostream& os, const QuicConsumedData& s); @@ -228,7 +229,7 @@ QUICHE_EXPORT std::ostream& operator<<( std::ostream& os, const ConnectionCloseSource& connection_close_source); // Should a connection be closed silently or not. -enum class ConnectionCloseBehavior { +enum class ConnectionCloseBehavior : uint8_t { SILENT_CLOSE, SILENT_CLOSE_WITH_CONNECTION_CLOSE_PACKET_SERIALIZED, SEND_CONNECTION_CLOSE_PACKET @@ -558,9 +559,24 @@ enum SentPacketState : uint8_t { }; enum PacketHeaderFormat : uint8_t { + // Indicates that the packet is either an IETF QUIC long header packet or a + // Google-QUIC Q046 long header packet. The Q046 long header format differs + // from true IETF-QUIC in that each connection ID length is encoded in 4 bits + // instead of 8. IETF_QUIC_LONG_HEADER_PACKET, + // Indicates that the packet is either an IETF QUIC short header packet or a + // Google-QUIC Q046 short header packet. The formats are identical. IETF_QUIC_SHORT_HEADER_PACKET, - GOOGLE_QUIC_PACKET, + // Indicates that the packet is an obsolete Google-QUIC Q043 packet. While + // QUICHE no longer supports Q043 (which had a very different packet header + // format) GOOGLE_QUIC_Q043_PACKET is only used to detect these packets in + // order to send an appropriately formatted Q043 version negotiation packet. + // There are bits in the first byte to indicate if there is a connection ID + // present (which must be 8 bytes long) and if there is a version present. + // Connection ID (with no length prefix) and version follow, in that order. + // The first byte bit-pattern that indicates Q043 (or earlier) is + // 0b00xx1xxx, where 'x' is any value. + GOOGLE_QUIC_Q043_PACKET, }; QUICHE_EXPORT std::string PacketHeaderFormatToString(PacketHeaderFormat format); @@ -907,7 +923,7 @@ QUICHE_EXPORT std::ostream& operator<<(std::ostream& os, // The two bits in the IP header for Explicit Congestion Notification can take // one of four values. -enum QuicEcnCodepoint { +enum QuicEcnCodepoint : uint8_t { // The NOT-ECT codepoint, indicating the packet sender is not using (or the // network has disabled) ECN. ECN_NOT_ECT = 0, @@ -938,10 +954,7 @@ struct QUICHE_EXPORT QuicEcnCounts { std::to_string(ce)); } - bool operator==(const QuicEcnCounts& other) const { - return (this->ect0 == other.ect0 && this->ect1 == other.ect1 && - this->ce == other.ce); - } + bool operator==(const QuicEcnCounts& other) const = default; QuicPacketCount ect0 = 0; QuicPacketCount ect1 = 0; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_versions.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_versions.cc index f27a5ef6da..84aaabaa8a 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_versions.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_versions.cc @@ -332,21 +332,10 @@ ParsedQuicVersionVector CurrentSupportedHttp3Versions() { } ParsedQuicVersion ParseQuicVersionLabel(QuicVersionLabel version_label) { - if (GetQuicReloadableFlag(quic_heapless_static_parser)) { - for (const ParsedQuicVersion& version : SupportedVersions()) { - if (version_label == CreateQuicVersionLabel(version)) { - return version; - } + for (const ParsedQuicVersion& version : SupportedVersions()) { + if (version_label == CreateQuicVersionLabel(version)) { + return version; } - } else { - for (const ParsedQuicVersion& version : AllSupportedVersions()) { - if (version_label == CreateQuicVersionLabel(version)) { - return version; - } - } - // Reading from the client so this should not be considered an ERROR. - QUIC_DLOG(INFO) << "Unsupported QuicVersionLabel version: " - << QuicVersionLabelToString(version_label); } return UnsupportedQuicVersion(); } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_versions.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_versions.h index f8fe6ed6ed..18bf1f92c3 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_versions.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_versions.h @@ -148,9 +148,9 @@ QUICHE_EXPORT std::string QuicVersionToString( // We are planning on eventually deprecating PROTOCOL_QUIC_CRYPTO in favor of // PROTOCOL_TLS1_3. enum HandshakeProtocol { - PROTOCOL_UNSUPPORTED, - PROTOCOL_QUIC_CRYPTO, - PROTOCOL_TLS1_3, + PROTOCOL_UNSUPPORTED = 0, + PROTOCOL_QUIC_CRYPTO = 1, + PROTOCOL_TLS1_3 = 2, }; // Helper function which translates from a HandshakeProtocol to a string. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_handshaker.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_handshaker.cc index 9529230d94..91f3b59e86 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_handshaker.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_handshaker.cc @@ -286,23 +286,13 @@ void TlsHandshaker::SetWriteSecret(EncryptionLevel level, QuicEncrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher)); const EVP_MD* prf = Prf(cipher); std::vector header_protection_key; - if (GetQuicReloadableFlag(quic_heapless_key_derivation)) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_heapless_key_derivation, 7, 10); - CryptoUtils::SetKeyAndIVHeapless(prf, write_secret, - handshaker_delegate_->parsed_version(), - encrypter.get()); - header_protection_key.resize(encrypter->GetKeySize()); - CryptoUtils::GenerateHeaderProtectionKey( - prf, write_secret, handshaker_delegate_->parsed_version(), - absl::Span(header_protection_key)); - } else { - CryptoUtils::SetKeyAndIV(prf, write_secret, - handshaker_delegate_->parsed_version(), - encrypter.get()); - header_protection_key = CryptoUtils::GenerateHeaderProtectionKey( - prf, write_secret, handshaker_delegate_->parsed_version(), - encrypter->GetKeySize()); - } + CryptoUtils::SetKeyAndIV(prf, write_secret, + handshaker_delegate_->parsed_version(), + encrypter.get()); + header_protection_key.resize(encrypter->GetKeySize()); + CryptoUtils::GenerateHeaderProtectionKey( + prf, write_secret, handshaker_delegate_->parsed_version(), + absl::Span(header_protection_key)); encrypter->SetHeaderProtectionKey( absl::string_view(reinterpret_cast(header_protection_key.data()), header_protection_key.size())); @@ -329,23 +319,13 @@ bool TlsHandshaker::SetReadSecret(EncryptionLevel level, QuicDecrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher)); const EVP_MD* prf = Prf(cipher); std::vector header_protection_key; - if (GetQuicReloadableFlag(quic_heapless_key_derivation)) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_heapless_key_derivation, 8, 10); - CryptoUtils::SetKeyAndIVHeapless(prf, read_secret, - handshaker_delegate_->parsed_version(), - decrypter.get()); - header_protection_key.resize(decrypter->GetKeySize()); - CryptoUtils::GenerateHeaderProtectionKey( - prf, read_secret, handshaker_delegate_->parsed_version(), - absl::Span(header_protection_key)); - } else { - CryptoUtils::SetKeyAndIV(prf, read_secret, - handshaker_delegate_->parsed_version(), - decrypter.get()); - header_protection_key = CryptoUtils::GenerateHeaderProtectionKey( - prf, read_secret, handshaker_delegate_->parsed_version(), - decrypter->GetKeySize()); - } + CryptoUtils::SetKeyAndIV(prf, read_secret, + handshaker_delegate_->parsed_version(), + decrypter.get()); + header_protection_key.resize(decrypter->GetKeySize()); + CryptoUtils::GenerateHeaderProtectionKey( + prf, read_secret, handshaker_delegate_->parsed_version(), + absl::Span(header_protection_key)); decrypter->SetHeaderProtectionKey( absl::string_view(reinterpret_cast(header_protection_key.data()), header_protection_key.size())); @@ -372,29 +352,17 @@ TlsHandshaker::AdvanceKeysAndCreateCurrentOneRttDecrypter() { } const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl()); const EVP_MD* prf = Prf(cipher); - std::unique_ptr decrypter; - if (GetQuicReloadableFlag(quic_heapless_key_derivation)) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_heapless_key_derivation, 9, 10); - CryptoUtils::GenerateNextKeyPhaseSecret( - prf, handshaker_delegate_->parsed_version(), latest_read_secret_, - absl::Span(latest_read_secret_)); - CryptoUtils::GenerateNextKeyPhaseSecret( - prf, handshaker_delegate_->parsed_version(), latest_write_secret_, - absl::Span(latest_write_secret_)); - decrypter = QuicDecrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher)); - CryptoUtils::SetKeyAndIVHeapless(prf, latest_read_secret_, - handshaker_delegate_->parsed_version(), - decrypter.get()); - } else { - latest_read_secret_ = CryptoUtils::GenerateNextKeyPhaseSecret( - prf, handshaker_delegate_->parsed_version(), latest_read_secret_); - latest_write_secret_ = CryptoUtils::GenerateNextKeyPhaseSecret( - prf, handshaker_delegate_->parsed_version(), latest_write_secret_); - decrypter = QuicDecrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher)); - CryptoUtils::SetKeyAndIV(prf, latest_read_secret_, - handshaker_delegate_->parsed_version(), - decrypter.get()); - } + CryptoUtils::GenerateNextKeyPhaseSecret( + prf, handshaker_delegate_->parsed_version(), latest_read_secret_, + absl::Span(latest_read_secret_)); + CryptoUtils::GenerateNextKeyPhaseSecret( + prf, handshaker_delegate_->parsed_version(), latest_write_secret_, + absl::Span(latest_write_secret_)); + std::unique_ptr decrypter = + QuicDecrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher)); + CryptoUtils::SetKeyAndIV(prf, latest_read_secret_, + handshaker_delegate_->parsed_version(), + decrypter.get()); decrypter->SetHeaderProtectionKey(absl::string_view( reinterpret_cast(one_rtt_read_header_protection_key_.data()), @@ -414,16 +382,9 @@ std::unique_ptr TlsHandshaker::CreateCurrentOneRttEncrypter() { const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl()); std::unique_ptr encrypter = QuicEncrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher)); - if (GetQuicReloadableFlag(quic_heapless_key_derivation)) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_heapless_key_derivation, 10, 10); - CryptoUtils::SetKeyAndIVHeapless(Prf(cipher), latest_write_secret_, - handshaker_delegate_->parsed_version(), - encrypter.get()); - } else { - CryptoUtils::SetKeyAndIV(Prf(cipher), latest_write_secret_, - handshaker_delegate_->parsed_version(), - encrypter.get()); - } + CryptoUtils::SetKeyAndIV(Prf(cipher), latest_write_secret_, + handshaker_delegate_->parsed_version(), + encrypter.get()); encrypter->SetHeaderProtectionKey(absl::string_view( reinterpret_cast(one_rtt_write_header_protection_key_.data()), one_rtt_write_header_protection_key_.size())); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/web_transport_stats.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/web_transport_stats.cc index 15797b29ba..302da2e163 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/web_transport_stats.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/web_transport_stats.cc @@ -27,11 +27,18 @@ webtransport::SessionStats WebTransportStatsForQuicSession( result.min_rtt = rtt_stats->min_rtt().ToAbsl(); result.smoothed_rtt = rtt_stats->smoothed_rtt().ToAbsl(); result.rtt_variation = rtt_stats->mean_deviation().ToAbsl(); - result.estimated_send_rate_bps = session.connection() - ->sent_packet_manager() - .BandwidthEstimate() - .ToBitsPerSecond(); result.datagram_stats = WebTransportDatagramStatsForQuicSession(session); + + // "This estimate excludes any framing overhead and represents the rate at + // which an application payload might be sent." + // https://w3c.github.io/webtransport/#web-transport-connection-stats + float adjustment = + 1.0f - session.connection()->sent_packet_manager().GetOverheadEstimate(); + result.estimated_send_rate_bps = adjustment * session.connection() + ->sent_packet_manager() + .BandwidthEstimate() + .ToBitsPerSecond(); + return result; } 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 442ce58c46..0bd8eecd8e 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 @@ -79,6 +79,11 @@ DEFINE_QUICHE_COMMAND_LINE_FLAG( "send the IP litteral in the CONNECT request. If set to false, " "masque_client send the hostname in the CONNECT request."); +DEFINE_QUICHE_COMMAND_LINE_FLAG( + bool, bind_use_uncompressed_context, false, + "If set, an uncompressed context will be created for the client." + "Otherwise, a compressed context will be requested."); + DEFINE_QUICHE_COMMAND_LINE_FLAG( bool, bring_up_tap, false, "If set to true, no URLs need to be specified and instead a TAP device " @@ -356,6 +361,9 @@ int RunMasqueClient(int argc, char* argv[]) { } else if (mode_string == "connectethernet" || mode_string == "connect-ethernet") { masque_mode = MasqueMode::kConnectEthernet; + } else if (mode_string == "connectudpbind" || + mode_string == "connect-udp-bind") { + masque_mode = MasqueMode::kConnectUdpBind; } else { QUIC_LOG(ERROR) << "Invalid masque_mode \"" << mode_string << "\""; return 1; @@ -412,6 +420,7 @@ int RunMasqueClient(int argc, char* argv[]) { masque_client = MasqueClient::Create(uri_template, masque_mode, event_loop.get(), std::move(proof_verifier)); + } else { masque_client = tools::CreateAndConnectMasqueEncapsulatedClient( masque_clients.back().get(), masque_mode, event_loop.get(), @@ -462,6 +471,13 @@ int RunMasqueClient(int argc, char* argv[]) { QUICHE_NOTREACHED(); } + if (masque_mode == MasqueMode::kConnectUdpBind) { + bool uncompressed_context = + quiche::GetQuicheCommandLineFlag(FLAGS_bind_use_uncompressed_context); + masque_client->masque_client_session()->set_bind_use_uncompressed_context( + uncompressed_context); + } + for (size_t i = 1; i < urls.size(); ++i) { if (absl::StartsWith(urls[i], "/")) { QuicSpdyClientStream* stream = @@ -472,11 +488,15 @@ int RunMasqueClient(int argc, char* argv[]) { // Print the response body to stdout. std::cout << std::endl << stream->data() << std::endl; } else { + // For bind, DNS has to be done on client in the encapsulated client. std::unique_ptr encapsulated_client = tools::CreateAndConnectMasqueEncapsulatedClient( masque_client.get(), masque_mode, event_loop.get(), urls[i], disable_certificate_verification, address_family_for_lookup, - dns_on_client, /*is_also_underlying=*/false); + /*dns_on_client=*/dns_on_client || + (masque_mode == MasqueMode::kConnectUdpBind), + /*is_also_underlying=*/false); + if (!encapsulated_client || !tools::SendRequestOnMasqueEncapsulatedClient( *encapsulated_client, urls[i])) { return 1; 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 6d3d74e669..dbef24e6d1 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 @@ -15,6 +15,7 @@ #include "absl/container/flat_hash_set.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" +#include "absl/strings/str_replace.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "openssl/curve25519.h" @@ -23,6 +24,7 @@ #include "quiche/quic/core/http/http_frames.h" #include "quiche/quic/core/http/quic_spdy_client_session.h" #include "quiche/quic/core/http/quic_spdy_client_stream.h" +#include "quiche/quic/core/http/quic_spdy_stream.h" #include "quiche/quic/core/quic_config.h" #include "quiche/quic/core/quic_connection.h" #include "quiche/quic/core/quic_data_reader.h" @@ -54,9 +56,10 @@ namespace { using ::quiche::AddressAssignCapsule; using ::quiche::AddressRequestCapsule; using ::quiche::RouteAdvertisementCapsule; +using ContextId = MasqueClientSession::ContextId; -constexpr uint64_t kConnectIpPayloadContextId = 0; -constexpr uint64_t kConnectEthernetPayloadContextId = 0; +constexpr MasqueClientSession::ContextId kConnectIpPayloadContextId = 0; +constexpr MasqueClientSession::ContextId kConnectEthernetPayloadContextId = 0; } // namespace MasqueClientSession::MasqueClientSession( @@ -93,25 +96,36 @@ void MasqueClientSession::OnMessageLost(QuicMessageId message_id) { QUIC_DVLOG(1) << "We believe DATAGRAM frame " << message_id << " was lost"; } -const MasqueClientSession::ConnectUdpClientState* +MasqueClientSession::ConnectUdpClientState* MasqueClientSession::GetOrCreateConnectUdpClientState( const QuicSocketAddress& target_server_address, EncapsulatedClientSession* encapsulated_client_session) { - for (const ConnectUdpClientState& client_state : connect_udp_client_states_) { + for (ConnectUdpClientState& client_state : connect_udp_client_states_) { if (client_state.target_server_address() == target_server_address && client_state.encapsulated_client_session() == - encapsulated_client_session) { + encapsulated_client_session && + IsBind() == client_state.is_bind()) { // Found existing CONNECT-UDP request. return &client_state; } } + + QUIC_DLOG(INFO) << "No existing state non bind state found, create one"; // No CONNECT-UDP request found, create a new one. - std::string target_host; - auto it = fake_addresses_.find(target_server_address.host().ToPackedString()); - if (it != fake_addresses_.end()) { - target_host = it->second; + std::string target_host, target_port; + + if (IsBind()) { + target_host = "*"; + target_port = "*"; } else { - target_host = target_server_address.host().ToString(); + auto it = + fake_addresses_.find(target_server_address.host().ToPackedString()); + if (it != fake_addresses_.end()) { + target_host = it->second; + } else { + target_host = target_server_address.host().ToString(); + } + target_port = absl::StrCat(target_server_address.port()); } QUICHE_CHECK(!target_host.empty()); @@ -132,8 +146,17 @@ MasqueClientSession::GetOrCreateConnectUdpClientState( parsed_uri_template.query.len)); } absl::flat_hash_map parameters; - parameters["target_host"] = target_host; - parameters["target_port"] = absl::StrCat(target_server_address.port()); + // TODO(abhisinghx): Remove this hack. + // ExpandURITemplate, does not encode * as %2A. + // Therefore to meet the spec, we need to do it manually. + if (IsBind()) { + parameters["target_host"] = "HackyStringForBind"; + parameters["target_port"] = "HackyStringForBind"; + } else { + parameters["target_host"] = target_host; + parameters["target_port"] = target_port; + } + std::string expanded_path; absl::flat_hash_set vars_found; bool expanded = @@ -145,6 +168,10 @@ MasqueClientSession::GetOrCreateConnectUdpClientState( << target_server_address.port(); return nullptr; } + if (IsBind()) { + expanded_path = + absl::StrReplaceAll(expanded_path, {{"HackyStringForBind", "%2A"}}); + } url::Component expanded_path_component(0, expanded_path.length()); url::RawCanonOutput<1024> canonicalized_path_output; @@ -185,6 +212,9 @@ MasqueClientSession::GetOrCreateConnectUdpClientState( headers[":scheme"] = scheme; headers[":authority"] = authority; headers[":path"] = canonicalized_path; + if (IsBind()) { + headers["connect-udp-bind"] = "?1"; + } AddAdditionalHeaders(headers, url); QUIC_DVLOG(1) << "Sending request headers: " << headers.DebugString(); size_t bytes_sent = @@ -196,6 +226,10 @@ MasqueClientSession::GetOrCreateConnectUdpClientState( connect_udp_client_states_.push_back(ConnectUdpClientState( stream, encapsulated_client_session, this, target_server_address)); + if (IsBind()) { + QUIC_DLOG(INFO) << "Creating bind state"; + connect_udp_client_states_.back().set_is_bind(true); + } return &connect_udp_client_states_.back(); } @@ -362,6 +396,25 @@ void MasqueClientSession::SendEthernetFrame( << MessageStatusToString(message_status); } +void MasqueClientSession::SendConnectUdpBindPacket( + absl::string_view packet, const QuicSocketAddress& target_server_address, + EncapsulatedClientSession* encapsulated_client_session) { + QUICHE_DCHECK(masque_mode_ == MasqueMode::kConnectUdpBind); + ConnectUdpClientState* connect_udp = GetOrCreateConnectUdpClientState( + QuicSocketAddress(), encapsulated_client_session); + std::optional bind_packet = connect_udp->PrepareBindPacket( + packet, target_server_address, bind_use_uncompressed_context_); + if (!bind_packet.has_value()) { + QUIC_DLOG(ERROR) << "Failed to prepare bind packet"; + return; + } + QUIC_DVLOG(1) << "Sending bind packet: " << bind_packet.value() + << " of length " << bind_packet.value().length() << " to " + << target_server_address; + + SendHttp3Datagram(connect_udp->stream()->id(), bind_packet.value()); +} + void MasqueClientSession::SendPacket( absl::string_view packet, const QuicSocketAddress& target_server_address, EncapsulatedClientSession* encapsulated_client_session) { @@ -371,6 +424,10 @@ void MasqueClientSession::SendPacket( QUIC_DLOG(ERROR) << "Failed to create CONNECT-UDP request"; return; } + if (masque_mode_ == MasqueMode::kConnectUdpBind) { + QUIC_LOG(ERROR) << "Should not be called in CONNECT-UDP Bind mode"; + return; + } std::string http_payload; http_payload.resize(1 + packet.size()); @@ -388,6 +445,18 @@ void MasqueClientSession::SendPacket( << quiche::QuicheTextUtils::HexDump(http_payload); } +// Send Capsule for CONNECT-UDP Bind. +void MasqueClientSession::SendBindCapsule( + const quiche::Capsule& capsule, + EncapsulatedClientSession* encapsulated_client_session) { + for (auto& state : connect_udp_client_states_) { + if (state.is_bind() && + state.encapsulated_client_session() == encapsulated_client_session) { + state.stream()->WriteCapsule(capsule); + } + } +} + void MasqueClientSession::CloseConnectUdpStream( EncapsulatedClientSession* encapsulated_client_session) { for (auto it = connect_udp_client_states_.begin(); @@ -525,11 +594,17 @@ MasqueClientSession::ConnectUdpClientState::ConnectUdpClientState( target_server_address_(target_server_address) { QUICHE_DCHECK_NE(masque_session_, nullptr); this->stream()->RegisterHttp3DatagramVisitor(this); + if (masque_session->IsBind()) { + this->stream()->RegisterConnectUdpBindVisitor(this); + } } MasqueClientSession::ConnectUdpClientState::~ConnectUdpClientState() { if (stream() != nullptr) { stream()->UnregisterHttp3DatagramVisitor(); + if (masque_session_->IsBind()) { + this->stream()->UnregisterConnectUdpBindVisitor(); + } } } @@ -546,26 +621,79 @@ MasqueClientSession::ConnectUdpClientState::operator=( masque_session_ = other.masque_session_; target_server_address_ = other.target_server_address_; other.stream_ = nullptr; + other.is_bind_ = is_bind_; + other.bind_context_ip_map_ = std::move(bind_context_ip_map_); if (stream() != nullptr) { stream()->ReplaceHttp3DatagramVisitor(this); + if (masque_session_->IsBind()) { + stream()->ReplaceConnectUdpBindVisitor(this); + } } return *this; } void MasqueClientSession::ConnectUdpClientState::OnHttp3Datagram( QuicStreamId stream_id, absl::string_view payload) { + QUIC_DVLOG(1) << "Received HTTP Datagram of length " << payload.size(); QUICHE_DCHECK_EQ(stream_id, stream()->id()); QuicDataReader reader(payload); - uint64_t context_id; - if (!reader.ReadVarInt62(&context_id)) { - QUIC_DLOG(ERROR) << "Failed to read context ID"; - return; - } - if (context_id != 0) { - QUIC_DLOG(ERROR) << "Ignoring HTTP Datagram with unexpected context ID " - << context_id; - return; + if (!is_bind_) { + ContextId context_id; + if (!reader.ReadVarInt62(&context_id)) { + QUIC_DLOG(ERROR) << "Failed to read context ID"; + return; + } + if (context_id != 0) { + QUIC_DLOG(ERROR) << "Ignoring HTTP Datagram with unexpected context ID " + << context_id; + return; + } + } else { + ContextId context_id; + QuicSocketAddress target_address; + if (!reader.ReadVarInt62(&context_id)) { + QUIC_DLOG(ERROR) << "Failed to read context ID"; + return; + } + if (!bind_context_ip_map_.contains(context_id)) { + // Non existent context id. + QUIC_DLOG(ERROR) << "Ignoring HTTP Datagram with non existent context id " + << context_id; + // Drop the packet. + return; + } + if (bind_context_ip_map_[context_id] == quiche::QuicheSocketAddress()) { + // Uncompressed Context. + // Parse IP and port. + uint8_t ip_version; + if (!reader.ReadUInt8(&ip_version)) { + QUIC_DLOG(ERROR) << "Failed to read IP version"; + return; + } + auto address_size = ip_version == 4 + ? quiche::QuicheIpAddress::kIPv4AddressSize + : quiche::QuicheIpAddress::kIPv6AddressSize; + absl::string_view ip_address_bytes; + if (!reader.ReadStringPiece(&ip_address_bytes, address_size)) { + QUIC_DLOG(ERROR) << "Failed to read IP address"; + return; + } + quiche::QuicheIpAddress ip_address; + if (!ip_address.FromPackedString(ip_address_bytes.data(), address_size)) { + QUIC_DLOG(ERROR) << "Failed to parse IP address"; + return; + } + uint16_t port; + if (!reader.ReadUInt16(&port)) { + QUIC_DLOG(ERROR) << "Failed to read port"; + return; + } + target_address = QuicSocketAddress(ip_address, port); + } else { + target_address = bind_context_ip_map_[context_id]; + } } + absl::string_view http_payload = reader.ReadRemainingPayload(); encapsulated_client_session_->ProcessPacket(http_payload, target_server_address_); @@ -573,6 +701,177 @@ void MasqueClientSession::ConnectUdpClientState::OnHttp3Datagram( << " bytes to connection for stream ID " << stream_id; } +ContextId MasqueClientSession::ConnectUdpClientState::CreateCompressedContext( + const QuicSocketAddress& target_address) { + bind_context_ip_map_[next_available_context_id_] = target_address; + quiche::Capsule capsule = quiche::Capsule::CompressionAssign(); + capsule.compression_assign_capsule().context_id = next_available_context_id_; + capsule.compression_assign_capsule().ip_address_port = target_address; + + masque_session_->SendBindCapsule(capsule, encapsulated_client_session_); + // TODO(abhisinghx): Verify Acks Before using it + return AllocateContextId(); +} + +ContextId +MasqueClientSession::ConnectUdpClientState::CreateUncompressedContext() { + bind_context_ip_map_[next_available_context_id_] = + quiche::QuicheSocketAddress(); + quiche::Capsule capsule = quiche::Capsule::CompressionAssign(); + capsule.compression_assign_capsule().context_id = next_available_context_id_; + capsule.compression_assign_capsule().ip_address_port = + quiche::QuicheSocketAddress(); + QUIC_DLOG(INFO) << "Requesting open context " << next_available_context_id_; + masque_session_->SendBindCapsule(capsule, encapsulated_client_session_); + // TODO(abhisinghx): Verify capsule ack before using it. + // It is fine to pre-emptively send UDP packets. + return AllocateContextId(); +} + +ContextId MasqueClientSession::ConnectUdpClientState::AllocateContextId() { + next_available_context_id_ += 2; + return next_available_context_id_ - 2; +} + +void MasqueClientSession::ConnectUdpClientState::CloseContext( + ContextId context_id) { + bind_context_ip_map_.erase(context_id); + quiche::Capsule capsule = quiche::Capsule::CompressionClose(); + capsule.compression_close_capsule().context_id = context_id; + QUIC_DLOG(INFO) << "Closing context " << context_id; + masque_session_->SendBindCapsule(capsule, encapsulated_client_session_); +} + +bool MasqueClientSession::ConnectUdpClientState::OnCompressionAssignCapsule( + const quiche::CompressionAssignCapsule& capsule) { + if (!is_bind_) { + QUIC_DLOG(ERROR) << "Received CompressionAssignCapsule " + << capsule.ToString() << " when bind is not set"; + return false; + } + QUIC_DLOG(INFO) << "CompressionAssignCapsule received: " + << capsule.ToString(); + if (!bind_context_ip_map_.contains(capsule.context_id)) { + // Server is asking to create a new context. + if (capsule.ip_address_port == quiche::QuicheSocketAddress()) { + // Server is not allowed to create open context. + QUIC_DLOG(ERROR) << "Server is not allowed to create open context"; + return false; + } else { + // Compressed context requested by server. + if (capsule.context_id % 2 == 0) { + // Even contexts are client-allocated. + QUIC_DLOG(ERROR) << "Server is not allowed to create even contexts"; + return false; + } + bind_context_ip_map_[capsule.context_id] = capsule.ip_address_port; + // Send acknowledgement. + + quiche::Capsule to_send = quiche::Capsule::CompressionAssign(); + to_send.compression_assign_capsule() = capsule; + masque_session_->SendBindCapsule(to_send, encapsulated_client_session_); + return true; + } + } else if (bind_context_ip_map_[capsule.context_id] != + capsule.ip_address_port) { + // Context already exists but the target address is different. + QUIC_DLOG(ERROR) << "Context already exists with different target address " + << bind_context_ip_map_[capsule.context_id] << " and " + << capsule.ip_address_port; + return false; + } else { + // This is an ack of client's request, ignore it. + QUIC_DLOG(INFO) << "Ignoring ack of client's request"; + return true; + } +} + +bool MasqueClientSession::ConnectUdpClientState::OnCompressionCloseCapsule( + const quiche::CompressionCloseCapsule& capsule) { + if (!is_bind_) { + QUIC_DLOG(ERROR) << "Received CompressionCloseCapsule " + << capsule.ToString() << " when bind is not set"; + return false; + } + QUIC_DLOG(INFO) << "CompressionCloseCapsule received: " << capsule.ToString(); + // If we have this context id in the map, we can close it and send ack. + if (bind_context_ip_map_.contains(capsule.context_id)) { + CloseContext(capsule.context_id); + } + return true; +} + +std::optional +MasqueClientSession::ConnectUdpClientState::GetContextForAddress( + const QuicSocketAddress& target_server_address) { + std::optional uncompressed_context_id; + for (const auto& [context_id, address] : bind_context_ip_map_) { + if (address == target_server_address) { + return context_id; + } + if (address == quiche::QuicheSocketAddress()) { + uncompressed_context_id = context_id; + } + } + return uncompressed_context_id; +} + +std::optional +MasqueClientSession::ConnectUdpClientState::PrepareBindPacket( + absl::string_view packet, const QuicSocketAddress& target_address, + bool use_uncompressed_context) { + std::string payload_out; + // Find existing or open context for this address. + std::optional context_id_opt = + GetContextForAddress(target_address); + ContextId context_id; + if (!context_id_opt.has_value()) { + // No context exists for this address, create a new compressed context. + context_id = use_uncompressed_context + ? CreateUncompressedContext() + : CreateCompressedContext(target_address); + } else { + context_id = context_id_opt.value(); + } + size_t total_size = + quiche::QuicheDataWriter::GetVarInt62Len(context_id) + packet.size(); + if (bind_context_ip_map_[context_id] == target_address) { + // No need to append target info, compress it. + payload_out.resize(total_size); + QuicDataWriter writer(total_size, payload_out.data()); + if (!writer.WriteVarInt62(context_id)) { + QUIC_DLOG(ERROR) << "Failed to write compressed bind packet context id " + << context_id; + return std::nullopt; + } + if (!writer.WriteStringPiece(packet)) { + QUIC_DLOG(ERROR) + << "Failed to write compressed bind packet payload for context id " + << context_id; + return std::nullopt; + } + } else { + // Append target info. + total_size += (sizeof(uint8_t) // Ip version. + + target_address.host().ToPackedString().size() // Ip addr. + + sizeof(uint16_t)); // Port. + payload_out.resize(total_size); + QuicDataWriter writer(total_size, payload_out.data()); + if (!writer.WriteVarInt62(context_id) || + !writer.WriteUInt8( + target_address.host().AddressFamilyToInt() == AF_INET ? 4 : 6) || + !writer.WriteStringPiece(target_address.host().ToPackedString()) || + !writer.WriteUInt16(target_address.port()) || + !writer.WriteStringPiece(packet)) { + QUIC_DLOG(ERROR) + << "Failed to write uncompressed bind packet for context id " + << context_id; + return std::nullopt; + } + } + return payload_out; +} + MasqueClientSession::ConnectIpClientState::ConnectIpClientState( QuicSpdyClientStream* stream, EncapsulatedIpSession* encapsulated_ip_session, @@ -615,7 +914,7 @@ void MasqueClientSession::ConnectIpClientState::OnHttp3Datagram( QuicStreamId stream_id, absl::string_view payload) { QUICHE_DCHECK_EQ(stream_id, stream()->id()); QuicDataReader reader(payload); - uint64_t context_id; + ContextId context_id; if (!reader.ReadVarInt62(&context_id)) { QUIC_DLOG(ERROR) << "Failed to read context ID"; return; @@ -689,7 +988,7 @@ void MasqueClientSession::ConnectEthernetClientState::OnHttp3Datagram( QuicStreamId stream_id, absl::string_view payload) { QUICHE_DCHECK_EQ(stream_id, stream()->id()); QuicDataReader reader(payload); - uint64_t context_id; + ContextId context_id; if (!reader.ReadVarInt62(&context_id)) { QUIC_DLOG(ERROR) << "Failed to read context ID"; 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 4ea6939748..6c6fe36585 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 @@ -5,6 +5,7 @@ #ifndef QUICHE_QUIC_MASQUE_MASQUE_CLIENT_SESSION_H_ #define QUICHE_QUIC_MASQUE_MASQUE_CLIENT_SESSION_H_ +#include #include #include #include @@ -25,6 +26,7 @@ #include "quiche/quic/core/quic_versions.h" #include "quiche/quic/masque/masque_utils.h" #include "quiche/quic/platform/api/quic_export.h" +#include "quiche/quic/platform/api/quic_logging.h" #include "quiche/quic/platform/api/quic_socket_address.h" #include "quiche/quic/tools/quic_url.h" #include "quiche/common/capsule.h" @@ -41,6 +43,7 @@ namespace quic { class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession, public QuicSpdyStream::Visitor { public: + using ContextId = uint64_t; // Interface meant to be implemented by the owner of the // MasqueClientSession instance. class QUIC_NO_EXPORT Owner { @@ -140,6 +143,17 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession, const QuicSocketAddress& target_server_address, EncapsulatedClientSession* encapsulated_client_session); + // Send CONNECT-UDP-BIND packet, creating contexts if needed. + void SendConnectUdpBindPacket( + absl::string_view packet, const QuicSocketAddress& target_server_address, + EncapsulatedClientSession* encapsulated_client_session); + + // Request uncompressed context for CONNECT-UDP Bind. + void set_bind_use_uncompressed_context(bool use_uncompressed_context) { + QUICHE_DCHECK(masque_mode_ == MasqueMode::kConnectUdpBind); + bind_use_uncompressed_context_ = use_uncompressed_context; + } + // Send encapsulated IP packet. |packet| contains the IP header and payload. void SendIpPacket(absl::string_view packet, EncapsulatedIpSession* encapsulated_ip_session); @@ -192,7 +206,8 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession, private: // State that the MasqueClientSession keeps for each CONNECT-UDP request. class QUIC_NO_EXPORT ConnectUdpClientState - : public QuicSpdyStream::Http3DatagramVisitor { + : public QuicSpdyStream::Http3DatagramVisitor, + public QuicSpdyStream::ConnectUdpBindVisitor { public: // |stream| and |encapsulated_client_session| must be valid for the lifetime // of the ConnectUdpClientState. @@ -204,6 +219,9 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession, ~ConnectUdpClientState(); + void set_is_bind(bool is_bind) { is_bind_ = is_bind; } + bool is_bind() const { return is_bind_; } + // Disallow copy but allow move. ConnectUdpClientState(const ConnectUdpClientState&) = delete; ConnectUdpClientState(ConnectUdpClientState&&); @@ -217,18 +235,43 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession, const QuicSocketAddress& target_server_address() const { return target_server_address_; } - + void CloseContext(ContextId context_id); // From QuicSpdyStream::Http3DatagramVisitor. void OnHttp3Datagram(QuicStreamId stream_id, absl::string_view payload) override; void OnUnknownCapsule(QuicStreamId /*stream_id*/, const quiche::UnknownCapsule& /*capsule*/) override {} + // From QuicSpdyStream::ConnectUdpBindVisitor. + + bool OnCompressionAssignCapsule( + const quiche::CompressionAssignCapsule& capsule) override; + + bool OnCompressionCloseCapsule( + const quiche::CompressionCloseCapsule& capsule) override; + + ContextId AllocateContextId(); + + // Get the context id for the given address if it exists or if + // an uncompressed context exists. + std::optional GetContextForAddress( + const QuicSocketAddress& target_server_address); + ContextId CreateCompressedContext(const QuicSocketAddress& target_address); + ContextId CreateUncompressedContext(); + std::optional PrepareBindPacket( + absl::string_view packet, const QuicSocketAddress& target_address, + bool use_uncompressed_context); + private: QuicSpdyClientStream* stream_; // Unowned. EncapsulatedClientSession* encapsulated_client_session_; // Unowned. MasqueClientSession* masque_session_; // Unowned. QuicSocketAddress target_server_address_; + + ContextId next_available_context_id_ = 2; + absl::flat_hash_map bind_context_ip_map_ = {}; + + bool is_bind_ = false; }; // State that the MasqueClientSession keeps for each CONNECT-IP request. @@ -318,10 +361,16 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession, return HttpDatagramSupport::kRfc; } - const ConnectUdpClientState* GetOrCreateConnectUdpClientState( + // target_server_address should be set to empty + // to create state for bind. + ConnectUdpClientState* GetOrCreateConnectUdpClientState( const QuicSocketAddress& target_server_address, EncapsulatedClientSession* encapsulated_client_session); + // Send Capsule for CONNECT-UDP Bind. + void SendBindCapsule(const quiche::Capsule& capsule, + EncapsulatedClientSession* encapsulated_client_session); + const ConnectIpClientState* GetOrCreateConnectIpClientState( EncapsulatedIpSession* encapsulated_ip_session); @@ -332,13 +381,15 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession, void AddAdditionalHeaders(quiche::HttpHeaderBlock& headers, const QuicUrl& url); - MasqueMode masque_mode_; + bool IsBind() const { return masque_mode_ == MasqueMode::kConnectUdpBind; } + MasqueMode masque_mode_ = MasqueMode::kInvalid; std::string uri_template_; std::string additional_headers_; std::string concealed_auth_key_id_; std::string concealed_auth_private_key_; std::string concealed_auth_public_key_; std::list connect_udp_client_states_; + bool bind_use_uncompressed_context_ = false; std::list connect_ip_client_states_; std::list connect_ethernet_client_states_; // Maps fake addresses generated by GetFakeAddress() to their corresponding diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_encapsulated_client.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_encapsulated_client.cc index 78ff0873ae..f68f92e29c 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_encapsulated_client.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_encapsulated_client.cc @@ -199,8 +199,18 @@ class MasquePacketWriter : public QuicPacketWriter { packet, client_->masque_encapsulated_client_session()); } else { absl::string_view packet(buffer, buf_len); - client_->masque_client()->masque_client_session()->SendPacket( - packet, peer_address, client_->masque_encapsulated_client_session()); + if (client_->masque_client()->masque_mode() == + MasqueMode::kConnectUdpBind) { + client_->masque_client() + ->masque_client_session() + ->SendConnectUdpBindPacket( + packet, peer_address, + client_->masque_encapsulated_client_session()); + } else { + client_->masque_client()->masque_client_session()->SendPacket( + packet, peer_address, + client_->masque_encapsulated_client_session()); + } } return WriteResult(WRITE_STATUS_OK, buf_len); } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_ohttp_client_bin.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_ohttp_client_bin.cc index df2aca2429..f7185de821 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_ohttp_client_bin.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_ohttp_client_bin.cc @@ -165,7 +165,6 @@ class MasqueOhttpClient : public MasqueConnectionPool::Visitor { request.headers[":scheme"] = url.scheme(); request.headers[":authority"] = url.HostPort(); request.headers[":path"] = url.path(); - request.headers["host"] = url.HostPort(); request.headers["accept"] = "application/ohttp-keys"; request.headers["content-type"] = "application/ohttp-keys"; absl::StatusOr request_id = @@ -268,7 +267,6 @@ class MasqueOhttpClient : public MasqueConnectionPool::Visitor { request.headers[":scheme"] = relay_url_.scheme(); request.headers[":authority"] = relay_url_.HostPort(); request.headers[":path"] = relay_url_.path(); - request.headers["host"] = relay_url_.HostPort(); request.headers["content-type"] = "message/ohttp-req"; request.body = ohttp_request->EncapsulateAndSerialize(); absl::StatusOr request_id = 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 4b815d6356..d42df91c2f 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 @@ -740,7 +740,7 @@ bool MasqueServerSession::HandleConnectUdpSocketEvent( QuicSocketAddress expected_target_server_address = it->target_server_address(); - QUICHE_DCHECK(expected_target_server_address.IsInitialized()); + QUICHE_DCHECK(expected_target_server_address.IsInitialized() || is_bind); QUIC_DVLOG(1) << "Received readable event on fd " << fd << " (mask " << events << ") stream ID " << it->stream()->id() << (is_bind ? " (bind)" : "") << " server " @@ -775,12 +775,15 @@ bool MasqueServerSession::HandleConnectUdpSocketEvent( << "Missing peer address when reading from fd " << fd; continue; } - QuicSocketAddress peer_address = read_result.packet_info.peer_address(); + + // Normalize v6 mapped v4 to v4 if needed. + QuicSocketAddress peer_address = + read_result.packet_info.peer_address().Normalized(); ContextId bind_context_id = kInvalidContextId; bool use_uncompressed_context = false; if (is_bind) { - ContextId uncompressed_context = it->uncompressed_context_id(); + ContextId uncompressed_context = kInvalidContextId; ContextId matching_context = kInvalidContextId; // Now check if we either have a matching context or an uncompressed // context. @@ -790,6 +793,9 @@ bool MasqueServerSession::HandleConnectUdpSocketEvent( matching_context = context_address_pair.first; break; } + if (context_address_pair.second == quiche::QuicheSocketAddress()) { + uncompressed_context = context_address_pair.first; + } } if (matching_context != kInvalidContextId) { @@ -1021,8 +1027,7 @@ void MasqueServerSession::ConnectUdpServerState::OnHttp3Datagram( return; } else if (is_bind_) { auto it = bind_context_ip_map_.find(context_id); - if (it == bind_context_ip_map_.end() && - uncompressed_context_id_ != context_id) { + if (it == bind_context_ip_map_.end()) { QUIC_DLOG(ERROR) << "Context ID " << context_id << " from datagram not found"; return; @@ -1084,14 +1089,10 @@ void MasqueServerSession::ConnectUdpServerState::OnHttp3Datagram( bool MasqueServerSession::ConnectUdpServerState::OnCompressionAssignCapsule( const quiche::CompressionAssignCapsule& capsule) { - if (bind_context_ip_map_.contains(capsule.context_id) || - uncompressed_context_id_ == capsule.context_id) { + if (bind_context_ip_map_.contains(capsule.context_id)) { QUIC_DLOG(ERROR) << "Context ID " << capsule.context_id << " from Compression Assign already exists"; return false; - } else if (capsule.ip_address_port.host().address_family() == - IpAddressFamily::IP_UNSPEC) { - uncompressed_context_id_ = capsule.context_id; } else { bind_context_ip_map_[capsule.context_id] = capsule.ip_address_port; } @@ -1111,8 +1112,6 @@ bool MasqueServerSession::ConnectUdpServerState::OnCompressionCloseCapsule( auto it = bind_context_ip_map_.find(capsule.context_id); if (it != bind_context_ip_map_.end()) { bind_context_ip_map_.erase(it); - } else if (uncompressed_context_id_ == capsule.context_id) { - uncompressed_context_id_ = kInvalidContextId; } else { QUIC_DLOG(ERROR) << "Context ID " << capsule.context_id << " from Compression Close not found"; 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 5e8dc703e3..1091fdb96c 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 @@ -141,9 +141,6 @@ class QUIC_NO_EXPORT MasqueServerSession bind_context_ip_map() { return bind_context_ip_map_; } - ContextId uncompressed_context_id() const { - return uncompressed_context_id_; - } private: QuicSpdyStream* stream_; @@ -155,7 +152,6 @@ class QUIC_NO_EXPORT MasqueServerSession // CONNECT-UDP-BIND context id to ip:port map. absl::flat_hash_map bind_context_ip_map_ = {}; - ContextId uncompressed_context_id_ = kInvalidContextId; // TODO(abhisinghx): Add Server's ability to request compression // or close contexts. }; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_tcp_client_bin.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_tcp_client_bin.cc index 3f9d77457b..fc5769321b 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_tcp_client_bin.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_tcp_client_bin.cc @@ -476,7 +476,6 @@ class MasqueTlsTcpClientHandler : public ConnectingClientSocket::AsyncVisitor, headers[":scheme"] = url_.scheme(); headers[":authority"] = url_.HostPort(); headers[":path"] = url_.path(); - headers["host"] = url_.HostPort(); stream_id_ = h2_connection_->SendRequest(headers, std::string()); h2_connection_->AttemptToSend(); if (stream_id_ >= 0) { 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 6c4f7f134a..875b93502f 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 @@ -60,6 +60,8 @@ std::string MasqueModeToString(MasqueMode masque_mode) { return "CONNECT-IP"; case MasqueMode::kConnectEthernet: return "CONNECT-ETHERNET"; + case MasqueMode::kConnectUdpBind: + return "CONNECT-UDP-BIND"; } return absl::StrCat("Unknown(", static_cast(masque_mode), ")"); } 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 09705d5488..7b404903a9 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 @@ -42,6 +42,12 @@ enum class MasqueMode : uint8_t { 3, // ConnectEthernet mode uses MASQUE HTTP CONNECT-ETHERNET. // // This mode also allows unauthenticated clients. + kConnectUdpBind = 4, + // Bind a UDP socket on the proxy and forward all packets to the client. + // This mode uses MASQUE HTTP CONNECT-UDP-BIND. + // We define a custom handler for this. Our default handler simply echoes + // back the UDP Payload. + // }; QUIC_NO_EXPORT std::string MasqueModeToString(MasqueMode masque_mode); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_bitrate_adjuster.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_bitrate_adjuster.cc index 0326a4430f..fbcc224780 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_bitrate_adjuster.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_bitrate_adjuster.cc @@ -4,11 +4,13 @@ #include "quiche/quic/moqt/moqt_bitrate_adjuster.h" -#include #include +#include +#include #include "quiche/quic/core/quic_bandwidth.h" #include "quiche/quic/core/quic_time.h" +#include "quiche/common/platform/api/quiche_bug_tracker.h" #include "quiche/common/platform/api/quiche_logging.h" #include "quiche/web_transport/web_transport.h" @@ -20,26 +22,29 @@ using ::quic::QuicBandwidth; using ::quic::QuicTime; using ::quic::QuicTimeDelta; -// Whenever adjusting bitrate down, it is set to `kTargetBitrateMultiplier * -// bw`, where `bw` is typically windowed max bandwidth reported by BBR. The -// current value selected is a bit arbitrary; ideally, we would adjust down to -// the application data goodput (i.e. goodput excluding all of the framing -// overhead), but that would either require us knowing how to compute the -// framing overhead correctly, or implementing our own application-level goodput -// monitoring. -constexpr float kTargetBitrateMultiplier = 0.9f; - -// Avoid re-adjusting bitrate within N RTTs after adjusting it. Here, on a -// typical 20ms connection, 40 RTTs is 800ms. Cap the limit at 3000ms. -constexpr float kMinTimeBetweenAdjustmentsInRtts = 40; -constexpr QuicTimeDelta kMaxTimeBetweenAdjustments = - QuicTimeDelta::FromSeconds(3); - } // namespace +void MoqtBitrateAdjuster::Start() { + if (start_time_.IsInitialized()) { + QUICHE_BUG(MoqtBitrateAdjuster_double_init) + << "MoqtBitrateAdjuster::Start() called more than once."; + return; + } + start_time_ = clock_->Now(); +} + void MoqtBitrateAdjuster::OnObjectAckReceived( uint64_t /*group_id*/, uint64_t /*object_id*/, QuicTimeDelta delta_from_deadline) { + if (!start_time_.IsInitialized()) { + return; + } + + const QuicTime earliest_action_time = start_time_ + parameters_.initial_delay; + if (clock_->Now() < earliest_action_time) { + return; + } + if (delta_from_deadline < QuicTimeDelta::Zero()) { // While adjusting down upon the first sign of packets getting late might // seem aggressive, note that: @@ -54,37 +59,49 @@ void MoqtBitrateAdjuster::OnObjectAckReceived( void MoqtBitrateAdjuster::AttemptAdjustingDown() { webtransport::SessionStats stats = session_->GetSessionStats(); - - // Wait for a while after doing an adjustment. There are non-trivial costs to - // switching, so we should rate limit adjustments. - QuicTimeDelta adjustment_delay = - QuicTimeDelta(stats.smoothed_rtt * kMinTimeBetweenAdjustmentsInRtts); - adjustment_delay = std::min(adjustment_delay, kMaxTimeBetweenAdjustments); - QuicTime now = clock_->ApproximateNow(); - if (now - last_adjustment_time_ < adjustment_delay) { - return; - } - - // Only adjust downwards. QuicBandwidth target_bandwidth = - kTargetBitrateMultiplier * + parameters_.target_bitrate_multiplier_down * QuicBandwidth::FromBitsPerSecond(stats.estimated_send_rate_bps); - QuicBandwidth current_bandwidth = adjustable_->GetCurrentBitrate(); - if (current_bandwidth <= target_bandwidth) { - return; - } - - QUICHE_DLOG(INFO) << "Adjusting the bitrate from " << current_bandwidth - << " to " << target_bandwidth; - bool success = adjustable_->AdjustBitrate(target_bandwidth); - if (success) { - last_adjustment_time_ = now; - } + QUICHE_DLOG(INFO) << "Adjusting the bitrate down to " << target_bandwidth; + adjustable_->ConsiderAdjustingBitrate(target_bandwidth, + BitrateAdjustmentType::kDown); } -void MoqtBitrateAdjuster::OnObjectAckSupportKnown(bool supported) { - QUICHE_DLOG_IF(WARNING, !supported) - << "OBJECT_ACK not supported; bitrate adjustments will not work."; +void MoqtBitrateAdjuster::OnObjectAckSupportKnown( + std::optional time_window) { + if (!time_window.has_value() || *time_window <= QuicTimeDelta::Zero()) { + QUICHE_DLOG(WARNING) + << "OBJECT_ACK not supported; bitrate adjustments will not work."; + return; + } + time_window_ = *time_window; + Start(); +} + +bool ShouldIgnoreBitrateAdjustment(quic::QuicBandwidth new_bitrate, + BitrateAdjustmentType type, + quic::QuicBandwidth old_bitrate, + float min_change) { + const float min_change_bps = old_bitrate.ToBitsPerSecond() * min_change; + const float change_bps = + new_bitrate.ToBitsPerSecond() - old_bitrate.ToBitsPerSecond(); + if (std::abs(change_bps) < min_change_bps) { + return true; + } + + switch (type) { + case moqt::BitrateAdjustmentType::kDown: + if (new_bitrate >= old_bitrate) { + return true; + } + break; + case moqt::BitrateAdjustmentType::kUp: + if (old_bitrate >= new_bitrate) { + return true; + } + break; + } + return false; } } // namespace moqt diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_bitrate_adjuster.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_bitrate_adjuster.h index 0075c51135..135373a8f8 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_bitrate_adjuster.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_bitrate_adjuster.h @@ -6,6 +6,7 @@ #define QUICHE_QUIC_MOQT_MOQT_BITRATE_ADJUSTER_H_ #include +#include #include "quiche/quic/core/quic_bandwidth.h" #include "quiche/quic/core/quic_clock.h" @@ -15,16 +16,48 @@ namespace moqt { +// Indicates the type of new bitrate estimate. +enum class BitrateAdjustmentType { + // Indicates that the sender is sending too much data. + kDown, + + // Indicates that the sender should attempt to increase the amount of data + // sent. + kUp, +}; + // A sender that can potentially have its outgoing bitrate adjusted. class BitrateAdjustable { public: virtual ~BitrateAdjustable() {} // Returns the currently used bitrate. + // TODO(vasilvv): we should not depend on this value long-term, since the + // self-reported bitrate is not reliable in most real encoders. virtual quic::QuicBandwidth GetCurrentBitrate() const = 0; - // Adjusts the bitrate to a new target. Returns true if the adjustment was - // successful. - virtual bool AdjustBitrate(quic::QuicBandwidth bandwidth) = 0; + + // Returns true if the sender could make use of more bandwidth than it is + // currently sending at. + virtual bool CouldUseExtraBandwidth() = 0; + + // Notifies the sender that it should consider increasing or decreasing its + // bandwidth. `bandwidth` is the estimate of bandwidth available to the + // application. + virtual void ConsiderAdjustingBitrate(quic::QuicBandwidth bandwidth, + BitrateAdjustmentType type) = 0; +}; + +// Parameters (mostly magic numbers) that determine behavior of +// MoqtBitrateAdjuster. +struct MoqtBitrateAdjusterParameters { + // When bitrate is adjusted down, multiply the congestion controller estimate + // by this factor. This should be less than 1, since congestion controller + // estimate tends to be overly optimistic in practice. + float target_bitrate_multiplier_down = 0.95f; + + // Do not perform any updates within `initial_delay` after the connection + // start. + quic::QuicTimeDelta initial_delay = quic::QuicTimeDelta::FromSeconds(2); }; // MoqtBitrateAdjuster monitors the progress of delivery for a single track, and @@ -34,26 +67,37 @@ class MoqtBitrateAdjuster : public MoqtPublishingMonitorInterface { MoqtBitrateAdjuster(const quic::QuicClock* clock, webtransport::Session* session, BitrateAdjustable* adjustable) - : clock_(clock), - session_(session), - adjustable_(adjustable), - last_adjustment_time_(clock->ApproximateNow()) {} + : clock_(clock), session_(session), adjustable_(adjustable) {} // MoqtPublishingMonitorInterface implementation. - void OnObjectAckSupportKnown(bool supported) override; + void OnObjectAckSupportKnown( + std::optional time_window) override; void OnObjectAckReceived(uint64_t group_id, uint64_t object_id, quic::QuicTimeDelta delta_from_deadline) override; private: + void Start(); + // Attempts adjusting the bitrate down. void AttemptAdjustingDown(); const quic::QuicClock* clock_; // Not owned. webtransport::Session* session_; // Not owned. BitrateAdjustable* adjustable_; // Not owned. - quic::QuicTime last_adjustment_time_; + MoqtBitrateAdjusterParameters parameters_; + quic::QuicTime start_time_ = quic::QuicTime::Zero(); + quic::QuicTimeDelta time_window_ = quic::QuicTimeDelta::Zero(); }; +// Given a suggestion to change bitrate `old_bitrate` to `new_bitrate` with the +// specified adjustment type, returns true if the change should be ignored. +// `min_change` is the threshold below which the change should be ignored, +// specified as a fraction of old bitrate. +bool ShouldIgnoreBitrateAdjustment(quic::QuicBandwidth new_bitrate, + BitrateAdjustmentType type, + quic::QuicBandwidth old_bitrate, + float min_change); + } // namespace moqt #endif // QUICHE_QUIC_MOQT_MOQT_BITRATE_ADJUSTER_H_ 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 index 33294bbf5f..df71f1c345 100644 --- 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 @@ -13,15 +13,12 @@ namespace moqt { moqt::PublishedObject CachedObjectToPublishedObject( const CachedObject& object) { PublishedObject result; - result.sequence = object.sequence; - result.status = object.status; - result.publisher_priority = object.publisher_priority; + result.metadata = object.metadata; if (object.payload != nullptr && !object.payload->empty()) { result.payload = quiche::QuicheMemSlice( object.payload->data(), object.payload->length(), [retained_pointer = object.payload](absl::string_view) {}); } - result.arrival_time = object.arrival_time; result.fin_after_this = object.fin_after_this; return result; } 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 index ac33096abf..ef5566a33a 100644 --- 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 @@ -7,9 +7,6 @@ #include -#include "quiche/quic/core/quic_time.h" -#include "quiche/quic/moqt/moqt_messages.h" -#include "quiche/quic/moqt/moqt_priority.h" #include "quiche/quic/moqt/moqt_publisher.h" #include "quiche/common/quiche_mem_slice.h" @@ -18,11 +15,8 @@ namespace moqt { // CachedObject is a version of PublishedObject with a reference counted // payload. struct CachedObject { - Location sequence; - MoqtObjectStatus status; - MoqtPriority publisher_priority; + PublishedObjectMetadata metadata; std::shared_ptr payload; - quic::QuicTime arrival_time; bool fin_after_this; // This is the last object before FIN. }; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_failed_fetch.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_failed_fetch.h index 154c6fcf2e..c9718974ea 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_failed_fetch.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_failed_fetch.h @@ -26,9 +26,9 @@ class MoqtFailedFetch : public MoqtFetchTask { ObjectsAvailableCallback /*callback*/) override {} void SetFetchResponseCallback(FetchResponseCallback callback) { MoqtFetchError error; - error.subscribe_id = 0; + error.request_id = 0; error.error_code = StatusToRequestErrorCode(status_); - error.reason_phrase = status_.message(); + error.error_reason = status_.message(); std::move(callback)(error); } 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 93c9a31f15..6f0d6abd16 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 @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "absl/status/status.h" @@ -32,6 +33,7 @@ namespace { using ::quiche::QuicheBuffer; using ::quiche::WireBytes; +using ::quiche::WireOptional; using ::quiche::WireSpan; using ::quiche::WireStringWithVarInt62Length; using ::quiche::WireUint8; @@ -274,95 +276,56 @@ quiche::QuicheBuffer MoqtFramer::SerializeObjectHeader( << "Object metadata is invalid"; return quiche::QuicheBuffer(); } - if (!message.subgroup_id.has_value()) { - QUICHE_BUG(QUICHE_BUG_serialize_object_header_02) - << "Subgroup ID is not set on data stream"; - return quiche::QuicheBuffer(); - } - if (!is_first_in_stream) { - switch (message_type) { - case MoqtDataStreamType::kStreamHeaderSubgroup: - return (message.payload_length == 0) - ? Serialize(WireVarInt62(message.object_id), - WireStringWithVarInt62Length( - message.extension_headers), - WireVarInt62(message.payload_length), - WireVarInt62(static_cast( - message.object_status))) - : Serialize(WireVarInt62(message.object_id), - WireStringWithVarInt62Length( - message.extension_headers), - WireVarInt62(message.payload_length)); - case MoqtDataStreamType::kStreamHeaderFetch: - return (message.payload_length == 0) - ? Serialize(WireVarInt62(message.group_id), - WireVarInt62(*message.subgroup_id), - WireVarInt62(message.object_id), - WireUint8(message.publisher_priority), - WireStringWithVarInt62Length( - message.extension_headers), - WireVarInt62(message.payload_length), - WireVarInt62(static_cast( - message.object_status))) - : Serialize(WireVarInt62(message.group_id), - WireVarInt62(*message.subgroup_id), - WireVarInt62(message.object_id), - WireUint8(message.publisher_priority), - WireStringWithVarInt62Length( - message.extension_headers), - WireVarInt62(message.payload_length)); - default: - QUICHE_NOTREACHED(); - return quiche::QuicheBuffer(); - } - } - switch (message_type) { - case MoqtDataStreamType::kStreamHeaderSubgroup: - return (message.payload_length == 0) - ? Serialize( - WireVarInt62(message_type), - WireVarInt62(message.track_alias), - WireVarInt62(message.group_id), - WireVarInt62(*message.subgroup_id), - WireUint8(message.publisher_priority), - WireVarInt62(message.object_id), - WireStringWithVarInt62Length(message.extension_headers), - WireVarInt62(message.payload_length), - WireVarInt62(message.object_status)) - : Serialize( - WireVarInt62(message_type), - WireVarInt62(message.track_alias), - WireVarInt62(message.group_id), - WireVarInt62(*message.subgroup_id), - WireUint8(message.publisher_priority), - WireVarInt62(message.object_id), - WireStringWithVarInt62Length(message.extension_headers), - WireVarInt62(message.payload_length)); - case MoqtDataStreamType::kStreamHeaderFetch: - return (message.payload_length == 0) - ? Serialize( - WireVarInt62(message_type), - WireVarInt62(message.track_alias), - WireVarInt62(message.group_id), - WireVarInt62(*message.subgroup_id), - WireVarInt62(message.object_id), - WireUint8(message.publisher_priority), - WireStringWithVarInt62Length(message.extension_headers), - WireVarInt62(message.payload_length), - WireVarInt62(message.object_status)) - : Serialize( - WireVarInt62(message_type), - WireVarInt62(message.track_alias), - WireVarInt62(message.group_id), - WireVarInt62(*message.subgroup_id), - WireVarInt62(message.object_id), - WireUint8(message.publisher_priority), - WireStringWithVarInt62Length(message.extension_headers), - WireVarInt62(message.payload_length)); - default: - QUICHE_NOTREACHED(); - return quiche::QuicheBuffer(); + // Not all fields will be written to the wire. Keep optional ones in + // std::optional so that they can be excluded. + // Three fields are always optional. + std::optional stream_type = + is_first_in_stream ? std::optional(message_type.value()) + : std::nullopt; + std::optional track_alias = + is_first_in_stream ? std::optional(message.track_alias) + : std::nullopt; + std::optional object_status = + (message.payload_length == 0) + ? std::optional( + static_cast(message.object_status)) + : std::nullopt; + if (message_type.IsFetch()) { + return Serialize( + WireOptional(stream_type), + WireOptional(track_alias), WireVarInt62(message.group_id), + WireVarInt62(message.subgroup_id), WireVarInt62(message.object_id), + WireUint8(message.publisher_priority), + WireStringWithVarInt62Length(message.extension_headers), + WireVarInt62(message.payload_length), + WireOptional(object_status)); } + // Subgroup headers have more optional fields. + QUICHE_CHECK(message_type.IsSubgroup()); + std::optional group_id = + is_first_in_stream ? std::optional(message.group_id) + : std::nullopt; + std::optional subgroup_id = + (is_first_in_stream && message_type.IsSubgroupPresent()) + ? std::optional(message.subgroup_id) + : std::nullopt; + std::optional publisher_priority = + is_first_in_stream ? std::optional(message.publisher_priority) + : std::nullopt; + std::optional extension_headers = + (message_type.AreExtensionHeadersPresent()) + ? std::optional(message.extension_headers) + : std::nullopt; + return Serialize( + WireOptional(stream_type), + WireOptional(track_alias), + WireOptional(group_id), + WireOptional(subgroup_id), + WireOptional(publisher_priority), + WireVarInt62(message.object_id), + WireOptional(extension_headers), + WireVarInt62(message.payload_length), + WireOptional(object_status)); } quiche::QuicheBuffer MoqtFramer::SerializeObjectDatagram( @@ -377,20 +340,26 @@ quiche::QuicheBuffer MoqtFramer::SerializeObjectDatagram( << "Payload length does not match payload"; return quiche::QuicheBuffer(); } - if (message.object_status != MoqtObjectStatus::kNormal) { - return Serialize( - WireVarInt62(MoqtDatagramType::kObjectStatus), - WireVarInt62(message.track_alias), WireVarInt62(message.group_id), - WireVarInt62(message.object_id), WireUint8(message.publisher_priority), - WireStringWithVarInt62Length(message.extension_headers), - WireVarInt62(message.object_status)); - } + MoqtDatagramType datagram_type(/*has_status=*/payload.empty(), + !message.extension_headers.empty()); + std::optional extensions = + datagram_type.has_extension() + ? std::optional(message.extension_headers) + : std::nullopt; + std::optional object_status = + payload.empty() ? std::optional( + static_cast(message.object_status)) + : std::nullopt; + std::optional raw_payload = + payload.empty() ? std::nullopt + : std::optional(payload); return Serialize( - WireVarInt62(MoqtDatagramType::kObject), - WireVarInt62(message.track_alias), WireVarInt62(message.group_id), - WireVarInt62(message.object_id), WireUint8(message.publisher_priority), - WireStringWithVarInt62Length(message.extension_headers), - WireVarInt62(message.payload_length), WireBytes(payload)); + WireVarInt62(datagram_type.value()), WireVarInt62(message.track_alias), + WireVarInt62(message.group_id), WireVarInt62(message.object_id), + WireUint8(message.publisher_priority), + WireOptional(extensions), + WireOptional(object_status), + WireOptional(raw_payload)); } quiche::QuicheBuffer MoqtFramer::SerializeClientSetup( @@ -437,50 +406,40 @@ quiche::QuicheBuffer MoqtFramer::SerializeSubscribe( << "Serializing invalid MoQT parameters"; return quiche::QuicheBuffer(); } + std::optional start_group, start_object, end_group; switch (message.filter_type) { case MoqtFilterType::kNextGroupStart: case MoqtFilterType::kLatestObject: - return SerializeControlMessage( - MoqtMessageType::kSubscribe, WireVarInt62(message.request_id), - WireVarInt62(message.track_alias), - WireFullTrackName(message.full_track_name), - WireUint8(message.subscriber_priority), - WireDeliveryOrder(message.group_order), WireBoolean(message.forward), - WireVarInt62(message.filter_type), WireKeyValuePairList(parameters)); - case MoqtFilterType::kAbsoluteStart: - if (!message.start.has_value()) { - return quiche::QuicheBuffer(); - }; - return SerializeControlMessage( - MoqtMessageType::kSubscribe, WireVarInt62(message.request_id), - WireVarInt62(message.track_alias), - WireFullTrackName(message.full_track_name), - WireUint8(message.subscriber_priority), - WireDeliveryOrder(message.group_order), WireBoolean(message.forward), - WireVarInt62(message.filter_type), WireVarInt62(message.start->group), - WireVarInt62(message.start->object), - WireKeyValuePairList(parameters)); + break; case MoqtFilterType::kAbsoluteRange: - if (!message.start.has_value() || !message.end_group.has_value()) { - return quiche::QuicheBuffer(); - } - if (*message.end_group < message.start->group) { + if (!message.end_group.has_value() || !message.start.has_value() || + *message.end_group < message.start->group) { QUICHE_BUG(MoqtFramer_invalid_end_group) << "Invalid object range"; return quiche::QuicheBuffer(); } - return SerializeControlMessage( - MoqtMessageType::kSubscribe, WireVarInt62(message.request_id), - WireVarInt62(message.track_alias), - WireFullTrackName(message.full_track_name), - WireUint8(message.subscriber_priority), - WireDeliveryOrder(message.group_order), WireBoolean(message.forward), - WireVarInt62(message.filter_type), WireVarInt62(message.start->group), - WireVarInt62(message.start->object), WireVarInt62(*message.end_group), - WireKeyValuePairList(parameters)); + end_group = *message.end_group; + [[fallthrough]]; + case MoqtFilterType::kAbsoluteStart: + if (!message.start.has_value()) { + QUICHE_BUG(MoqtFramer_invalid_start) << "Filter requires start"; + return quiche::QuicheBuffer(); + } + start_group = message.start->group; + start_object = message.start->object; + break; default: QUICHE_BUG(MoqtFramer_end_group_missing) << "Subscribe framing error."; return quiche::QuicheBuffer(); } + return SerializeControlMessage( + MoqtMessageType::kSubscribe, WireVarInt62(message.request_id), + WireFullTrackName(message.full_track_name), + WireUint8(message.subscriber_priority), + WireDeliveryOrder(message.group_order), WireBoolean(message.forward), + WireVarInt62(message.filter_type), + WireOptional(start_group), + WireOptional(start_object), + WireOptional(end_group), WireKeyValuePairList(parameters)); } quiche::QuicheBuffer MoqtFramer::SerializeSubscribeOk( @@ -496,6 +455,7 @@ quiche::QuicheBuffer MoqtFramer::SerializeSubscribeOk( if (message.largest_location.has_value()) { return SerializeControlMessage( MoqtMessageType::kSubscribeOk, WireVarInt62(message.request_id), + WireVarInt62(message.track_alias), WireVarInt62(message.expires.ToMilliseconds()), WireDeliveryOrder(message.group_order), WireUint8(1), WireVarInt62(message.largest_location->group), @@ -504,6 +464,7 @@ quiche::QuicheBuffer MoqtFramer::SerializeSubscribeOk( } return SerializeControlMessage( MoqtMessageType::kSubscribeOk, WireVarInt62(message.request_id), + WireVarInt62(message.track_alias), WireVarInt62(message.expires.ToMilliseconds()), WireDeliveryOrder(message.group_order), WireUint8(0), WireKeyValuePairList(parameters)); @@ -514,22 +475,21 @@ quiche::QuicheBuffer MoqtFramer::SerializeSubscribeError( return SerializeControlMessage( MoqtMessageType::kSubscribeError, WireVarInt62(message.request_id), WireVarInt62(message.error_code), - WireStringWithVarInt62Length(message.reason_phrase), - WireVarInt62(message.track_alias)); + WireStringWithVarInt62Length(message.reason_phrase)); } quiche::QuicheBuffer MoqtFramer::SerializeUnsubscribe( const MoqtUnsubscribe& message) { return SerializeControlMessage(MoqtMessageType::kUnsubscribe, - WireVarInt62(message.subscribe_id)); + WireVarInt62(message.request_id)); } quiche::QuicheBuffer MoqtFramer::SerializeSubscribeDone( const MoqtSubscribeDone& message) { return SerializeControlMessage( - MoqtMessageType::kSubscribeDone, WireVarInt62(message.subscribe_id), + MoqtMessageType::kSubscribeDone, WireVarInt62(message.request_id), WireVarInt62(message.status_code), WireVarInt62(message.stream_count), - WireStringWithVarInt62Length(message.reason_phrase)); + WireStringWithVarInt62Length(message.error_reason)); } quiche::QuicheBuffer MoqtFramer::SerializeSubscribeUpdate( @@ -562,6 +522,7 @@ quiche::QuicheBuffer MoqtFramer::SerializeAnnounce( return quiche::QuicheBuffer(); } return SerializeControlMessage(MoqtMessageType::kAnnounce, + WireVarInt62(message.request_id), WireTrackNamespace(message.track_namespace), WireKeyValuePairList(parameters)); } @@ -569,16 +530,21 @@ quiche::QuicheBuffer MoqtFramer::SerializeAnnounce( quiche::QuicheBuffer MoqtFramer::SerializeAnnounceOk( const MoqtAnnounceOk& message) { return SerializeControlMessage(MoqtMessageType::kAnnounceOk, - WireTrackNamespace(message.track_namespace)); + WireVarInt62(message.request_id)); } quiche::QuicheBuffer MoqtFramer::SerializeAnnounceError( const MoqtAnnounceError& message) { return SerializeControlMessage( - MoqtMessageType::kAnnounceError, - WireTrackNamespace(message.track_namespace), + MoqtMessageType::kAnnounceError, WireVarInt62(message.request_id), WireVarInt62(message.error_code), - WireStringWithVarInt62Length(message.reason_phrase)); + WireStringWithVarInt62Length(message.error_reason)); +} + +quiche::QuicheBuffer MoqtFramer::SerializeUnannounce( + const MoqtUnannounce& message) { + return SerializeControlMessage(MoqtMessageType::kUnannounce, + WireTrackNamespace(message.track_namespace)); } quiche::QuicheBuffer MoqtFramer::SerializeAnnounceCancel( @@ -587,7 +553,7 @@ quiche::QuicheBuffer MoqtFramer::SerializeAnnounceCancel( MoqtMessageType::kAnnounceCancel, WireTrackNamespace(message.track_namespace), WireVarInt62(message.error_code), - WireStringWithVarInt62Length(message.reason_phrase)); + WireStringWithVarInt62Length(message.error_reason)); } quiche::QuicheBuffer MoqtFramer::SerializeTrackStatusRequest( @@ -601,16 +567,11 @@ quiche::QuicheBuffer MoqtFramer::SerializeTrackStatusRequest( return quiche::QuicheBuffer(); } return SerializeControlMessage(MoqtMessageType::kTrackStatusRequest, + WireVarInt62(message.request_id), WireFullTrackName(message.full_track_name), WireKeyValuePairList(parameters)); } -quiche::QuicheBuffer MoqtFramer::SerializeUnannounce( - const MoqtUnannounce& message) { - return SerializeControlMessage(MoqtMessageType::kUnannounce, - WireTrackNamespace(message.track_namespace)); -} - quiche::QuicheBuffer MoqtFramer::SerializeTrackStatus( const MoqtTrackStatus& message) { KeyValuePairList parameters; @@ -621,10 +582,12 @@ quiche::QuicheBuffer MoqtFramer::SerializeTrackStatus( << "Serializing invalid MoQT parameters"; return quiche::QuicheBuffer(); } - return SerializeControlMessage( - MoqtMessageType::kTrackStatus, WireFullTrackName(message.full_track_name), - WireVarInt62(message.status_code), WireVarInt62(message.last_group), - WireVarInt62(message.last_object), WireKeyValuePairList(parameters)); + return SerializeControlMessage(MoqtMessageType::kTrackStatus, + WireVarInt62(message.request_id), + WireVarInt62(message.status_code), + WireVarInt62(message.largest_location.group), + WireVarInt62(message.largest_location.object), + WireKeyValuePairList(parameters)); } quiche::QuicheBuffer MoqtFramer::SerializeGoAway(const MoqtGoAway& message) { @@ -644,6 +607,7 @@ quiche::QuicheBuffer MoqtFramer::SerializeSubscribeAnnounces( return quiche::QuicheBuffer(); } return SerializeControlMessage(MoqtMessageType::kSubscribeAnnounces, + WireVarInt62(message.request_id), WireTrackNamespace(message.track_namespace), WireKeyValuePairList(parameters)); } @@ -651,16 +615,15 @@ quiche::QuicheBuffer MoqtFramer::SerializeSubscribeAnnounces( quiche::QuicheBuffer MoqtFramer::SerializeSubscribeAnnouncesOk( const MoqtSubscribeAnnouncesOk& message) { return SerializeControlMessage(MoqtMessageType::kSubscribeAnnouncesOk, - WireTrackNamespace(message.track_namespace)); + WireVarInt62(message.request_id)); } quiche::QuicheBuffer MoqtFramer::SerializeSubscribeAnnouncesError( const MoqtSubscribeAnnouncesError& message) { return SerializeControlMessage( MoqtMessageType::kSubscribeAnnouncesError, - WireTrackNamespace(message.track_namespace), - WireVarInt62(message.error_code), - WireStringWithVarInt62Length(message.reason_phrase)); + WireVarInt62(message.request_id), WireVarInt62(message.error_code), + WireStringWithVarInt62Length(message.error_reason)); } quiche::QuicheBuffer MoqtFramer::SerializeUnsubscribeAnnounces( @@ -676,13 +639,16 @@ quiche::QuicheBuffer MoqtFramer::SerializeMaxRequestId( } quiche::QuicheBuffer MoqtFramer::SerializeFetch(const MoqtFetch& message) { - if (!message.joining_fetch.has_value() && - (message.end_group < message.start_object.group || - (message.end_group == message.start_object.group && - message.end_object.has_value() && - *message.end_object < message.start_object.object))) { - QUICHE_BUG(MoqtFramer_invalid_fetch) << "Invalid FETCH object range"; - return quiche::QuicheBuffer(); + if (std::holds_alternative(message.fetch)) { + const StandaloneFetch& standalone_fetch = + std::get(message.fetch); + if (standalone_fetch.end_group < standalone_fetch.start_object.group || + (standalone_fetch.end_group == standalone_fetch.start_object.group && + standalone_fetch.end_object.has_value() && + *standalone_fetch.end_object < standalone_fetch.start_object.object)) { + QUICHE_BUG(MoqtFramer_invalid_fetch) << "Invalid FETCH object range"; + return quiche::QuicheBuffer(); + } } KeyValuePairList parameters; VersionSpecificParametersToKeyValuePairList(message.parameters, parameters); @@ -691,34 +657,42 @@ quiche::QuicheBuffer MoqtFramer::SerializeFetch(const MoqtFetch& message) { << "Serializing invalid MoQT parameters"; return quiche::QuicheBuffer(); } - if (message.joining_fetch.has_value()) { + if (std::holds_alternative(message.fetch)) { + const StandaloneFetch& standalone_fetch = + std::get(message.fetch); return SerializeControlMessage( - MoqtMessageType::kFetch, WireVarInt62(message.fetch_id), + MoqtMessageType::kFetch, WireVarInt62(message.request_id), WireUint8(message.subscriber_priority), WireDeliveryOrder(message.group_order), - WireVarInt62(FetchType::kJoining), - WireVarInt62(message.joining_fetch->joining_subscribe_id), - WireVarInt62(message.joining_fetch->preceding_group_offset), + WireVarInt62(FetchType::kStandalone), + WireFullTrackName(standalone_fetch.full_track_name), + WireVarInt62(standalone_fetch.start_object.group), + WireVarInt62(standalone_fetch.start_object.object), + WireVarInt62(standalone_fetch.end_group), + WireVarInt62(standalone_fetch.end_object.has_value() + ? *standalone_fetch.end_object + 1 + : 0), WireKeyValuePairList(parameters)); } + uint64_t subscribe_id; + uint64_t joining_start; + if (std::holds_alternative(message.fetch)) { + const JoiningFetchRelative& joining_fetch = + std::get(message.fetch); + subscribe_id = joining_fetch.joining_subscribe_id; + joining_start = joining_fetch.joining_start; + } else { + const JoiningFetchAbsolute& joining_fetch = + std::get(message.fetch); + subscribe_id = joining_fetch.joining_subscribe_id; + joining_start = joining_fetch.joining_start; + } return SerializeControlMessage( - MoqtMessageType::kFetch, WireVarInt62(message.fetch_id), + MoqtMessageType::kFetch, WireVarInt62(message.request_id), WireUint8(message.subscriber_priority), WireDeliveryOrder(message.group_order), - WireVarInt62(FetchType::kStandalone), - WireFullTrackName(message.full_track_name), - WireVarInt62(message.start_object.group), - WireVarInt62(message.start_object.object), - WireVarInt62(message.end_group), - WireVarInt62(message.end_object.has_value() ? *message.end_object + 1 - : 0), - WireKeyValuePairList(parameters)); -} - -quiche::QuicheBuffer MoqtFramer::SerializeFetchCancel( - const MoqtFetchCancel& message) { - return SerializeControlMessage(MoqtMessageType::kFetchCancel, - WireVarInt62(message.subscribe_id)); + WireVarInt62(message.fetch.index() + 1), WireVarInt62(subscribe_id), + WireVarInt62(joining_start), WireKeyValuePairList(parameters)); } quiche::QuicheBuffer MoqtFramer::SerializeFetchOk(const MoqtFetchOk& message) { @@ -730,20 +704,26 @@ quiche::QuicheBuffer MoqtFramer::SerializeFetchOk(const MoqtFetchOk& message) { << "Serializing invalid MoQT parameters"; return quiche::QuicheBuffer(); } - return SerializeControlMessage(MoqtMessageType::kFetchOk, - WireVarInt62(message.subscribe_id), - WireDeliveryOrder(message.group_order), - WireVarInt62(message.largest_id.group), - WireVarInt62(message.largest_id.object), - WireKeyValuePairList(parameters)); + return SerializeControlMessage( + MoqtMessageType::kFetchOk, WireVarInt62(message.request_id), + WireDeliveryOrder(message.group_order), WireBoolean(message.end_of_track), + WireVarInt62(message.end_location.group), + WireVarInt62(message.end_location.object), + WireKeyValuePairList(parameters)); } quiche::QuicheBuffer MoqtFramer::SerializeFetchError( const MoqtFetchError& message) { return SerializeControlMessage( - MoqtMessageType::kFetchError, WireVarInt62(message.subscribe_id), + MoqtMessageType::kFetchError, WireVarInt62(message.request_id), WireVarInt62(message.error_code), - WireStringWithVarInt62Length(message.reason_phrase)); + WireStringWithVarInt62Length(message.error_reason)); +} + +quiche::QuicheBuffer MoqtFramer::SerializeFetchCancel( + const MoqtFetchCancel& message) { + return SerializeControlMessage(MoqtMessageType::kFetchCancel, + WireVarInt62(message.request_id)); } quiche::QuicheBuffer MoqtFramer::SerializeRequestsBlocked( @@ -752,6 +732,90 @@ quiche::QuicheBuffer MoqtFramer::SerializeRequestsBlocked( WireVarInt62(message.max_request_id)); } +quiche::QuicheBuffer MoqtFramer::SerializePublish(const MoqtPublish& message) { + KeyValuePairList parameters; + VersionSpecificParametersToKeyValuePairList(message.parameters, parameters); + if (!ValidateVersionSpecificParameters(parameters, + MoqtMessageType::kPublish)) { + QUICHE_BUG(QUICHE_BUG_invalid_parameters) + << "Serializing invalid MoQT parameters"; + return quiche::QuicheBuffer(); + } + std::optional group, object; + if (message.largest_location.has_value()) { + group = message.largest_location->group; + object = message.largest_location->object; + } + return SerializeControlMessage( + MoqtMessageType::kPublish, WireVarInt62(message.request_id), + WireFullTrackName(message.full_track_name), + WireVarInt62(message.track_alias), WireDeliveryOrder(message.group_order), + WireBoolean(message.largest_location.has_value()), + WireOptional(group), WireOptional(object), + WireBoolean(message.forward), WireKeyValuePairList(parameters)); +} + +quiche::QuicheBuffer MoqtFramer::SerializePublishOk( + const MoqtPublishOk& message) { + KeyValuePairList parameters; + VersionSpecificParametersToKeyValuePairList(message.parameters, parameters); + if (!ValidateVersionSpecificParameters(parameters, + MoqtMessageType::kPublishOk)) { + QUICHE_BUG(QUICHE_BUG_invalid_parameters) + << "Serializing invalid MoQT parameters"; + return quiche::QuicheBuffer(); + } + std::optional start_group, start_object, end_group; + switch (message.filter_type) { + case MoqtFilterType::kNextGroupStart: + case MoqtFilterType::kLatestObject: + break; + case MoqtFilterType::kAbsoluteStart: + case MoqtFilterType::kAbsoluteRange: + if (!message.start.has_value()) { + QUICHE_BUG(QUICHE_BUG_invalid_filter_type) + << "Serializing invalid MoQT filter type"; + return quiche::QuicheBuffer(); + } + start_group = message.start->group; + start_object = message.start->object; + if (message.filter_type == MoqtFilterType::kAbsoluteStart) { + break; + } + if (!message.end_group.has_value()) { + QUICHE_BUG(QUICHE_BUG_invalid_filter_type) + << "Serializing invalid MoQT filter type"; + return quiche::QuicheBuffer(); + } + end_group = message.end_group; + if (*end_group < *start_group) { + QUICHE_BUG(QUICHE_BUG_invalid_filter_type) + << "End group is less than start group"; + return quiche::QuicheBuffer(); + } + break; + default: + QUICHE_BUG(QUICHE_BUG_invalid_filter_type) + << "Serializing invalid MoQT filter type"; + return quiche::QuicheBuffer(); + } + return SerializeControlMessage( + MoqtMessageType::kPublishOk, WireVarInt62(message.request_id), + WireBoolean(message.forward), WireUint8(message.subscriber_priority), + WireDeliveryOrder(message.group_order), WireVarInt62(message.filter_type), + WireOptional(start_group), + WireOptional(start_object), + WireOptional(end_group), WireKeyValuePairList(parameters)); +} + +quiche::QuicheBuffer MoqtFramer::SerializePublishError( + const MoqtPublishError& message) { + return SerializeControlMessage( + MoqtMessageType::kPublishError, WireVarInt62(message.request_id), + WireVarInt62(message.error_code), + WireStringWithVarInt62Length(message.error_reason)); +} + quiche::QuicheBuffer MoqtFramer::SerializeObjectAck( const MoqtObjectAck& message) { return SerializeControlMessage( @@ -768,7 +832,7 @@ bool MoqtFramer::ValidateObjectMetadata(const MoqtObject& object, object.payload_length > 0) { return false; } - if (is_datagram == object.subgroup_id.has_value()) { + if (is_datagram && object.subgroup_id != object.object_id) { return false; } return true; 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 d001464e5f..8310736c3f 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 @@ -33,6 +33,7 @@ class QUICHE_EXPORT MoqtFramer { quiche::QuicheBuffer SerializeObjectHeader(const MoqtObject& message, MoqtDataStreamType message_type, bool is_first_in_stream); + // Serializes both OBJECT and OBJECT_STATUS datagrams. quiche::QuicheBuffer SerializeObjectDatagram(const MoqtObject& message, absl::string_view payload); quiche::QuicheBuffer SerializeClientSetup(const MoqtClientSetup& message); @@ -49,11 +50,11 @@ class QUICHE_EXPORT MoqtFramer { quiche::QuicheBuffer SerializeAnnounce(const MoqtAnnounce& message); quiche::QuicheBuffer SerializeAnnounceOk(const MoqtAnnounceOk& message); quiche::QuicheBuffer SerializeAnnounceError(const MoqtAnnounceError& message); + quiche::QuicheBuffer SerializeUnannounce(const MoqtUnannounce& 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); quiche::QuicheBuffer SerializeSubscribeAnnounces( @@ -71,6 +72,9 @@ class QUICHE_EXPORT MoqtFramer { quiche::QuicheBuffer SerializeFetchError(const MoqtFetchError& message); quiche::QuicheBuffer SerializeRequestsBlocked( const MoqtRequestsBlocked& message); + quiche::QuicheBuffer SerializePublish(const MoqtPublish& message); + quiche::QuicheBuffer SerializePublishOk(const MoqtPublishOk& message); + quiche::QuicheBuffer SerializePublishError(const MoqtPublishError& message); quiche::QuicheBuffer SerializeObjectAck(const MoqtObjectAck& message); private: diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_live_relay_queue.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_live_relay_queue.cc index e6b6f9b0d3..3468192fe6 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_live_relay_queue.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_live_relay_queue.cc @@ -4,6 +4,7 @@ #include "quiche/quic/moqt/moqt_live_relay_queue.h" +#include #include #include #include @@ -18,13 +19,14 @@ #include "quiche/quic/moqt/moqt_subscribe_windows.h" #include "quiche/common/platform/api/quiche_logging.h" #include "quiche/common/quiche_buffer_allocator.h" +#include "quiche/common/quiche_callbacks.h" #include "quiche/common/quiche_mem_slice.h" #include "quiche/common/simple_buffer_allocator.h" #include "quiche/web_transport/web_transport.h" namespace moqt { -bool MoqtLiveRelayQueue::AddFin(Location sequence) { +bool MoqtLiveRelayQueue::AddFin(Location sequence, uint64_t subgroup) { switch (forwarding_preference_) { case MoqtForwardingPreference::kDatagram: return false; @@ -37,8 +39,8 @@ bool MoqtLiveRelayQueue::AddFin(Location sequence) { return false; } Group& group = group_it->second; - auto subgroup_it = group.subgroups.find( - SubgroupPriority{publisher_priority_, sequence.subgroup}); + auto subgroup_it = + group.subgroups.find(SubgroupPriority{publisher_priority_, subgroup}); if (subgroup_it == group.subgroups.end()) { // Subgroup does not exist. return false; @@ -53,13 +55,14 @@ bool MoqtLiveRelayQueue::AddFin(Location sequence) { } subgroup_it->second.rbegin()->second.fin_after_this = true; for (MoqtObjectListener* listener : listeners_) { - listener->OnNewFinAvailable(sequence); + listener->OnNewFinAvailable(sequence, subgroup); } return true; } bool MoqtLiveRelayQueue::OnStreamReset( - Location sequence, webtransport::StreamErrorCode error_code) { + Location sequence, uint64_t subgroup_id, + webtransport::StreamErrorCode error_code) { switch (forwarding_preference_) { case MoqtForwardingPreference::kDatagram: return false; @@ -72,23 +75,21 @@ bool MoqtLiveRelayQueue::OnStreamReset( return false; } Group& group = group_it->second; - auto subgroup_it = group.subgroups.find( - SubgroupPriority{publisher_priority_, sequence.subgroup}); + auto subgroup_it = + group.subgroups.find(SubgroupPriority{publisher_priority_, subgroup_id}); if (subgroup_it == group.subgroups.end()) { // Subgroup does not exist. return false; } for (MoqtObjectListener* listener : listeners_) { - listener->OnSubgroupAbandoned(sequence, error_code); + listener->OnSubgroupAbandoned(sequence.group, subgroup_id, error_code); } return true; } -// TODO(martinduke): Unless Track Forwarding preference goes away, support it. -bool MoqtLiveRelayQueue::AddRawObject(Location sequence, - MoqtObjectStatus status, - MoqtPriority priority, - absl::string_view payload, bool fin) { +bool MoqtLiveRelayQueue::AddObject(const PublishedObjectMetadata& metadata, + absl::string_view payload, bool fin) { + const Location& sequence = metadata.location; bool last_object_in_stream = fin; if (queue_.size() == kMaxQueuedGroups) { if (queue_.begin()->first > sequence.group) { @@ -110,32 +111,13 @@ bool MoqtLiveRelayQueue::AddRawObject(Location sequence, << "track"; return false; } - switch (status) { - case MoqtObjectStatus::kEndOfTrackAndGroup: - if (sequence < next_sequence_) { - QUICHE_DLOG(INFO) << "EndOfTrackAndGroup is too early."; - return false; - } - // TODO(martinduke): Check that EndOfTrackAndGroup has normal IDs. - end_of_track_ = sequence; - break; - case MoqtObjectStatus::kEndOfTrack: - if (sequence.group <= next_sequence_.group || sequence.object > 0) { - QUICHE_DLOG(INFO) << "EndOfTrack is too early."; - return false; - } - // TODO(martinduke): Check that EndOfTrack has normal IDs. - end_of_track_ = sequence; - break; - case MoqtObjectStatus::kGroupDoesNotExist: - if (sequence.object > 0) { - QUICHE_DLOG(INFO) << "GroupDoesNotExist is not the last object in the " - << "group"; - return false; - } - break; - default: - break; + if (metadata.status == MoqtObjectStatus::kEndOfTrack) { + if (sequence < next_sequence_) { + QUICHE_DLOG(INFO) << "EndOfTrack is too early."; + return false; + } + // TODO(martinduke): Check that EndOfTrack has normal IDs. + end_of_track_ = sequence; } auto group_it = queue_.try_emplace(sequence.group); Group& group = group_it.first->second; @@ -145,16 +127,16 @@ bool MoqtLiveRelayQueue::AddRawObject(Location sequence, << "group"; return false; } - if ((status == MoqtObjectStatus::kEndOfGroup || - status == MoqtObjectStatus::kEndOfTrackAndGroup) && + if (metadata.status == MoqtObjectStatus::kEndOfGroup && sequence.object < group.next_object) { QUICHE_DLOG(INFO) << "Skipping EndOfGroup because it is not the last " << "object in the group."; return false; } } + // TODO: use `metadata.publisher_priority` instead. auto subgroup_it = group.subgroups.try_emplace( - SubgroupPriority{priority, sequence.subgroup}); + SubgroupPriority{publisher_priority_, metadata.subgroup}); auto& subgroup = subgroup_it.first->second; if (!subgroup.empty()) { // Check if the new object is valid CachedObject& last_object = subgroup.rbegin()->second; @@ -165,10 +147,10 @@ bool MoqtLiveRelayQueue::AddRawObject(Location sequence, } // If last_object has stream-ending status, it should have been caught by // the fin_after_this check above. - QUICHE_DCHECK(last_object.status != MoqtObjectStatus::kEndOfTrackAndGroup && - last_object.status != MoqtObjectStatus::kEndOfGroup && - last_object.status != MoqtObjectStatus::kEndOfTrack); - if (last_object.sequence.object >= sequence.object) { + QUICHE_DCHECK( + last_object.metadata.status != MoqtObjectStatus::kEndOfGroup && + last_object.metadata.status != MoqtObjectStatus::kEndOfTrack); + if (last_object.metadata.location.object >= sequence.object) { QUICHE_DLOG(INFO) << "Skipping object because it does not increase the " << "object ID monotonically in the subgroup."; return false; @@ -182,13 +164,11 @@ bool MoqtLiveRelayQueue::AddRawObject(Location sequence, group.next_object = sequence.object + 1; } // Anticipate stream FIN with most non-normal objects. - switch (status) { + switch (metadata.status) { case MoqtObjectStatus::kEndOfTrack: - case MoqtObjectStatus::kEndOfTrackAndGroup: end_of_track_ = sequence; last_object_in_stream = true; ABSL_FALLTHROUGH_INTENDED; - case MoqtObjectStatus::kGroupDoesNotExist: case MoqtObjectStatus::kEndOfGroup: group.complete = true; last_object_in_stream = true; @@ -201,26 +181,24 @@ bool MoqtLiveRelayQueue::AddRawObject(Location sequence, ? nullptr : std::make_shared(quiche::QuicheBuffer::Copy( quiche::SimpleBufferAllocator::Get(), payload)); - subgroup.emplace( - sequence.object, - CachedObject{sequence, status, priority, slice, clock_->ApproximateNow(), - last_object_in_stream}); + subgroup.emplace(sequence.object, + CachedObject{metadata, slice, last_object_in_stream}); for (MoqtObjectListener* listener : listeners_) { - listener->OnNewObjectAvailable(sequence); + listener->OnNewObjectAvailable(sequence, metadata.subgroup); } return true; } std::optional MoqtLiveRelayQueue::GetCachedObject( - Location sequence) const { - auto group_it = queue_.find(sequence.group); + uint64_t group_id, uint64_t subgroup_id, uint64_t object_id) const { + auto group_it = queue_.find(group_id); if (group_it == queue_.end()) { // Group does not exist. return std::nullopt; } const Group& group = group_it->second; - auto subgroup_it = group.subgroups.find( - SubgroupPriority{publisher_priority_, sequence.subgroup}); + auto subgroup_it = + group.subgroups.find(SubgroupPriority{publisher_priority_, subgroup_id}); if (subgroup_it == group.subgroups.end()) { // Subgroup does not exist. return std::nullopt; @@ -230,7 +208,7 @@ std::optional MoqtLiveRelayQueue::GetCachedObject( return std::nullopt; // There are no objects. } // Find an object with ID of at least sequence.object. - auto object_it = subgroup.lower_bound(sequence.object); + auto object_it = subgroup.lower_bound(object_id); if (object_it == subgroup.end()) { // No object after the last one received. return std::nullopt; @@ -238,30 +216,15 @@ std::optional MoqtLiveRelayQueue::GetCachedObject( return CachedObjectToPublishedObject(object_it->second); } -std::vector MoqtLiveRelayQueue::GetCachedObjectsInRange( - Location start, Location end) const { - std::vector sequences; - SubscribeWindow window(start, end.group, end.object); +void MoqtLiveRelayQueue::ForAllObjects( + quiche::UnretainedCallback callback) { for (auto& group_it : queue_) { - if (group_it.first < start.group) { - continue; - } - if (group_it.first > end.group) { - return sequences; - } for (auto& subgroup_it : group_it.second.subgroups) { for (auto& object_it : subgroup_it.second) { - if (window.InWindow(object_it.second.sequence)) { - sequences.push_back(object_it.second.sequence); - } - if (group_it.first == end.group && - object_it.second.sequence.object >= end.object) { - break; - } + callback(object_it.second); } } } - return sequences; } absl::StatusOr MoqtLiveRelayQueue::GetTrackStatus() const { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_live_relay_queue.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_live_relay_queue.h index 0ecb671116..60ef82875d 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_live_relay_queue.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_live_relay_queue.h @@ -10,7 +10,6 @@ #include #include #include -#include #include "absl/container/btree_map.h" #include "absl/container/flat_hash_set.h" @@ -24,6 +23,7 @@ #include "quiche/quic/moqt/moqt_messages.h" #include "quiche/quic/moqt/moqt_priority.h" #include "quiche/quic/moqt/moqt_publisher.h" +#include "quiche/common/quiche_callbacks.h" #include "quiche/web_transport/web_transport.h" namespace moqt { @@ -58,32 +58,48 @@ class MoqtLiveRelayQueue : public MoqtTrackPublisher { // occur. A false return value might result in a session error on the // inbound session, but this queue is the only place that retains enough state // to check. - bool AddObject(Location sequence, MoqtObjectStatus status, bool fin = false) { - return AddRawObject(sequence, status, publisher_priority_, "", fin); - } - bool AddObject(Location sequence, absl::string_view object, + bool AddObject(const PublishedObjectMetadata& metadata, + absl::string_view payload, bool fin); + + // Convenience methods primarily for use in tests. Prefer the + // `PublishedObjectMetadata` version in real forwarding code to ensure all + // metadata is copied correctly. + bool AddObject(Location location, uint64_t subgroup, MoqtObjectStatus status, bool fin = false) { - return AddRawObject(sequence, MoqtObjectStatus::kNormal, - publisher_priority_, object, fin); + PublishedObjectMetadata metadata; + metadata.location = location; + metadata.subgroup = subgroup; + metadata.status = status; + metadata.publisher_priority = 0; + return AddObject(metadata, "", fin); } + bool AddObject(Location location, uint64_t subgroup, absl::string_view object, + bool fin = false) { + PublishedObjectMetadata metadata; + metadata.location = location; + metadata.subgroup = subgroup; + metadata.status = MoqtObjectStatus::kNormal; + metadata.publisher_priority = 0; + return AddObject(metadata, object, fin); + } + // Record a received FIN that did not come with the last object. // If the forwarding preference is kDatagram or kTrack, |sequence| is ignored. // Otherwise, |sequence| is used to determine which stream is being FINed. If // the object ID does not match the last object ID in the stream, no action // is taken. - bool AddFin(Location sequence); + bool AddFin(Location sequence, uint64_t subgroup_id); // Record a received RESET_STREAM. |sequence| encodes the group and subgroup // of the stream that is being reset. Returns false on datagram tracks, or if // the stream does not exist. - bool OnStreamReset(Location sequence, + bool OnStreamReset(Location sequence, uint64_t subgroup_id, webtransport::StreamErrorCode error_code); // MoqtTrackPublisher implementation. const FullTrackName& GetTrackName() const override { return track_; } std::optional GetCachedObject( - Location sequence) const override; - std::vector GetCachedObjectsInRange(Location start, - Location end) const override; + uint64_t group_id, uint64_t subgroup_id, + uint64_t min_object) const override; void AddObjectListener(MoqtObjectListener* listener) override { listeners_.insert(listener); listener->OnSubscribeAccepted(); @@ -121,6 +137,9 @@ class MoqtLiveRelayQueue : public MoqtTrackPublisher { } } + void ForAllObjects( + quiche::UnretainedCallback callback); + private: // The number of recent groups to keep around for newly joined subscribers. static constexpr size_t kMaxQueuedGroups = 3; @@ -134,9 +153,6 @@ class MoqtLiveRelayQueue : public MoqtTrackPublisher { absl::btree_map subgroups; }; - bool AddRawObject(Location sequence, MoqtObjectStatus status, - MoqtPriority priority, absl::string_view payload, bool fin); - const quic::QuicClock* clock_; FullTrackName track_; MoqtForwardingPreference forwarding_preference_; 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 3cb9923a6b..993fa2d755 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 @@ -134,7 +134,6 @@ absl::StatusCode RequestErrorCodeToStatusCode(RequestErrorCode error_code) { return absl::StatusCode::kNotFound; case RequestErrorCode::kInvalidJoiningSubscribeId: case RequestErrorCode::kMalformedAuthToken: - case RequestErrorCode::kUnknownAuthTokenAlias: return absl::StatusCode::kInvalidArgument; case RequestErrorCode::kExpiredAuthToken: return absl::StatusCode::kUnauthenticated; @@ -174,16 +173,18 @@ MoqtError ValidateSetupParameters(const KeyValuePairList& parameters, return MoqtError::kNoError; } -const std::array kAllowsAuthorization = { - MoqtMessageType::kSubscribe, MoqtMessageType::kTrackStatusRequest, - MoqtMessageType::kFetch, MoqtMessageType::kSubscribeAnnounces, - MoqtMessageType::kAnnounce}; -const std::array kAllowsDeliveryTimeout = { - MoqtMessageType::kSubscribe, MoqtMessageType::kSubscribeOk, - MoqtMessageType::kSubscribeUpdate, MoqtMessageType::kTrackStatus}; -const std::array kAllowsMaxCacheDuration = { +const std::array kAllowsAuthorization = { + MoqtMessageType::kClientSetup, MoqtMessageType::kServerSetup, + MoqtMessageType::kSubscribe, MoqtMessageType::kSubscribeAnnounces, + MoqtMessageType::kAnnounce, MoqtMessageType::kTrackStatusRequest, + MoqtMessageType::kFetch, MoqtMessageType::kPublish}; +const std::array kAllowsDeliveryTimeout = { + MoqtMessageType::kSubscribe, MoqtMessageType::kSubscribeOk, + MoqtMessageType::kSubscribeUpdate, MoqtMessageType::kTrackStatus, + MoqtMessageType::kPublish, MoqtMessageType::kPublishOk}; +const std::array kAllowsMaxCacheDuration = { MoqtMessageType::kSubscribeOk, MoqtMessageType::kTrackStatus, - MoqtMessageType::kFetchOk}; + MoqtMessageType::kFetchOk, MoqtMessageType::kPublish}; bool ValidateVersionSpecificParameters(const KeyValuePairList& parameters, MoqtMessageType message_type) { size_t authorization_token = @@ -255,6 +256,12 @@ std::string MoqtMessageTypeToString(const MoqtMessageType message_type) { return "UNSUBSCRIBE_NAMESPACE"; case MoqtMessageType::kMaxRequestId: return "MAX_REQUEST_ID"; + case MoqtMessageType::kPublish: + return "PUBLISH"; + case MoqtMessageType::kPublishOk: + return "PUBLISH_OK"; + case MoqtMessageType::kPublishError: + return "PUBLISH_ERROR"; case MoqtMessageType::kFetch: return "FETCH"; case MoqtMessageType::kFetchCancel: @@ -272,25 +279,17 @@ std::string MoqtMessageTypeToString(const MoqtMessageType message_type) { } std::string MoqtDataStreamTypeToString(MoqtDataStreamType type) { - switch (type) { - case MoqtDataStreamType::kStreamHeaderSubgroup: - return "STREAM_HEADER_SUBGROUP"; - case MoqtDataStreamType::kStreamHeaderFetch: - return "STREAM_HEADER_FETCH"; - case MoqtDataStreamType::kPadding: - return "PADDING"; + if (type.IsPadding()) { + return "PADDING"; + } else if (type.IsFetch()) { + return "STREAM_HEADER_FETCH"; } - return "Unknown stream type " + absl::StrCat(static_cast(type)); + return absl::StrCat("STREAM_HEADER_SUBGROUP_", type.value()); } std::string MoqtDatagramTypeToString(MoqtDatagramType type) { - switch (type) { - case MoqtDatagramType::kObject: - return "OBJECT_DATAGRAM"; - case MoqtDatagramType::kObjectStatus: - return "OBJECT_STATUS_DATAGRAM"; - } - return "Unknown datagram type " + absl::StrCat(static_cast(type)); + return absl::StrCat("DATAGRAM", type.has_status() ? "_STATUS" : "", + type.has_extension() ? "_EXTENSION" : ""); } std::string MoqtForwardingPreferenceToString( @@ -356,17 +355,6 @@ std::string TrackNamespace::ToString() const { return absl::StrCat("{", absl::StrJoin(bits, "::"), "}"); } -bool TrackNamespace::operator==(const TrackNamespace& other) const { - if (number_of_elements() != other.number_of_elements()) { - return false; - } - return absl::c_equal(tuple_, other.tuple_); -} - -bool TrackNamespace::operator<(const TrackNamespace& other) const { - return absl::c_lexicographical_compare(tuple_, other.tuple_); -} - void FullTrackName::set_name(absl::string_view name) { QUIC_BUG_IF(Moqt_name_too_large_03, !CanAddName(name)) << "Setting a name that is too large."; @@ -376,10 +364,14 @@ void FullTrackName::set_name(absl::string_view name) { absl::Status MoqtStreamErrorToStatus(webtransport::StreamErrorCode error_code, absl::string_view reason_phrase) { switch (error_code) { - case kResetCodeSubscriptionGone: - return absl::NotFoundError(reason_phrase); - case kResetCodeTimedOut: + case kResetCodeCanceled: + return absl::CancelledError(reason_phrase); + case kResetCodeDeliveryTimeout: return absl::DeadlineExceededError(reason_phrase); + case kResetCodeSessionClosed: + return absl::AbortedError(reason_phrase); + case kResetCodeMalformedTrack: + return absl::InvalidArgumentError(reason_phrase); default: return absl::UnknownError(reason_phrase); } 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 3a32cb9f23..d1979be0f8 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 @@ -7,16 +7,17 @@ #ifndef QUICHE_QUIC_MOQT_MOQT_MESSAGES_H_ #define QUICHE_QUIC_MOQT_MOQT_MESSAGES_H_ +#include #include #include #include #include #include #include +#include #include #include "absl/container/btree_map.h" -#include "absl/container/inlined_vector.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" @@ -38,11 +39,11 @@ inline constexpr quic::ParsedQuicVersionVector GetMoqtSupportedQuicVersions() { } enum class MoqtVersion : uint64_t { - kDraft11 = 0xff00000b, + kDraft12 = 0xff00000c, kUnrecognizedVersionForTests = 0xfe0000ff, }; -inline constexpr MoqtVersion kDefaultMoqtVersion = MoqtVersion::kDraft11; +inline constexpr MoqtVersion kDefaultMoqtVersion = MoqtVersion::kDraft12; inline constexpr uint64_t kDefaultInitialMaxRequestId = 100; // TODO(martinduke): Implement an auth token cache. inline constexpr uint64_t kDefaultMaxAuthTokenCacheSize = 0; @@ -50,6 +51,30 @@ inline constexpr uint64_t kMinNamespaceElements = 1; inline constexpr uint64_t kMaxNamespaceElements = 32; inline constexpr size_t kMaxFullTrackNameSize = 1024; +enum AuthTokenType : uint64_t { + kOutOfBand = 0x0, + + kMaxAuthTokenType = 0x0, +}; + +enum AuthTokenAliasType : uint64_t { + kDelete = 0x0, + kRegister = 0x1, + kUseAlias = 0x2, + kUseValue = 0x3, + + kMaxValue = 0x3, +}; + +struct AuthToken { + AuthToken(AuthTokenType token_type, absl::string_view token) + : type(token_type), token(token) {} + bool operator==(const AuthToken& other) const = default; + + AuthTokenType type; + std::string token; +}; + struct QUICHE_EXPORT MoqtSessionParameters { // TODO: support multiple versions. MoqtSessionParameters() = default; @@ -67,15 +92,7 @@ struct QUICHE_EXPORT MoqtSessionParameters { max_request_id(max_request_id) {} MoqtSessionParameters(quic::Perspective perspective, uint64_t max_request_id) : perspective(perspective), max_request_id(max_request_id) {} - bool operator==(const MoqtSessionParameters& other) { - return version == other.version && - deliver_partial_objects == other.deliver_partial_objects && - perspective == other.perspective && - using_webtrans == other.using_webtrans && path == other.path && - max_request_id == other.max_request_id && - max_auth_token_cache_size == other.max_auth_token_cache_size && - support_object_acks == other.support_object_acks; - } + bool operator==(const MoqtSessionParameters& other) const = default; MoqtVersion version = kDefaultMoqtVersion; bool deliver_partial_objects = false; @@ -85,6 +102,8 @@ struct QUICHE_EXPORT MoqtSessionParameters { uint64_t max_request_id = kDefaultInitialMaxRequestId; uint64_t max_auth_token_cache_size = kDefaultMaxAuthTokenCacheSize; bool support_object_acks = false; + // TODO(martinduke): Turn authorization_token into structured data. + std::vector authorization_token; }; // The maximum length of a message, excluding any OBJECT payload. This prevents @@ -92,17 +111,107 @@ struct QUICHE_EXPORT MoqtSessionParameters { // are not buffered by the parser). inline constexpr size_t kMaxMessageHeaderSize = 2048; -enum class QUICHE_EXPORT MoqtDataStreamType : uint64_t { - kStreamHeaderSubgroup = 0x04, - kStreamHeaderFetch = 0x05, +class QUICHE_EXPORT MoqtDataStreamType { + public: + // Factory functions. + static std::optional FromValue(uint64_t value) { + MoqtDataStreamType stream_type(static_cast(value)); + if (stream_type.IsFetch() || stream_type.IsPadding() || + stream_type.IsSubgroup()) { + return stream_type; + } + return std::nullopt; + } + static MoqtDataStreamType Fetch() { + return MoqtDataStreamType(StreamType::kFetch); + } + static MoqtDataStreamType Padding() { + return MoqtDataStreamType(StreamType::kPadding); + } + static MoqtDataStreamType Subgroup(uint64_t subgroup_id, + uint64_t first_object_id, + bool no_extension_headers) { + if (subgroup_id == 0) { + return MoqtDataStreamType( + no_extension_headers ? StreamType::kSubgroup0NoExtensionHeaders + : StreamType::kSubgroup0WithExtensionHeaders); + } + if (subgroup_id == first_object_id) { + return MoqtDataStreamType( + no_extension_headers + ? StreamType::kSubgroupFirstObjectNoExtensionHeaders + : StreamType::kSubgroupFirstObjectWithExtensionHeaders); + } + return MoqtDataStreamType( + no_extension_headers + ? StreamType::kSubgroupExplicitNoExtensionHeaders + : StreamType::kSubgroupExplicitWithExtensionHeaders); + } + MoqtDataStreamType(const MoqtDataStreamType& other) = default; + bool IsFetch() const { return value_ == StreamType::kFetch; } + bool IsPadding() const { return value_ == StreamType::kPadding; } + bool IsSubgroup() const { + return value_ >= StreamType::kSubgroup0NoExtensionHeaders && + value_ <= StreamType::kSubgroupExplicitWithExtensionHeaders; + } + bool IsSubgroupPresent() const { + return value_ == StreamType::kSubgroupExplicitNoExtensionHeaders || + value_ == StreamType::kSubgroupExplicitWithExtensionHeaders; + } + bool SubgroupIsZero() const { + return value_ == StreamType::kSubgroup0NoExtensionHeaders || + value_ == StreamType::kSubgroup0WithExtensionHeaders; + } + bool SubgroupIsFirstObjectId() const { + return value_ == StreamType::kSubgroupFirstObjectNoExtensionHeaders || + value_ == StreamType::kSubgroupFirstObjectWithExtensionHeaders; + } + bool AreExtensionHeadersPresent() const { + return value_ == StreamType::kSubgroup0WithExtensionHeaders || + value_ == StreamType::kSubgroupFirstObjectWithExtensionHeaders || + value_ == StreamType::kSubgroupExplicitWithExtensionHeaders; + } + uint64_t value() const { return static_cast(value_); } + bool operator==(const MoqtDataStreamType& other) const = default; + enum class StreamType : uint64_t { + kFetch = 0x05, + kSubgroup0NoExtensionHeaders = 0x08, + kSubgroup0WithExtensionHeaders = 0x09, + kSubgroupFirstObjectNoExtensionHeaders = 0x0a, + kSubgroupFirstObjectWithExtensionHeaders = 0x0b, + kSubgroupExplicitNoExtensionHeaders = 0x0c, + kSubgroupExplicitWithExtensionHeaders = 0x0d, + kPadding = 0x26d3, + }; - // Currently QUICHE-specific. All data on a kPadding stream is ignored. - kPadding = 0x26d3, + private: + explicit MoqtDataStreamType(StreamType value) : value_(value) {} + const StreamType value_; }; -enum class QUICHE_EXPORT MoqtDatagramType : uint64_t { - kObject = 0x01, - kObjectStatus = 0x02, +class QUICHE_EXPORT MoqtDatagramType { + public: + MoqtDatagramType(bool has_status, bool has_extension) : value_(0) { + if (has_status) { + value_ |= 0x02; + } + if (has_extension) { + value_ |= 0x01; + } + } + static std::optional FromValue(uint64_t value) { + if (value <= 3) { + return MoqtDatagramType(value); + } + return std::nullopt; + } + bool has_status() const { return value_ & 0x02; } + bool has_extension() const { return value_ & 0x01; } + uint64_t value() const { return value_; } + + private: + uint64_t value_; + explicit MoqtDatagramType(uint64_t value) : value_(value) {} }; enum class QUICHE_EXPORT MoqtMessageType : uint64_t { @@ -130,6 +239,9 @@ enum class QUICHE_EXPORT MoqtMessageType : uint64_t { kFetchOk = 0x18, kFetchError = 0x19, kRequestsBlocked = 0x1a, + kPublish = 0x1d, + kPublishOk = 0x1e, + kPublishError = 0x1f, kClientSetup = 0x20, kServerSetup = 0x21, @@ -160,16 +272,18 @@ enum class QUICHE_EXPORT MoqtError : uint64_t { }; // Error codes used by MoQT to reset streams. -// TODO: update with spec-defined error codes once those are available, see -// . inline constexpr webtransport::StreamErrorCode kResetCodeUnknown = 0x00; -inline constexpr webtransport::StreamErrorCode kResetCodeSubscriptionGone = - 0x01; -inline constexpr webtransport::StreamErrorCode kResetCodeTimedOut = 0x02; +inline constexpr webtransport::StreamErrorCode kResetCodeCanceled = 0x01; +inline constexpr webtransport::StreamErrorCode kResetCodeDeliveryTimeout = 0x02; +inline constexpr webtransport::StreamErrorCode kResetCodeSessionClosed = 0x03; +// TODO(martinduke): This is not in the spec, but is needed. The number might +// change. +inline constexpr webtransport::StreamErrorCode kResetCodeMalformedTrack = 0x04; enum class QUICHE_EXPORT SetupParameter : uint64_t { kPath = 0x1, kMaxRequestId = 0x2, + kAuthorizationToken = 0x3, kMaxAuthTokenCacheSize = 0x4, // QUICHE-specific extensions. @@ -178,39 +292,14 @@ enum class QUICHE_EXPORT SetupParameter : uint64_t { }; enum class QUICHE_EXPORT VersionSpecificParameter : uint64_t { - kAuthorizationToken = 0x1, kDeliveryTimeout = 0x2, + kAuthorizationToken = 0x3, kMaxCacheDuration = 0x4, // QUICHE-specific extensions. kOackWindowSize = 0xbbf1438, }; -enum AuthTokenType : uint64_t { - kOutOfBand = 0x0, - - kMaxAuthTokenType = 0x0, -}; - -enum AuthTokenAliasType : uint64_t { - kDelete = 0x0, - kRegister = 0x1, - kUseAlias = 0x2, - kUseValue = 0x3, - - kMaxValue = 0x3, -}; - -struct AuthToken { - AuthToken(AuthTokenType token_type, absl::string_view token) - : type(token_type), token(token) {} - bool operator==(const AuthToken& other) const { - return type == other.type && token == other.token; - } - AuthTokenType type; - std::string token; -}; - struct VersionSpecificParameters { VersionSpecificParameters() = default; // Likely parameter combinations. @@ -233,12 +322,7 @@ struct VersionSpecificParameters { quic::QuicTimeDelta max_cache_duration = quic::QuicTimeDelta::Infinite(); std::optional oack_window_size; - bool operator==(const VersionSpecificParameters& other) const { - return authorization_token == other.authorization_token && - delivery_timeout == other.delivery_timeout && - max_cache_duration == other.max_cache_duration && - oack_window_size == other.oack_window_size; - } + bool operator==(const VersionSpecificParameters& other) const = default; }; // Used for SUBSCRIBE_ERROR, ANNOUNCE_ERROR, ANNOUNCE_CANCEL, @@ -253,11 +337,9 @@ enum class QUICHE_EXPORT RequestErrorCode : uint64_t { kNamespacePrefixUnknown = 0x4, // SUBSCRIBE_ANNOUNCES_ERROR only. kInvalidRange = 0x5, // SUBSCRIBE_ERROR and FETCH_ERROR only. kNamespacePrefixOverlap = 0x5, // SUBSCRIBE_ANNOUNCES_ERROR only. - kRetryTrackAlias = 0x6, // SUBSCRIBE_ERROR only. kNoObjects = 0x6, // FETCH_ERROR only. kInvalidJoiningSubscribeId = 0x7, // FETCH_ERROR only. kMalformedAuthToken = 0x10, - kUnknownAuthTokenAlias = 0x11, kExpiredAuthToken = 0x12, }; @@ -294,8 +376,14 @@ class TrackNamespace { size_t number_of_elements() const { return tuple_.size(); } // Returns the sum of the lengths of all elements in the tuple. size_t total_length() const { return length_; } - bool operator==(const TrackNamespace& other) const; - bool operator<(const TrackNamespace& other) const; + + auto operator<=>(const TrackNamespace& other) const { + return std::lexicographical_compare_three_way( + tuple_.cbegin(), tuple_.cend(), other.tuple_.cbegin(), + other.tuple_.cend()); + } + bool operator==(const TrackNamespace&) const = default; + const std::vector& tuple() const { return tuple_; } template @@ -345,13 +433,8 @@ class FullTrackName { } void set_name(absl::string_view name); size_t length() const { return namespace_.total_length() + name_.length(); } - bool operator==(const FullTrackName& other) const { - return name_ == other.name_ && namespace_ == other.namespace_; - } - bool operator<(const FullTrackName& other) const { - return namespace_ < other.namespace_ || - (namespace_ == other.namespace_ && name_ < other.name_); - } + + auto operator<=>(const FullTrackName&) const = default; template friend H AbslHashValue(H h, const FullTrackName& m) { return H::combine(std::move(h), m.namespace_.tuple(), m.name_); @@ -366,37 +449,21 @@ class FullTrackName { std::string name_ = ""; }; -// These are absolute sequence numbers. +// Location as defined in +// https://moq-wg.github.io/moq-transport/draft-ietf-moq-transport.html#location-structure struct Location { - uint64_t group; - uint64_t subgroup; - uint64_t object; - Location() : Location(0, 0) {} - // There is a lot of code from before subgroups. Assume there's one subgroup - // with ID 0 per group. - Location(uint64_t group, uint64_t object) : Location(group, 0, object) {} - Location(uint64_t group, uint64_t subgroup, uint64_t object) - : group(group), subgroup(subgroup), object(object) {} - bool operator==(const Location& other) const { - return group == other.group && object == other.object; - } - // These are temporal ordering comparisons, so subgroup ID doesn't matter. - bool operator<(const Location& other) const { - return group < other.group || - (group == other.group && object < other.object); - } - bool operator<=(const Location& other) const { - return (group < other.group || - (group == other.group && object <= other.object)); - } - bool operator>(const Location& other) const { return !(*this <= other); } - Location& operator=(Location other) { - group = other.group; - subgroup = other.subgroup; - object = other.object; - return *this; - } - Location next() const { return Location{group, subgroup, object + 1}; } + uint64_t group = 0; + uint64_t object = 0; + + Location() = default; + Location(uint64_t group, uint64_t object) : group(group), object(object) {} + + // Location order as described in + // https://moq-wg.github.io/moq-transport/draft-ietf-moq-transport.html#location-structure + auto operator<=>(const Location&) const = default; + + Location next() const { return Location(group, object + 1); } + template friend H AbslHashValue(H h, const Location& m); @@ -410,20 +477,7 @@ struct SubgroupPriority { uint8_t publisher_priority = 0xf0; uint64_t subgroup_id = 0; - bool operator==(const SubgroupPriority& other) const { - return publisher_priority == other.publisher_priority && - subgroup_id == other.subgroup_id; - } - bool operator<(const SubgroupPriority& other) const { - return publisher_priority < other.publisher_priority || - (publisher_priority == other.publisher_priority && - subgroup_id < other.subgroup_id); - } - bool operator<=(const SubgroupPriority& other) const { - return (publisher_priority < other.publisher_priority || - (publisher_priority == other.publisher_priority && - subgroup_id <= other.subgroup_id)); - } + auto operator<=>(const SubgroupPriority&) const = default; }; template @@ -533,11 +587,9 @@ enum class QUICHE_EXPORT MoqtForwardingPreference { enum class QUICHE_EXPORT MoqtObjectStatus : uint64_t { kNormal = 0x0, kObjectDoesNotExist = 0x1, - kGroupDoesNotExist = 0x2, kEndOfGroup = 0x3, - kEndOfTrackAndGroup = 0x4, - kEndOfTrack = 0x5, - kInvalidObjectStatus = 0x6, + kEndOfTrack = 0x4, + kInvalidObjectStatus = 0x5, }; MoqtObjectStatus IntegerToObjectStatus(uint64_t integer); @@ -551,7 +603,7 @@ struct QUICHE_EXPORT MoqtObject { MoqtPriority publisher_priority; std::string extension_headers; // Raw, unparsed extension headers. MoqtObjectStatus object_status; - std::optional subgroup_id; + uint64_t subgroup_id; uint64_t payload_length; }; @@ -565,7 +617,6 @@ enum class QUICHE_EXPORT MoqtFilterType : uint64_t { struct QUICHE_EXPORT MoqtSubscribe { uint64_t request_id; - uint64_t track_alias; FullTrackName full_track_name; MoqtPriority subscriber_priority; std::optional group_order; @@ -578,6 +629,7 @@ struct QUICHE_EXPORT MoqtSubscribe { struct QUICHE_EXPORT MoqtSubscribeOk { uint64_t request_id; + uint64_t track_alias; // The message uses ms, but expires is in us. quic::QuicTimeDelta expires = quic::QuicTimeDelta::FromMilliseconds(0); MoqtDeliveryOrder group_order; @@ -590,11 +642,10 @@ struct QUICHE_EXPORT MoqtSubscribeError { uint64_t request_id; RequestErrorCode error_code; std::string reason_phrase; - uint64_t track_alias; }; struct QUICHE_EXPORT MoqtUnsubscribe { - uint64_t subscribe_id; + uint64_t request_id; }; enum class QUICHE_EXPORT SubscribeDoneCode : uint64_t { @@ -605,13 +656,14 @@ enum class QUICHE_EXPORT SubscribeDoneCode : uint64_t { kGoingAway = 0x4, kExpired = 0x5, kTooFarBehind = 0x6, + kMalformedTrack = 0x7, }; struct QUICHE_EXPORT MoqtSubscribeDone { - uint64_t subscribe_id; + uint64_t request_id; SubscribeDoneCode status_code; uint64_t stream_count; - std::string reason_phrase; + std::string error_reason; }; struct QUICHE_EXPORT MoqtSubscribeUpdate { @@ -624,24 +676,31 @@ struct QUICHE_EXPORT MoqtSubscribeUpdate { }; struct QUICHE_EXPORT MoqtAnnounce { + uint64_t request_id; TrackNamespace track_namespace; VersionSpecificParameters parameters; }; struct QUICHE_EXPORT MoqtAnnounceOk { - TrackNamespace track_namespace; + uint64_t request_id; }; struct QUICHE_EXPORT MoqtAnnounceError { - TrackNamespace track_namespace; + uint64_t request_id; RequestErrorCode error_code; - std::string reason_phrase; + std::string error_reason; }; struct QUICHE_EXPORT MoqtUnannounce { TrackNamespace track_namespace; }; +struct QUICHE_EXPORT MoqtAnnounceCancel { + TrackNamespace track_namespace; + RequestErrorCode error_code; + std::string error_reason; +}; + enum class QUICHE_EXPORT MoqtTrackStatusCode : uint64_t { kInProgress = 0x0, kDoesNotExist = 0x1, @@ -663,22 +722,16 @@ inline bool DoesTrackStatusImplyHavingData(MoqtTrackStatusCode code) { return false; } -struct QUICHE_EXPORT MoqtTrackStatus { +struct QUICHE_EXPORT MoqtTrackStatusRequest { + uint64_t request_id; FullTrackName full_track_name; - MoqtTrackStatusCode status_code; - uint64_t last_group; - uint64_t last_object; VersionSpecificParameters parameters; }; -struct QUICHE_EXPORT MoqtAnnounceCancel { - TrackNamespace track_namespace; - RequestErrorCode error_code; - std::string reason_phrase; -}; - -struct QUICHE_EXPORT MoqtTrackStatusRequest { - FullTrackName full_track_name; +struct QUICHE_EXPORT MoqtTrackStatus { + uint64_t request_id; + MoqtTrackStatusCode status_code; + Location largest_location; VersionSpecificParameters parameters; }; @@ -687,18 +740,19 @@ struct QUICHE_EXPORT MoqtGoAway { }; struct QUICHE_EXPORT MoqtSubscribeAnnounces { + uint64_t request_id; TrackNamespace track_namespace; VersionSpecificParameters parameters; }; struct QUICHE_EXPORT MoqtSubscribeAnnouncesOk { - TrackNamespace track_namespace; + uint64_t request_id; }; struct QUICHE_EXPORT MoqtSubscribeAnnouncesError { - TrackNamespace track_namespace; + uint64_t request_id; RequestErrorCode error_code; - std::string reason_phrase; + std::string error_reason; }; struct QUICHE_EXPORT MoqtUnsubscribeAnnounces { @@ -711,52 +765,120 @@ struct QUICHE_EXPORT MoqtMaxRequestId { enum class QUICHE_EXPORT FetchType : uint64_t { kStandalone = 0x1, - kJoining = 0x2, + kRelativeJoining = 0x2, + kAbsoluteJoining = 0x3, }; -struct JoiningFetch { - JoiningFetch(uint64_t joining_subscribe_id, uint64_t preceding_group_offset) - : joining_subscribe_id(joining_subscribe_id), - preceding_group_offset(preceding_group_offset) {} - uint64_t joining_subscribe_id; - uint64_t preceding_group_offset; -}; - -struct QUICHE_EXPORT MoqtFetch { - uint64_t fetch_id; - MoqtPriority subscriber_priority; - std::optional group_order; - // If joining_fetch has a value, then the parser will not populate the name - // and ranges. The session will populate them instead. - std::optional joining_fetch; +struct StandaloneFetch { + StandaloneFetch() = default; + StandaloneFetch(FullTrackName full_track_name, Location start_object, + uint64_t end_group, std::optional end_object) + : full_track_name(full_track_name), + start_object(start_object), + end_group(end_group), + end_object(end_object) {} FullTrackName full_track_name; Location start_object; // subgroup is ignored uint64_t end_group; std::optional end_object; + bool operator==(const StandaloneFetch& other) const { + return full_track_name == other.full_track_name && + start_object == other.start_object && end_group == other.end_group && + end_object == other.end_object; + } + bool operator!=(const StandaloneFetch& other) const { + return !(*this == other); + } +}; + +struct JoiningFetchRelative { + JoiningFetchRelative(uint64_t joining_subscribe_id, uint64_t joining_start) + : joining_subscribe_id(joining_subscribe_id), + joining_start(joining_start) {} + uint64_t joining_subscribe_id; + uint64_t joining_start; + bool operator==(const JoiningFetchRelative& other) const { + return joining_subscribe_id == other.joining_subscribe_id && + joining_start == other.joining_start; + } + bool operator!=(const JoiningFetchRelative& other) const { + return !(*this == other); + } +}; + +struct JoiningFetchAbsolute { + JoiningFetchAbsolute(uint64_t joining_subscribe_id, uint64_t joining_start) + : joining_subscribe_id(joining_subscribe_id), + joining_start(joining_start) {} + uint64_t joining_subscribe_id; + uint64_t joining_start; + bool operator==(const JoiningFetchAbsolute& other) const { + return joining_subscribe_id == other.joining_subscribe_id && + joining_start == other.joining_start; + } + bool operator!=(const JoiningFetchAbsolute& other) const { + return !(*this == other); + } +}; + +struct QUICHE_EXPORT MoqtFetch { + uint64_t request_id; + MoqtPriority subscriber_priority; + std::optional group_order; + std::variant + fetch; VersionSpecificParameters parameters; }; -struct QUICHE_EXPORT MoqtFetchCancel { - uint64_t subscribe_id; -}; - struct QUICHE_EXPORT MoqtFetchOk { - uint64_t subscribe_id; + uint64_t request_id; MoqtDeliveryOrder group_order; - Location largest_id; // subgroup is ignored + bool end_of_track; + Location end_location; VersionSpecificParameters parameters; }; struct QUICHE_EXPORT MoqtFetchError { - uint64_t subscribe_id; + uint64_t request_id; RequestErrorCode error_code; - std::string reason_phrase; + std::string error_reason; +}; + +struct QUICHE_EXPORT MoqtFetchCancel { + uint64_t request_id; }; struct QUICHE_EXPORT MoqtRequestsBlocked { uint64_t max_request_id; }; +struct QUICHE_EXPORT MoqtPublish { + uint64_t request_id; + FullTrackName full_track_name; + uint64_t track_alias; + MoqtDeliveryOrder group_order; + std::optional largest_location; + bool forward; + VersionSpecificParameters parameters; +}; + +struct QUICHE_EXPORT MoqtPublishOk { + uint64_t request_id; + bool forward; + MoqtPriority subscriber_priority; + MoqtDeliveryOrder group_order; + MoqtFilterType filter_type; + std::optional start; + std::optional end_group; + VersionSpecificParameters parameters; +}; + +struct QUICHE_EXPORT MoqtPublishError { + uint64_t request_id; + RequestErrorCode error_code; + std::string error_reason; +}; + // All of the four values in this message are encoded as varints. // `delta_from_deadline` is encoded as an absolute value, with the lowest bit // indicating the sign (0 if positive). 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 0428f7ea58..324fa67d12 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 @@ -65,33 +65,39 @@ void MoqtOutgoingQueue::AddRawObject(MoqtObjectStatus status, Location sequence{current_group_id_, queue_.back().size()}; bool fin = forwarding_preference_ == MoqtForwardingPreference::kSubgroup && status == MoqtObjectStatus::kEndOfGroup; - queue_.back().push_back( - CachedObject{sequence, status, publisher_priority_, - std::make_shared(std::move(payload)), - clock_->ApproximateNow(), fin}); + queue_.back().push_back(CachedObject{ + PublishedObjectMetadata{sequence, 0, status, publisher_priority_, + clock_->ApproximateNow()}, + std::make_shared(std::move(payload)), fin}); for (MoqtObjectListener* listener : listeners_) { - listener->OnNewObjectAvailable(sequence); + listener->OnNewObjectAvailable(sequence, /*subgroup=*/0); } } std::optional MoqtOutgoingQueue::GetCachedObject( - Location sequence) const { - if (sequence.group < first_group_in_queue()) { - return PublishedObject{Location{sequence.group, sequence.object}, - MoqtObjectStatus::kGroupDoesNotExist, - publisher_priority_, quiche::QuicheMemSlice(), - clock_->ApproximateNow()}; - } - if (sequence.group > current_group_id_) { + uint64_t group, uint64_t subgroup, uint64_t object) const { + QUICHE_DCHECK_EQ(subgroup, 0u); + if (group < first_group_in_queue()) { + if (object == 0) { + return PublishedObject{PublishedObjectMetadata{ + Location(group, object), /*subgroup=*/0, + MoqtObjectStatus::kEndOfGroup, + publisher_priority_, clock_->ApproximateNow()}, + quiche::QuicheMemSlice{}}; + } return std::nullopt; } - const std::vector& group = - queue_[sequence.group - first_group_in_queue()]; - if (sequence.object >= group.size()) { + if (group > current_group_id_) { return std::nullopt; } - QUICHE_DCHECK(sequence == group[sequence.object].sequence); - return CachedObjectToPublishedObject(group[sequence.object]); + const std::vector& group_objects = + queue_[group - first_group_in_queue()]; + if (object >= group_objects.size()) { + return std::nullopt; + } + QUICHE_DCHECK(Location(group, object) == + group_objects[object].metadata.location); + return CachedObjectToPublishedObject(group_objects[object]); } std::vector MoqtOutgoingQueue::GetCachedObjectsInRange( @@ -100,8 +106,8 @@ std::vector MoqtOutgoingQueue::GetCachedObjectsInRange( SubscribeWindow window(start, end.group, end.object); for (const Group& group : queue_) { for (const CachedObject& object : group) { - if (window.InWindow(object.sequence)) { - sequences.push_back(object.sequence); + if (window.InWindow(object.metadata.location)) { + sequences.push_back(object.metadata.location); } } } @@ -169,18 +175,14 @@ std::unique_ptr MoqtOutgoingQueue::Fetch( MoqtFetchTask::GetNextObjectResult MoqtOutgoingQueue::FetchTask::GetNextObject( PublishedObject& object) { - for (;;) { + MoqtFetchTask::GetNextObjectResult result; + do { + result = GetNextObjectInner(object); // The specification for FETCH requires that all missing objects are simply // skipped. - MoqtFetchTask::GetNextObjectResult result = GetNextObjectInner(object); - bool missing_object = - result == kSuccess && - (object.status == MoqtObjectStatus::kObjectDoesNotExist || - object.status == MoqtObjectStatus::kGroupDoesNotExist); - if (!missing_object) { - return result; - } - } + } while (result == MoqtFetchTask::GetNextObjectResult::kSuccess && + object.metadata.status == MoqtObjectStatus::kObjectDoesNotExist); + return result; } MoqtFetchTask::GetNextObjectResult @@ -192,14 +194,24 @@ MoqtOutgoingQueue::FetchTask::GetNextObjectInner(PublishedObject& object) { return kEof; } - std::optional result = - queue_->GetCachedObject(objects_.front()); + std::optional result = queue_->GetCachedObject( + objects_.front().group, 0, objects_.front().object); if (!result.has_value()) { - status_ = absl::InternalError("Previously known object became unknown."); - return kError; + // Create a synthetic object of status kEndOfGroup (if the object ID is + // zero) or kObjectDoesNotExist, which will result in the Fetch response + // skipping it. + object.metadata.location = objects_.front(); + object.metadata.subgroup = 0; + object.metadata.publisher_priority = queue_->publisher_priority_; + object.metadata.status = object.metadata.location.object == 0 + ? MoqtObjectStatus::kEndOfGroup + : MoqtObjectStatus::kObjectDoesNotExist; + object.metadata.arrival_time = queue_->clock_->ApproximateNow(); + object.payload = quiche::QuicheMemSlice(); + object.fin_after_this = false; + } else { + object = *std::move(result); } - - object = *std::move(result); objects_.pop_front(); return kSuccess; } 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 c6302fb752..c61b22002f 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 @@ -55,9 +55,7 @@ class MoqtOutgoingQueue : public MoqtTrackPublisher { // MoqtTrackPublisher implementation. const FullTrackName& GetTrackName() const override { return track_; } std::optional GetCachedObject( - Location sequence) const override; - std::vector GetCachedObjectsInRange(Location start, - Location end) const override; + uint64_t group, uint64_t subgroup, uint64_t min_object) const override; void AddObjectListener(MoqtObjectListener* listener) override { listeners_.insert(listener); listener->OnSubscribeAccepted(); @@ -98,6 +96,9 @@ class MoqtOutgoingQueue : public MoqtTrackPublisher { // Sends an "End of Track" object. void Close(); + std::vector GetCachedObjectsInRange(Location start, + Location end) const; + private: // The number of recent groups to keep around for newly joined subscribers. static constexpr size_t kMaxQueuedGroups = 3; @@ -122,7 +123,7 @@ class MoqtOutgoingQueue : public MoqtTrackPublisher { MoqtFetchError error(0, StatusToRequestErrorCode(status_), std::string(status_.message())); error.error_code = StatusToRequestErrorCode(status_); - error.reason_phrase = status_.message(); + error.error_reason = status_.message(); std::move(callback)(error); return; } @@ -134,11 +135,13 @@ class MoqtOutgoingQueue : public MoqtTrackPublisher { } MoqtFetchOk ok; ok.group_order = MoqtDeliveryOrder::kAscending; - ok.largest_id = *(objects_.crbegin()); - if (objects_.size() > 1 && *(objects_.cbegin()) > ok.largest_id) { + ok.end_location = *(objects_.crbegin()); + if (objects_.size() > 1 && *(objects_.cbegin()) > ok.end_location) { ok.group_order = MoqtDeliveryOrder::kDescending; - ok.largest_id = *(objects_.cbegin()); + ok.end_location = *(objects_.cbegin()); } + ok.end_of_track = + queue_->closed_ && ok.end_location == queue_->GetLargestLocation(); std::move(callback)(ok); } 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 01cd6c1f35..498ea148fe 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 @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include "absl/base/casts.h" #include "absl/cleanup/cleanup.h" @@ -56,18 +58,8 @@ uint64_t SignedVarintUnserializedForm(uint64_t value) { return value >> 1; } -bool IsAllowedStreamType(uint64_t value) { - constexpr std::array kAllowedStreamTypes = { - MoqtDataStreamType::kStreamHeaderSubgroup, - MoqtDataStreamType::kStreamHeaderFetch, MoqtDataStreamType::kPadding}; - for (MoqtDataStreamType type : kAllowedStreamTypes) { - if (static_cast(type) == value) { - return true; - } - } - return false; -} - +// |fin_read| is set to true if there is a FIN anywhere before the end of the +// varint. std::optional ReadVarInt62FromStream(quiche::ReadStream& stream, bool& fin_read) { fin_read = false; @@ -84,6 +76,9 @@ std::optional ReadVarInt62FromStream(quiche::ReadStream& stream, size_t varint_size = 1 << ((absl::bit_cast(first_byte) & 0b11000000) >> 6); if (stream.ReadableBytes() < varint_size) { + if (peek_result.all_data_received) { + fin_read = true; + } return std::nullopt; } @@ -132,39 +127,6 @@ bool ParseKeyValuePairList(quic::QuicDataReader& reader, return true; } -void KeyValuePairListToMoqtSessionParameters(const KeyValuePairList& parameters, - MoqtSessionParameters& out) { - parameters.ForEach( - [&](uint64_t key, uint64_t value) { - SetupParameter parameter = static_cast(key); - switch (parameter) { - case SetupParameter::kMaxRequestId: - out.max_request_id = value; - break; - case SetupParameter::kMaxAuthTokenCacheSize: - out.max_auth_token_cache_size = value; - break; - case SetupParameter::kSupportObjectAcks: - out.support_object_acks = (value == 1); - break; - default: - break; - } - return true; - }, - [&](uint64_t key, absl::string_view value) { - SetupParameter parameter = static_cast(key); - switch (parameter) { - case SetupParameter::kPath: - out.path = value; - break; - default: - break; - } - return true; - }); -} - } // namespace void MoqtControlParser::ReadAndDispatchMessages() { @@ -329,6 +291,15 @@ size_t MoqtControlParser::ProcessMessage(absl::string_view data, case MoqtMessageType::kRequestsBlocked: bytes_read = ProcessRequestsBlocked(reader); break; + case MoqtMessageType::kPublish: + bytes_read = ProcessPublish(reader); + break; + case MoqtMessageType::kPublishOk: + bytes_read = ProcessPublishOk(reader); + break; + case MoqtMessageType::kPublishError: + bytes_read = ProcessPublishError(reader); + break; case moqt::MoqtMessageType::kObjectAck: bytes_read = ProcessObjectAck(reader); break; @@ -369,7 +340,9 @@ size_t MoqtControlParser::ProcessClientSetup(quic::QuicDataReader& reader) { ParseError(error, "Client SETUP contains invalid parameters"); return 0; } - KeyValuePairListToMoqtSessionParameters(parameters, setup.parameters); + if (!KeyValuePairListToMoqtSessionParameters(parameters, setup.parameters)) { + return 0; + } // TODO(martinduke): Validate construction of the PATH (Sec 8.3.2.1) visitor_.OnClientSetupMessage(setup); return reader.PreviouslyReadPayload().length(); @@ -394,7 +367,9 @@ size_t MoqtControlParser::ProcessServerSetup(quic::QuicDataReader& reader) { ParseError(error, "Server SETUP contains invalid parameters"); return 0; } - KeyValuePairListToMoqtSessionParameters(parameters, setup.parameters); + if (!KeyValuePairListToMoqtSessionParameters(parameters, setup.parameters)) { + return 0; + } visitor_.OnServerSetupMessage(setup); return reader.PreviouslyReadPayload().length(); } @@ -404,7 +379,6 @@ size_t MoqtControlParser::ProcessSubscribe(quic::QuicDataReader& reader) { uint64_t filter, group, object; uint8_t group_order, forward; if (!reader.ReadVarInt62(&subscribe.request_id) || - !reader.ReadVarInt62(&subscribe.track_alias) || !ReadFullTrackName(reader, subscribe.full_track_name) || !reader.ReadUInt8(&subscribe.subscriber_priority) || !reader.ReadUInt8(&group_order) || !reader.ReadUInt8(&forward) || @@ -470,6 +444,7 @@ size_t MoqtControlParser::ProcessSubscribeOk(quic::QuicDataReader& reader) { uint8_t group_order; uint8_t content_exists; if (!reader.ReadVarInt62(&subscribe_ok.request_id) || + !reader.ReadVarInt62(&subscribe_ok.track_alias) || !reader.ReadVarInt62(&milliseconds) || !reader.ReadUInt8(&group_order) || !reader.ReadUInt8(&content_exists)) { return 0; @@ -513,8 +488,7 @@ size_t MoqtControlParser::ProcessSubscribeError(quic::QuicDataReader& reader) { uint64_t error_code; if (!reader.ReadVarInt62(&subscribe_error.request_id) || !reader.ReadVarInt62(&error_code) || - !reader.ReadStringVarInt62(subscribe_error.reason_phrase) || - !reader.ReadVarInt62(&subscribe_error.track_alias)) { + !reader.ReadStringVarInt62(subscribe_error.reason_phrase)) { return 0; } subscribe_error.error_code = static_cast(error_code); @@ -524,7 +498,7 @@ size_t MoqtControlParser::ProcessSubscribeError(quic::QuicDataReader& reader) { size_t MoqtControlParser::ProcessUnsubscribe(quic::QuicDataReader& reader) { MoqtUnsubscribe unsubscribe; - if (!reader.ReadVarInt62(&unsubscribe.subscribe_id)) { + if (!reader.ReadVarInt62(&unsubscribe.request_id)) { return 0; } visitor_.OnUnsubscribeMessage(unsubscribe); @@ -534,10 +508,10 @@ size_t MoqtControlParser::ProcessUnsubscribe(quic::QuicDataReader& reader) { size_t MoqtControlParser::ProcessSubscribeDone(quic::QuicDataReader& reader) { MoqtSubscribeDone subscribe_done; uint64_t value; - if (!reader.ReadVarInt62(&subscribe_done.subscribe_id) || + if (!reader.ReadVarInt62(&subscribe_done.request_id) || !reader.ReadVarInt62(&value) || !reader.ReadVarInt62(&subscribe_done.stream_count) || - !reader.ReadStringVarInt62(subscribe_done.reason_phrase)) { + !reader.ReadStringVarInt62(subscribe_done.error_reason)) { return 0; } subscribe_done.status_code = static_cast(value); @@ -588,7 +562,8 @@ size_t MoqtControlParser::ProcessSubscribeUpdate(quic::QuicDataReader& reader) { size_t MoqtControlParser::ProcessAnnounce(quic::QuicDataReader& reader) { MoqtAnnounce announce; - if (!ReadTrackNamespace(reader, announce.track_namespace)) { + if (!reader.ReadVarInt62(&announce.request_id) || + !ReadTrackNamespace(reader, announce.track_namespace)) { return 0; } KeyValuePairList parameters; @@ -610,7 +585,7 @@ size_t MoqtControlParser::ProcessAnnounce(quic::QuicDataReader& reader) { size_t MoqtControlParser::ProcessAnnounceOk(quic::QuicDataReader& reader) { MoqtAnnounceOk announce_ok; - if (!ReadTrackNamespace(reader, announce_ok.track_namespace)) { + if (!reader.ReadVarInt62(&announce_ok.request_id)) { return 0; } visitor_.OnAnnounceOkMessage(announce_ok); @@ -619,12 +594,10 @@ size_t MoqtControlParser::ProcessAnnounceOk(quic::QuicDataReader& reader) { size_t MoqtControlParser::ProcessAnnounceError(quic::QuicDataReader& reader) { MoqtAnnounceError announce_error; - if (!ReadTrackNamespace(reader, announce_error.track_namespace)) { - return 0; - } uint64_t error_code; - if (!reader.ReadVarInt62(&error_code) || - !reader.ReadStringVarInt62(announce_error.reason_phrase)) { + if (!reader.ReadVarInt62(&announce_error.request_id) || + !reader.ReadVarInt62(&error_code) || + !reader.ReadStringVarInt62(announce_error.error_reason)) { return 0; } announce_error.error_code = static_cast(error_code); @@ -639,7 +612,7 @@ size_t MoqtControlParser::ProcessAnnounceCancel(quic::QuicDataReader& reader) { } uint64_t error_code; if (!reader.ReadVarInt62(&error_code) || - !reader.ReadStringVarInt62(announce_cancel.reason_phrase)) { + !reader.ReadStringVarInt62(announce_cancel.error_reason)) { return 0; } announce_cancel.error_code = static_cast(error_code); @@ -650,6 +623,9 @@ size_t MoqtControlParser::ProcessAnnounceCancel(quic::QuicDataReader& reader) { size_t MoqtControlParser::ProcessTrackStatusRequest( quic::QuicDataReader& reader) { MoqtTrackStatusRequest track_status_request; + if (!reader.ReadVarInt62(&track_status_request.request_id)) { + return 0; + } if (!ReadFullTrackName(reader, track_status_request.full_track_name)) { return 0; } @@ -681,16 +657,14 @@ size_t MoqtControlParser::ProcessUnannounce(quic::QuicDataReader& reader) { size_t MoqtControlParser::ProcessTrackStatus(quic::QuicDataReader& reader) { MoqtTrackStatus track_status; - if (!ReadFullTrackName(reader, track_status.full_track_name)) { + uint64_t status_code; + if (!reader.ReadVarInt62(&track_status.request_id) || + !reader.ReadVarInt62(&status_code) || + !reader.ReadVarInt62(&track_status.largest_location.group) || + !reader.ReadVarInt62(&track_status.largest_location.object)) { return 0; } - uint64_t value; - if (!reader.ReadVarInt62(&value) || - !reader.ReadVarInt62(&track_status.last_group) || - !reader.ReadVarInt62(&track_status.last_object)) { - return 0; - } - track_status.status_code = static_cast(value); + track_status.status_code = static_cast(status_code); KeyValuePairList parameters; if (!ParseKeyValuePairList(reader, parameters)) { return 0; @@ -720,7 +694,8 @@ size_t MoqtControlParser::ProcessGoAway(quic::QuicDataReader& reader) { size_t MoqtControlParser::ProcessSubscribeAnnounces( quic::QuicDataReader& reader) { MoqtSubscribeAnnounces subscribe_announces; - if (!ReadTrackNamespace(reader, subscribe_announces.track_namespace)) { + if (!reader.ReadVarInt62(&subscribe_announces.request_id) || + !ReadTrackNamespace(reader, subscribe_announces.track_namespace)) { return 0; } KeyValuePairList parameters; @@ -743,7 +718,7 @@ size_t MoqtControlParser::ProcessSubscribeAnnounces( size_t MoqtControlParser::ProcessSubscribeAnnouncesOk( quic::QuicDataReader& reader) { MoqtSubscribeAnnouncesOk subscribe_namespace_ok; - if (!ReadTrackNamespace(reader, subscribe_namespace_ok.track_namespace)) { + if (!reader.ReadVarInt62(&subscribe_namespace_ok.request_id)) { return 0; } visitor_.OnSubscribeAnnouncesOkMessage(subscribe_namespace_ok); @@ -754,9 +729,9 @@ size_t MoqtControlParser::ProcessSubscribeAnnouncesError( quic::QuicDataReader& reader) { MoqtSubscribeAnnouncesError subscribe_namespace_error; uint64_t error_code; - if (!ReadTrackNamespace(reader, subscribe_namespace_error.track_namespace) || + if (!reader.ReadVarInt62(&subscribe_namespace_error.request_id) || !reader.ReadVarInt62(&error_code) || - !reader.ReadStringVarInt62(subscribe_namespace_error.reason_phrase)) { + !reader.ReadStringVarInt62(subscribe_namespace_error.error_reason)) { return 0; } subscribe_namespace_error.error_code = @@ -787,9 +762,8 @@ size_t MoqtControlParser::ProcessMaxRequestId(quic::QuicDataReader& reader) { size_t MoqtControlParser::ProcessFetch(quic::QuicDataReader& reader) { MoqtFetch fetch; uint8_t group_order; - uint64_t end_object; uint64_t type; - if (!reader.ReadVarInt62(&fetch.fetch_id) || + if (!reader.ReadVarInt62(&fetch.request_id) || !reader.ReadUInt8(&fetch.subscriber_priority) || !reader.ReadUInt8(&group_order) || !reader.ReadVarInt62(&type)) { return 0; @@ -799,32 +773,45 @@ size_t MoqtControlParser::ProcessFetch(quic::QuicDataReader& reader) { return 0; } switch (static_cast(type)) { - case FetchType::kJoining: { + case FetchType::kAbsoluteJoining: { uint64_t joining_subscribe_id; - uint64_t preceding_group_offset; + uint64_t joining_start; if (!reader.ReadVarInt62(&joining_subscribe_id) || - !reader.ReadVarInt62(&preceding_group_offset)) { + !reader.ReadVarInt62(&joining_start)) { return 0; } - fetch.joining_fetch = - JoiningFetch{joining_subscribe_id, preceding_group_offset}; + fetch.fetch = JoiningFetchAbsolute{joining_subscribe_id, joining_start}; + break; + } + case FetchType::kRelativeJoining: { + uint64_t joining_subscribe_id; + uint64_t joining_start; + if (!reader.ReadVarInt62(&joining_subscribe_id) || + !reader.ReadVarInt62(&joining_start)) { + return 0; + } + fetch.fetch = JoiningFetchRelative{joining_subscribe_id, joining_start}; break; } case FetchType::kStandalone: { - fetch.joining_fetch = std::nullopt; - if (!ReadFullTrackName(reader, fetch.full_track_name) || - !reader.ReadVarInt62(&fetch.start_object.group) || - !reader.ReadVarInt62(&fetch.start_object.object) || - !reader.ReadVarInt62(&fetch.end_group) || + fetch.fetch = StandaloneFetch(); + StandaloneFetch& standalone_fetch = + std::get(fetch.fetch); + uint64_t end_object; + if (!ReadFullTrackName(reader, standalone_fetch.full_track_name) || + !reader.ReadVarInt62(&standalone_fetch.start_object.group) || + !reader.ReadVarInt62(&standalone_fetch.start_object.object) || + !reader.ReadVarInt62(&standalone_fetch.end_group) || !reader.ReadVarInt62(&end_object)) { return 0; } - fetch.end_object = + standalone_fetch.end_object = end_object == 0 ? std::optional() : (end_object - 1); - if (fetch.end_group < fetch.start_object.group || - (fetch.end_group == fetch.start_object.group && - fetch.end_object.has_value() && - *fetch.end_object < fetch.start_object.object)) { + if (standalone_fetch.end_group < standalone_fetch.start_object.group || + (standalone_fetch.end_group == standalone_fetch.start_object.group && + standalone_fetch.end_object.has_value() && + *standalone_fetch.end_object < + standalone_fetch.start_object.object)) { ParseError("End object comes before start object in FETCH"); return 0; } @@ -850,23 +837,14 @@ size_t MoqtControlParser::ProcessFetch(quic::QuicDataReader& reader) { return reader.PreviouslyReadPayload().length(); } -size_t MoqtControlParser::ProcessFetchCancel(quic::QuicDataReader& reader) { - MoqtFetchCancel fetch_cancel; - if (!reader.ReadVarInt62(&fetch_cancel.subscribe_id)) { - return 0; - } - visitor_.OnFetchCancelMessage(fetch_cancel); - return reader.PreviouslyReadPayload().length(); -} - size_t MoqtControlParser::ProcessFetchOk(quic::QuicDataReader& reader) { MoqtFetchOk fetch_ok; - uint8_t group_order; + uint8_t group_order, end_of_track; KeyValuePairList parameters; - if (!reader.ReadVarInt62(&fetch_ok.subscribe_id) || - !reader.ReadUInt8(&group_order) || - !reader.ReadVarInt62(&fetch_ok.largest_id.group) || - !reader.ReadVarInt62(&fetch_ok.largest_id.object) || + if (!reader.ReadVarInt62(&fetch_ok.request_id) || + !reader.ReadUInt8(&group_order) || !reader.ReadUInt8(&end_of_track) || + !reader.ReadVarInt62(&fetch_ok.end_location.group) || + !reader.ReadVarInt62(&fetch_ok.end_location.object) || !ParseKeyValuePairList(reader, parameters)) { return 0; } @@ -874,12 +852,17 @@ size_t MoqtControlParser::ProcessFetchOk(quic::QuicDataReader& reader) { ParseError("Invalid group order value in FETCH_OK"); return 0; } + if (end_of_track > 0x01) { + ParseError("Invalid end of track value in FETCH_OK"); + return 0; + } if (!ValidateVersionSpecificParameters(parameters, MoqtMessageType::kFetchOk)) { ParseError("FETCH_OK message contains invalid parameters"); return 0; } fetch_ok.group_order = static_cast(group_order); + fetch_ok.end_of_track = end_of_track == 1; if (!KeyValuePairListToVersionSpecificParameters(parameters, fetch_ok.parameters)) { return 0; @@ -891,9 +874,9 @@ size_t MoqtControlParser::ProcessFetchOk(quic::QuicDataReader& reader) { size_t MoqtControlParser::ProcessFetchError(quic::QuicDataReader& reader) { MoqtFetchError fetch_error; uint64_t error_code; - if (!reader.ReadVarInt62(&fetch_error.subscribe_id) || + if (!reader.ReadVarInt62(&fetch_error.request_id) || !reader.ReadVarInt62(&error_code) || - !reader.ReadStringVarInt62(fetch_error.reason_phrase)) { + !reader.ReadStringVarInt62(fetch_error.error_reason)) { return 0; } fetch_error.error_code = static_cast(error_code); @@ -901,6 +884,15 @@ size_t MoqtControlParser::ProcessFetchError(quic::QuicDataReader& reader) { return reader.PreviouslyReadPayload().length(); } +size_t MoqtControlParser::ProcessFetchCancel(quic::QuicDataReader& reader) { + MoqtFetchCancel fetch_cancel; + if (!reader.ReadVarInt62(&fetch_cancel.request_id)) { + return 0; + } + visitor_.OnFetchCancelMessage(fetch_cancel); + return reader.PreviouslyReadPayload().length(); +} + size_t MoqtControlParser::ProcessRequestsBlocked(quic::QuicDataReader& reader) { MoqtRequestsBlocked requests_blocked; if (!reader.ReadVarInt62(&requests_blocked.max_request_id)) { @@ -910,6 +902,136 @@ size_t MoqtControlParser::ProcessRequestsBlocked(quic::QuicDataReader& reader) { return reader.PreviouslyReadPayload().length(); } +size_t MoqtControlParser::ProcessPublish(quic::QuicDataReader& reader) { + MoqtPublish publish; + uint8_t group_order, content_exists; + QUICHE_DCHECK(reader.PreviouslyReadPayload().empty()); + if (!reader.ReadVarInt62(&publish.request_id) || + !ReadFullTrackName(reader, publish.full_track_name) || + !reader.ReadVarInt62(&publish.track_alias) || + !reader.ReadUInt8(&group_order) || !reader.ReadUInt8(&content_exists)) { + return 0; + } + publish.group_order = static_cast(group_order); + if (group_order != 0x01 && group_order != 0x02) { + ParseError("Invalid group order value in PUBLISH"); + return 0; + } + if (content_exists > 1) { + ParseError("PUBLISH ContentExists has invalid value"); + return 0; + } + if (content_exists == 1) { + uint64_t group, object; + if (!reader.ReadVarInt62(&group) || !reader.ReadVarInt62(&object)) { + return 0; + } + publish.largest_location = Location(group, object); + } + uint8_t forward; + if (!reader.ReadUInt8(&forward)) { + return 0; + } + if (forward > 0x01) { + ParseError("Invalid forward value in PUBLISH"); + return 0; + } + publish.forward = forward == 1; + KeyValuePairList parameters; + if (!ParseKeyValuePairList(reader, parameters)) { + return 0; + } + if (!ValidateVersionSpecificParameters(parameters, + MoqtMessageType::kPublish)) { + ParseError("PUBLISH message contains invalid parameters"); + return 0; + } + if (!KeyValuePairListToVersionSpecificParameters( + parameters, /*out=*/publish.parameters)) { + return 0; + }; + visitor_.OnPublishMessage(publish); + return reader.PreviouslyReadPayload().length(); +} + +size_t MoqtControlParser::ProcessPublishOk(quic::QuicDataReader& reader) { + MoqtPublishOk publish_ok; + uint8_t forward, group_order; + uint64_t filter_type; + KeyValuePairList parameters; + if (!reader.ReadVarInt62(&publish_ok.request_id) || + !reader.ReadUInt8(&forward) || + !reader.ReadUInt8(&publish_ok.subscriber_priority) || + !reader.ReadUInt8(&group_order) || !reader.ReadVarInt62(&filter_type)) { + return 0; + } + if (forward > 0x01) { + ParseError("Invalid forward value in PUBLISH_OK"); + return 0; + } + publish_ok.forward = forward == 1; + if (group_order != 0x01 && group_order != 0x02) { + ParseError("Invalid group order value in PUBLISH_OK"); + return 0; + } + publish_ok.group_order = static_cast(group_order); + publish_ok.filter_type = static_cast(filter_type); + uint64_t group, object, end_group; + switch (publish_ok.filter_type) { + case MoqtFilterType::kNextGroupStart: + case MoqtFilterType::kLatestObject: + break; + case MoqtFilterType::kAbsoluteStart: + case MoqtFilterType::kAbsoluteRange: + if (!reader.ReadVarInt62(&group) || !reader.ReadVarInt62(&object)) { + return 0; + } + publish_ok.start = Location(group, object); + if (publish_ok.filter_type == MoqtFilterType::kAbsoluteStart) { + break; + } + if (!reader.ReadVarInt62(&end_group)) { + return 0; + } + publish_ok.end_group = end_group; + if (*publish_ok.end_group < publish_ok.start->group) { + ParseError("End group is less than start group"); + return 0; + } + break; + default: + ParseError("Invalid filter type"); + return 0; + } + if (!ParseKeyValuePairList(reader, parameters)) { + return 0; + } + if (!ValidateVersionSpecificParameters(parameters, + MoqtMessageType::kPublishOk)) { + ParseError("PUBLISH_OK message contains invalid parameters"); + return 0; + } + if (!KeyValuePairListToVersionSpecificParameters(parameters, + publish_ok.parameters)) { + return 0; + }; + visitor_.OnPublishOkMessage(publish_ok); + return reader.PreviouslyReadPayload().length(); +} + +size_t MoqtControlParser::ProcessPublishError(quic::QuicDataReader& reader) { + MoqtPublishError publish_error; + uint64_t error_code; + if (!reader.ReadVarInt62(&publish_error.request_id) || + !reader.ReadVarInt62(&error_code) || + !reader.ReadStringVarInt62(publish_error.error_reason)) { + return 0; + } + publish_error.error_code = static_cast(error_code); + visitor_.OnPublishErrorMessage(publish_error); + return reader.PreviouslyReadPayload().length(); +} + size_t MoqtControlParser::ProcessObjectAck(quic::QuicDataReader& reader) { MoqtObjectAck object_ack; uint64_t raw_delta; @@ -984,6 +1106,44 @@ bool MoqtControlParser::ReadFullTrackName(quic::QuicDataReader& reader, return true; } +bool MoqtControlParser::KeyValuePairListToMoqtSessionParameters( + const KeyValuePairList& parameters, MoqtSessionParameters& out) { + return parameters.ForEach( + [&](uint64_t key, uint64_t value) { + SetupParameter parameter = static_cast(key); + switch (parameter) { + case SetupParameter::kMaxRequestId: + out.max_request_id = value; + break; + case SetupParameter::kMaxAuthTokenCacheSize: + out.max_auth_token_cache_size = value; + break; + case SetupParameter::kSupportObjectAcks: + out.support_object_acks = (value == 1); + break; + default: + break; + } + return true; + }, + [&](uint64_t key, absl::string_view value) { + SetupParameter parameter = static_cast(key); + switch (parameter) { + case SetupParameter::kPath: + out.path = value; + break; + case SetupParameter::kAuthorizationToken: + if (!ParseAuthTokenParameter(value, out.authorization_token)) { + return false; + } + break; + default: + break; + } + return true; + }); +} + // Returns false if there is a protocol violation. bool MoqtControlParser::KeyValuePairListToVersionSpecificParameters( const KeyValuePairList& parameters, VersionSpecificParameters& out) { @@ -1012,7 +1172,7 @@ bool MoqtControlParser::KeyValuePairListToVersionSpecificParameters( static_cast(key); switch (parameter) { case VersionSpecificParameter::kAuthorizationToken: - if (!ParseAuthTokenParameter(value, out)) { + if (!ParseAuthTokenParameter(value, out.authorization_token)) { return false; } break; @@ -1023,8 +1183,8 @@ bool MoqtControlParser::KeyValuePairListToVersionSpecificParameters( }); } -bool MoqtControlParser::ParseAuthTokenParameter( - absl::string_view field, VersionSpecificParameters& out) { +bool MoqtControlParser::ParseAuthTokenParameter(absl::string_view field, + std::vector& out) { quic::QuicDataReader reader(field); AuthTokenType token_type; absl::string_view token; @@ -1073,6 +1233,14 @@ bool MoqtControlParser::ParseAuthTokenParameter( } token_type = static_cast(value); token = reader.PeekRemainingPayload(); + if (message_type_.has_value() && + *message_type_ == + static_cast(MoqtMessageType::kClientSetup)) { + // Do not check the max cache size. Since the max size isn't sent until + // SERVER_SETUP, it's not yet known. Since draft-12, this is not an + // error and tokens in excess of the cache limit are simply ignored. + break; + } if (auth_token_cache_size_ + sizeof(uint64_t) + token.length() > max_auth_token_cache_size_) { ParseError(MoqtError::kAuthTokenCacheOverflow, @@ -1096,7 +1264,7 @@ bool MoqtControlParser::ParseAuthTokenParameter( return false; } // Validate cache operations. - out.authorization_token.push_back(AuthToken(token_type, token)); + out.push_back(AuthToken(token_type, token)); return true; } @@ -1115,17 +1283,31 @@ std::optional ParseDatagram(absl::string_view data, uint64_t type_raw, object_status_raw; absl::string_view extensions; quic::QuicDataReader reader(data); + object_metadata = MoqtObject(); if (!reader.ReadVarInt62(&type_raw) || !reader.ReadVarInt62(&object_metadata.track_alias) || !reader.ReadVarInt62(&object_metadata.group_id) || !reader.ReadVarInt62(&object_metadata.object_id) || - !reader.ReadUInt8(&object_metadata.publisher_priority) || - !reader.ReadStringPieceVarInt62(&extensions)) { + !reader.ReadUInt8(&object_metadata.publisher_priority)) { return std::nullopt; } - object_metadata.extension_headers = std::string(extensions); - if (static_cast(type_raw) == - MoqtDatagramType::kObjectStatus) { + object_metadata.subgroup_id = object_metadata.object_id; + std::optional datagram_type = + MoqtDatagramType::FromValue(type_raw); + if (!datagram_type.has_value()) { + return std::nullopt; + } + if (datagram_type->has_extension()) { + if (!reader.ReadStringPieceVarInt62(&extensions)) { + return std::nullopt; + } + if (extensions.empty()) { + // This is a session error. + return std::nullopt; + } + object_metadata.extension_headers = std::string(extensions); + } + if (datagram_type->has_status()) { object_metadata.payload_length = 0; if (!reader.ReadVarInt62(&object_status_raw)) { return std::nullopt; @@ -1133,11 +1315,7 @@ std::optional ParseDatagram(absl::string_view data, object_metadata.object_status = IntegerToObjectStatus(object_status_raw); return ""; } - - absl::string_view payload; - if (!reader.ReadStringPieceVarInt62(&payload)) { - return std::nullopt; - } + absl::string_view payload = reader.ReadRemainingPayload(); object_metadata.object_status = MoqtObjectStatus::kNormal; object_metadata.payload_length = payload.length(); return payload; @@ -1165,8 +1343,8 @@ void MoqtDataParser::ReadDataUntil(StopCondition stop_condition) { std::optional MoqtDataParser::ReadVarInt62NoFin() { bool fin_read = false; std::optional result = ReadVarInt62FromStream(stream_, fin_read); - if (fin_read) { - ParseError("Unexpected FIN received in the middle of a header"); + if (fin_read) { // FIN received before a complete varint. + ParseError("FIN after incomplete message"); return std::nullopt; } return result; @@ -1176,10 +1354,6 @@ std::optional MoqtDataParser::ReadUint8NoFin() { char buffer[1]; quiche::ReadStream::ReadResult read_result = stream_.Read(absl::MakeSpan(buffer)); - if (read_result.fin) { - ParseError("Unexpected FIN received in the middle of a header"); - return std::nullopt; - } if (read_result.bytes_read == 0) { return std::nullopt; } @@ -1187,9 +1361,11 @@ std::optional MoqtDataParser::ReadUint8NoFin() { } void MoqtDataParser::AdvanceParserState() { - QUICHE_DCHECK(type_ == MoqtDataStreamType::kStreamHeaderSubgroup || - type_ == MoqtDataStreamType::kStreamHeaderFetch); - const bool is_fetch = type_ == MoqtDataStreamType::kStreamHeaderFetch; + if (next_input_ != kStreamType && !type_.has_value()) { + QUICHE_BUG(quic_bug_advance_parser_state_no_type) + << "Advancing parser state without a stream type"; + return; + } switch (next_input_) { // The state table is factored into a separate function (rather than // inlined) in order to separate the order of elements from the way they are @@ -1201,25 +1377,40 @@ void MoqtDataParser::AdvanceParserState() { next_input_ = kGroupId; break; case kGroupId: - next_input_ = kSubgroupId; + if (type_->IsFetch() || type_->IsSubgroupPresent()) { + next_input_ = kSubgroupId; + break; + } + if (type_->SubgroupIsZero()) { + metadata_.subgroup_id = 0; + } + next_input_ = kPublisherPriority; break; case kSubgroupId: - next_input_ = is_fetch ? kObjectId : kPublisherPriority; + next_input_ = type_->IsFetch() ? kObjectId : kPublisherPriority; break; case kPublisherPriority: - next_input_ = is_fetch ? kExtensionSize : kObjectId; + next_input_ = type_->IsFetch() ? kExtensionSize : kObjectId; break; case kObjectId: - next_input_ = is_fetch ? kPublisherPriority : kExtensionSize; + if (num_objects_read_ == 0 && type_->SubgroupIsFirstObjectId()) { + metadata_.subgroup_id = metadata_.object_id; + } + if (type_->IsFetch()) { + next_input_ = kPublisherPriority; + } else if (type_->AreExtensionHeadersPresent()) { + next_input_ = kExtensionSize; + } else { + next_input_ = kObjectPayloadLength; + } break; case kExtensionBody: next_input_ = kObjectPayloadLength; break; case kStatus: case kData: - next_input_ = is_fetch ? kGroupId : kObjectId; + next_input_ = type_->IsFetch() ? kGroupId : kObjectId; break; - case kExtensionSize: // Either kExtensionBody or // kObjectPayloadLength. case kObjectPayloadLength: // Either kStatus or kData depending on length. @@ -1237,22 +1428,21 @@ void MoqtDataParser::ParseNextItemFromStream() { switch (next_input_) { case kStreamType: { std::optional value_read = ReadVarInt62NoFin(); - if (value_read.has_value()) { - if (!IsAllowedStreamType(*value_read)) { - ParseError("Invalid stream type supplied"); - return; - } - type_ = static_cast(*value_read); - switch (*type_) { - case MoqtDataStreamType::kStreamHeaderSubgroup: - case MoqtDataStreamType::kStreamHeaderFetch: - AdvanceParserState(); - break; - case MoqtDataStreamType::kPadding: - next_input_ = kPadding; - break; - } + if (!value_read.has_value()) { + return; } + std::optional type = + MoqtDataStreamType::FromValue(*value_read); + if (!type.has_value()) { + ParseError("Invalid stream type supplied"); + return; + } + type_.emplace(std::move(*type)); + if (type_->IsPadding()) { + next_input_ = kPadding; + return; + } + AdvanceParserState(); return; } @@ -1356,11 +1546,6 @@ void MoqtDataParser::ParseNextItemFromStream() { if (!peek_result.has_data()) { return; } - if (peek_result.fin_next && payload_length_remaining_ > 0) { - ParseError("FIN received at an unexpected point in the stream"); - return; - } - size_t chunk_size = std::min(payload_length_remaining_, peek_result.peeked_data.size()); payload_length_remaining_ -= chunk_size; @@ -1368,17 +1553,20 @@ void MoqtDataParser::ParseNextItemFromStream() { if (next_input_ == kData) { visitor_.OnObjectMessage( metadata_, peek_result.peeked_data.substr(0, chunk_size), done); - const bool fin = stream_.SkipBytes(chunk_size); + no_more_data_ = stream_.SkipBytes(chunk_size); if (done) { ++num_objects_read_; - no_more_data_ |= fin; AdvanceParserState(); + } else if (no_more_data_) { + ParseError("FIN received at an unexpected point in the stream"); + return; } } else { absl::StrAppend(&metadata_.extension_headers, peek_result.peeked_data.substr(0, chunk_size)); if (stream_.SkipBytes(chunk_size)) { ParseError("FIN received at an unexpected point in the stream"); + no_more_data_ = true; return; } if (done) { @@ -1421,11 +1609,11 @@ bool MoqtDataParser::CheckForFinWithoutData() { if (!stream_.PeekNextReadableRegion().fin_next) { return false; } - const bool valid_state = - (type_ == MoqtDataStreamType::kStreamHeaderSubgroup && - next_input_ == kObjectId) || - (type_ == MoqtDataStreamType::kStreamHeaderFetch && - next_input_ == kGroupId); + no_more_data_ = true; + const bool valid_state = type_.has_value() && + payload_length_remaining_ == 0 && + ((type_->IsSubgroup() && next_input_ == kObjectId) || + (type_->IsFetch() && next_input_ == kGroupId)); if (!valid_state || num_objects_read_ == 0) { ParseError("FIN received at an unexpected point in the stream"); return true; 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 030861d2b6..2df5cdf3b2 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 @@ -11,6 +11,7 @@ #include #include #include +#include #include "absl/strings/string_view.h" #include "quiche/quic/core/quic_data_reader.h" @@ -62,6 +63,9 @@ class QUICHE_EXPORT MoqtControlParserVisitor { virtual void OnFetchOkMessage(const MoqtFetchOk& message) = 0; virtual void OnFetchErrorMessage(const MoqtFetchError& message) = 0; virtual void OnRequestsBlockedMessage(const MoqtRequestsBlocked& message) = 0; + virtual void OnPublishMessage(const MoqtPublish& message) = 0; + virtual void OnPublishOkMessage(const MoqtPublishOk& message) = 0; + virtual void OnPublishErrorMessage(const MoqtPublishError& message) = 0; virtual void OnObjectAckMessage(const MoqtObjectAck& message) = 0; virtual void OnParsingError(MoqtError code, absl::string_view reason) = 0; @@ -130,6 +134,9 @@ class QUICHE_EXPORT MoqtControlParser { size_t ProcessFetchOk(quic::QuicDataReader& reader); size_t ProcessFetchError(quic::QuicDataReader& reader); size_t ProcessRequestsBlocked(quic::QuicDataReader& reader); + size_t ProcessPublish(quic::QuicDataReader& reader); + size_t ProcessPublishOk(quic::QuicDataReader& reader); + size_t ProcessPublishError(quic::QuicDataReader& reader); size_t ProcessObjectAck(quic::QuicDataReader& reader); // If |error| is not provided, assumes kProtocolViolation. @@ -145,15 +152,13 @@ class QUICHE_EXPORT MoqtControlParser { bool ReadFullTrackName(quic::QuicDataReader& reader, FullTrackName& full_track_name); // Translates raw key/value pairs into semantically meaningful formats. - // The spec defines many encoding errors in AUTHORIZATION TOKEN as - // request level. This treats them as session-level, unless they are a result - // of expiration, incorrect internal structure, or anything else not defined - // in the MoQT spec. It is allowed to promote request errors to session errors - // in MoQT. See also https://github.com/moq-wg/moq-transport/issues/964. + // Returns false if the parameters contain a protocol violation. + bool KeyValuePairListToMoqtSessionParameters( + const KeyValuePairList& parameters, MoqtSessionParameters& out); bool KeyValuePairListToVersionSpecificParameters( const KeyValuePairList& parameters, VersionSpecificParameters& out); bool ParseAuthTokenParameter(absl::string_view field, - VersionSpecificParameters& out); + std::vector& out); MoqtControlParserVisitor& visitor_; quiche::ReadStream& stream_; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_probe_manager.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_probe_manager.cc index c3745b38c3..2ad86dfebb 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_probe_manager.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_probe_manager.cc @@ -18,6 +18,7 @@ #include "quiche/quic/moqt/moqt_priority.h" #include "quiche/common/platform/api/quiche_bug_tracker.h" #include "quiche/common/platform/api/quiche_logging.h" +#include "quiche/common/quiche_mem_slice.h" #include "quiche/common/quiche_stream.h" #include "quiche/common/wire_serialization.h" #include "quiche/web_transport/web_transport.h" @@ -72,15 +73,16 @@ void MoqtProbeManager::ProbeStreamVisitor::OnCanWrite() { if (!header_sent_) { absl::Status status = quiche::WriteIntoStream( - *stream_, *quiche::SerializeIntoString( - quiche::WireVarInt62(MoqtDataStreamType::kPadding))); + *stream_, *quiche::SerializeIntoString(quiche::WireVarInt62( + MoqtDataStreamType::Padding().value()))); QUICHE_DCHECK(status.ok()) << status; // Should succeed if CanWrite(). header_sent_ = true; } while (stream_->CanWrite() && data_remaining_ > 0) { quic::QuicByteCount chunk_size = std::min(kWriteChunkSize, data_remaining_); - absl::string_view chunk(kZeroes, chunk_size); + quiche::QuicheMemSlice chunk( + kZeroes, chunk_size, +[](absl::string_view) {}); quiche::StreamWriteOptions options; options.set_send_fin(chunk_size == data_remaining_); absl::Status status = stream_->Writev(absl::MakeSpan(&chunk, 1), options); 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 index 9d8950c406..ec7c121e3e 100644 --- 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 @@ -9,7 +9,6 @@ #include #include #include -#include #include "absl/status/status.h" #include "absl/status/statusor.h" @@ -22,14 +21,19 @@ namespace moqt { +struct PublishedObjectMetadata { + Location location; + uint64_t subgroup; // Equal to object_id for datagrams. + MoqtObjectStatus status; + MoqtPriority publisher_priority; + quic::QuicTime arrival_time = quic::QuicTime::Zero(); +}; + // PublishedObject is a description of an object that is sufficient to publish // it on a given track. struct PublishedObject { - Location sequence; - MoqtObjectStatus status; - MoqtPriority publisher_priority; + PublishedObjectMetadata metadata; quiche::QuicheMemSlice payload; - quic::QuicTime arrival_time = quic::QuicTime::Zero(); bool fin_after_this = false; }; @@ -49,18 +53,20 @@ class MoqtObjectListener { MoqtSubscribeErrorReason reason, std::optional track_alias = std::nullopt) = 0; - // 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(Location sequence) = 0; + // Notifies that a new object is available on the track. The object payload + // itself may be retrieved via GetCachedObject method of the associated track + // publisher. + virtual void OnNewObjectAvailable(Location sequence, uint64_t subgroup) = 0; // Notifies that a pure FIN has arrived following |sequence|. Should not be // called unless all objects have already been delivered. If not delivered, // instead set the fin_after_this flag in the PublishedObject. - virtual void OnNewFinAvailable(Location sequence) = 0; + virtual void OnNewFinAvailable(Location final_object_in_subgroup, + uint64_t subgroup_id) = 0; // Notifies that the a stream is being abandoned (via RESET_STREAM) before // all objects are delivered. virtual void OnSubgroupAbandoned( - Location sequence, webtransport::StreamErrorCode error_code) = 0; + uint64_t group, uint64_t subgroup, + webtransport::StreamErrorCode error_code) = 0; // No further object will be published for the given group, usually due to a // timeout. The owner of the Listener may want to reset the relevant streams. @@ -130,7 +136,7 @@ class MoqtTrackPublisher { // GetCachedObject lets the MoQT stack access the objects that are available // in the track's built-in local cache. Retrieves the first object ID >= - // sequence.object that matches (sequence.group, sequence.subgroup). + // min_object that matches (sequence.group, sequence.subgroup). // // 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 @@ -141,22 +147,11 @@ class MoqtTrackPublisher { // // 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; + // kEndOfGroup/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( - Location sequence) const = 0; - - // Returns a full list of objects available in the cache, to be used for - // SUBSCRIBEs with a backfill. Returned in order of worsening priority. - virtual std::vector GetCachedObjectsInRange(Location start, - Location 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. + uint64_t group, uint64_t subgroup, uint64_t min_object) const = 0; // 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 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 8ad711cbb7..5128ed3c0a 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 @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -206,7 +207,7 @@ void MoqtSession::OnDatagramReceived(absl::string_view datagram) { return; } QUICHE_DLOG(INFO) << ENDPOINT - << "Received OBJECT message in datagram for subscribe_id " + << "Received OBJECT message in datagram for request_id " << " for track alias " << message.track_alias << " with sequence " << message.group_id << ":" << message.object_id << " priority " @@ -217,8 +218,7 @@ void MoqtSession::OnDatagramReceived(absl::string_view datagram) { return; } if (!track->OnObject(/*is_datagram=*/true)) { - Error(MoqtError::kProtocolViolation, - "Received DATAGRAM for non-datagram track"); + OnMalformedTrack(track); return; } if (!track->InWindow(Location(message.group_id, message.object_id))) { @@ -230,10 +230,14 @@ void MoqtSession::OnDatagramReceived(absl::string_view datagram) { SubscribeRemoteTrack::Visitor* visitor = track->visitor(); if (visitor != nullptr) { // TODO(martinduke): Handle extension headers. - visitor->OnObjectFragment(track->full_track_name(), - Location{message.group_id, 0, message.object_id}, - message.publisher_priority, message.object_status, - *payload, true); + PublishedObjectMetadata metadata; + metadata.location = Location(message.group_id, message.object_id); + metadata.subgroup = message.object_id; + metadata.status = message.object_status; + metadata.publisher_priority = message.publisher_priority; + metadata.arrival_time = callbacks_.clock->Now(); + visitor->OnObjectFragment(track->full_track_name(), metadata, *payload, + true); } } @@ -259,13 +263,37 @@ bool MoqtSession::SubscribeAnnounces( << "Tried to send SUBSCRIBE_ANNOUNCES after GOAWAY"; return false; } + if (next_request_id_ >= peer_max_request_id_) { + if (!last_requests_blocked_sent_.has_value() || + peer_max_request_id_ > *last_requests_blocked_sent_) { + MoqtRequestsBlocked requests_blocked; + requests_blocked.max_request_id = peer_max_request_id_; + SendControlMessage(framer_.SerializeRequestsBlocked(requests_blocked)); + last_requests_blocked_sent_ = peer_max_request_id_; + } + QUIC_DLOG(INFO) << ENDPOINT << "Tried to send SUBSCRIBE_ANNOUNCES with ID " + << next_request_id_ + << " which is greater than the maximum ID " + << peer_max_request_id_; + return false; + } + if (outgoing_subscribe_announces_.contains(track_namespace)) { + std::move(callback)( + track_namespace, RequestErrorCode::kInternalError, + "SUBSCRIBE_ANNOUNCES already outstanding for namespace"); + return false; + } MoqtSubscribeAnnounces message; + message.request_id = next_request_id_; + next_request_id_ += 2; message.track_namespace = track_namespace; message.parameters = parameters; SendControlMessage(framer_.SerializeSubscribeAnnounces(message)); QUIC_DLOG(INFO) << ENDPOINT << "Sent SUBSCRIBE_ANNOUNCES message for " << message.track_namespace; - outgoing_subscribe_announces_[track_namespace] = std::move(callback); + pending_outgoing_subscribe_announces_[message.request_id] = + PendingSubscribeAnnouncesData{track_namespace, std::move(callback)}; + outgoing_subscribe_announces_.emplace(track_namespace); return true; } @@ -290,9 +318,22 @@ void MoqtSession::Announce(TrackNamespace track_namespace, if (outgoing_announces_.contains(track_namespace)) { std::move(announce_callback)( track_namespace, - MoqtAnnounceErrorReason{ - RequestErrorCode::kInternalError, - "ANNOUNCE message already outstanding for namespace"}); + MoqtAnnounceErrorReason{RequestErrorCode::kInternalError, + "ANNOUNCE already outstanding for namespace"}); + return; + } + if (next_request_id_ >= peer_max_request_id_) { + if (!last_requests_blocked_sent_.has_value() || + peer_max_request_id_ > *last_requests_blocked_sent_) { + MoqtRequestsBlocked requests_blocked; + requests_blocked.max_request_id = peer_max_request_id_; + SendControlMessage(framer_.SerializeRequestsBlocked(requests_blocked)); + last_requests_blocked_sent_ = peer_max_request_id_; + } + QUIC_DLOG(INFO) << ENDPOINT << "Tried to send ANNOUNCE with ID " + << next_request_id_ + << " which is greater than the maximum ID " + << peer_max_request_id_; return; } if (received_goaway_ || sent_goaway_) { @@ -300,11 +341,14 @@ void MoqtSession::Announce(TrackNamespace track_namespace, return; } MoqtAnnounce message; + message.request_id = next_request_id_; + next_request_id_ += 2; message.track_namespace = track_namespace; message.parameters = parameters; SendControlMessage(framer_.SerializeAnnounce(message)); QUIC_DLOG(INFO) << ENDPOINT << "Sent ANNOUNCE message for " << message.track_namespace; + pending_outgoing_announces_[message.request_id] = track_namespace; outgoing_announces_[track_namespace] = std::move(announce_callback); } @@ -455,7 +499,7 @@ void MoqtSession::Unsubscribe(const FullTrackName& name) { QUICHE_DCHECK(name.IsValid()); QUIC_DLOG(INFO) << ENDPOINT << "Sent UNSUBSCRIBE message for " << name; MoqtUnsubscribe message; - message.subscribe_id = track->request_id(); + message.request_id = track->request_id(); SendControlMessage(framer_.SerializeUnsubscribe(message)); DestroySubscription(track); } @@ -479,29 +523,26 @@ bool MoqtSession::Fetch(const FullTrackName& name, return false; } MoqtFetch message; - message.full_track_name = name; - message.fetch_id = next_request_id_; + message.fetch = StandaloneFetch(name, start, end_group, end_object); + message.request_id = next_request_id_; next_request_id_ += 2; - message.start_object = start; - message.end_group = end_group; - message.end_object = end_object; message.subscriber_priority = priority; message.group_order = delivery_order; message.parameters = parameters; SendControlMessage(framer_.SerializeFetch(message)); - QUIC_DLOG(INFO) << ENDPOINT << "Sent FETCH message for " - << message.full_track_name; - auto fetch = std::make_unique(message, std::move(callback)); - upstream_by_id_.emplace(message.fetch_id, std::move(fetch)); + QUIC_DLOG(INFO) << ENDPOINT << "Sent FETCH message for " << name; + auto fetch = std::make_unique( + message, std::get(message.fetch), std::move(callback)); + upstream_by_id_.emplace(message.request_id, std::move(fetch)); return true; } -bool MoqtSession::JoiningFetch(const FullTrackName& name, - SubscribeRemoteTrack::Visitor* visitor, - uint64_t num_previous_groups, - VersionSpecificParameters parameters) { +bool MoqtSession::RelativeJoiningFetch(const FullTrackName& name, + SubscribeRemoteTrack::Visitor* visitor, + uint64_t num_previous_groups, + VersionSpecificParameters parameters) { QUICHE_DCHECK(name.IsValid()); - return JoiningFetch( + return RelativeJoiningFetch( name, visitor, [this, id = next_request_id_](std::unique_ptr fetch_task) { // Move the fetch_task to the subscribe to plumb into its visitor. @@ -518,13 +559,11 @@ bool MoqtSession::JoiningFetch(const FullTrackName& name, parameters); } -bool MoqtSession::JoiningFetch(const FullTrackName& name, - SubscribeRemoteTrack::Visitor* visitor, - FetchResponseCallback callback, - uint64_t num_previous_groups, - MoqtPriority priority, - std::optional delivery_order, - VersionSpecificParameters parameters) { +bool MoqtSession::RelativeJoiningFetch( + const FullTrackName& name, SubscribeRemoteTrack::Visitor* visitor, + FetchResponseCallback callback, uint64_t num_previous_groups, + MoqtPriority priority, std::optional delivery_order, + VersionSpecificParameters parameters) { QUICHE_DCHECK(name.IsValid()); if ((next_request_id_ + 2) >= peer_max_request_id_) { QUIC_DLOG(INFO) << ENDPOINT << "Tried to send JOINING_FETCH with ID " @@ -542,21 +581,21 @@ bool MoqtSession::JoiningFetch(const FullTrackName& name, subscribe.start = std::nullopt; subscribe.end_group = std::nullopt; subscribe.parameters = parameters; - if (!Subscribe(subscribe, visitor, std::nullopt)) { + if (!Subscribe(subscribe, visitor)) { return false; } MoqtFetch fetch; - fetch.fetch_id = next_request_id_; + fetch.request_id = next_request_id_; next_request_id_ += 2; fetch.subscriber_priority = priority; fetch.group_order = delivery_order; - fetch.joining_fetch = {subscribe.request_id, num_previous_groups}; + fetch.fetch = JoiningFetchRelative{subscribe.request_id, num_previous_groups}; fetch.parameters = parameters; SendControlMessage(framer_.SerializeFetch(fetch)); QUIC_DLOG(INFO) << ENDPOINT << "Sent Joining FETCH message for " << name; auto upstream_fetch = - std::make_unique(fetch, std::move(callback)); - upstream_by_id_.emplace(fetch.fetch_id, std::move(upstream_fetch)); + std::make_unique(fetch, name, std::move(callback)); + upstream_by_id_.emplace(fetch.request_id, std::move(upstream_fetch)); return true; } @@ -592,14 +631,15 @@ void MoqtSession::PublishedFetch::FetchStreamVisitor::OnCanWrite() { switch (result) { case MoqtFetchTask::GetNextObjectResult::kSuccess: // Skip ObjectDoesNotExist in FETCH. - if (object.status == MoqtObjectStatus::kObjectDoesNotExist) { + if (object.metadata.status == MoqtObjectStatus::kObjectDoesNotExist) { QUIC_BUG(quic_bug_got_doesnotexist_in_fetch) << "Got ObjectDoesNotExist in FETCH"; continue; } if (fetch->session_->WriteObjectToStream( - stream_, fetch->fetch_id_, object, - MoqtDataStreamType::kStreamHeaderFetch, !stream_header_written_, + stream_, fetch->request_id(), object.metadata, + std::move(object.payload), MoqtDataStreamType::Fetch(), + !stream_header_written_, /*fin=*/false)) { stream_header_written_ = true; } @@ -627,9 +667,9 @@ void MoqtSession::GoAwayTimeoutDelegate::OnAlarm() { "Peer did not close session after GOAWAY"); } -bool MoqtSession::SubscribeIsDone(uint64_t subscribe_id, SubscribeDoneCode code, - absl::string_view reason_phrase) { - auto it = published_subscriptions_.find(subscribe_id); +bool MoqtSession::SubscribeIsDone(uint64_t request_id, SubscribeDoneCode code, + absl::string_view error_reason) { + auto it = published_subscriptions_.find(request_id); if (it == published_subscriptions_.end()) { return false; } @@ -639,10 +679,10 @@ bool MoqtSession::SubscribeIsDone(uint64_t subscribe_id, SubscribeDoneCode code, subscription.GetAllStreams(); MoqtSubscribeDone subscribe_done; - subscribe_done.subscribe_id = subscribe_id; + subscribe_done.request_id = request_id; subscribe_done.status_code = code; subscribe_done.stream_count = subscription.streams_opened(); - subscribe_done.reason_phrase = reason_phrase; + subscribe_done.error_reason = error_reason; SendControlMessage(framer_.SerializeSubscribeDone(subscribe_done)); QUIC_DLOG(INFO) << ENDPOINT << "Sent SUBSCRIBE_DONE message for " << subscription.publisher().GetTrackName(); @@ -653,7 +693,7 @@ bool MoqtSession::SubscribeIsDone(uint64_t subscribe_id, SubscribeDoneCode code, if (stream == nullptr) { continue; } - stream->ResetWithUserCode(kResetCodeSubscriptionGone); + stream->ResetWithUserCode(kResetCodeCanceled); } return true; } @@ -667,12 +707,13 @@ void MoqtSession::MaybeDestroySubscription(SubscribeRemoteTrack* subscribe) { void MoqtSession::DestroySubscription(SubscribeRemoteTrack* subscribe) { subscribe->visitor()->OnSubscribeDone(subscribe->full_track_name()); subscribe_by_name_.erase(subscribe->full_track_name()); - subscribe_by_alias_.erase(subscribe->track_alias()); + if (subscribe->track_alias().has_value()) { + subscribe_by_alias_.erase(*subscribe->track_alias()); + } } bool MoqtSession::Subscribe(MoqtSubscribe& message, - SubscribeRemoteTrack::Visitor* visitor, - std::optional provided_track_alias) { + SubscribeRemoteTrack::Visitor* visitor) { // TODO(martinduke): support authorization info if (next_request_id_ >= peer_max_request_id_) { if (!last_requests_blocked_sent_.has_value() || @@ -694,24 +735,12 @@ bool MoqtSession::Subscribe(MoqtSubscribe& message, << " which is already subscribed"; return false; } - if (provided_track_alias.has_value() && - subscribe_by_alias_.contains(*provided_track_alias)) { - Error(MoqtError::kProtocolViolation, "Provided track alias already in use"); - return false; - } if (received_goaway_ || sent_goaway_) { QUIC_DLOG(INFO) << ENDPOINT << "Tried to send SUBSCRIBE after GOAWAY"; return false; } message.request_id = next_request_id_; next_request_id_ += 2; - if (provided_track_alias.has_value()) { - message.track_alias = *provided_track_alias; - next_remote_track_alias_ = - std::max(next_remote_track_alias_, *provided_track_alias) + 1; - } else { - message.track_alias = next_remote_track_alias_++; - } if (SupportsObjectAck() && visitor != nullptr) { // Since we do not expose subscribe IDs directly in the API, instead wrap // the session and subscribe ID in a callback. @@ -728,13 +757,12 @@ bool MoqtSession::Subscribe(MoqtSubscribe& message, << message.full_track_name; auto track = std::make_unique(message, visitor); subscribe_by_name_.emplace(message.full_track_name, track.get()); - subscribe_by_alias_.emplace(message.track_alias, track.get()); upstream_by_id_.emplace(message.request_id, std::move(track)); return true; } webtransport::Stream* MoqtSession::OpenOrQueueDataStream( - uint64_t subscription_id, Location first_object) { + uint64_t subscription_id, const NewStreamParameters& parameters) { auto it = published_subscriptions_.find(subscription_id); if (it == published_subscriptions_.end()) { // It is possible that the subscription has been discarded while the stream @@ -743,17 +771,18 @@ webtransport::Stream* MoqtSession::OpenOrQueueDataStream( } PublishedSubscription& subscription = *it->second; if (!session_->CanOpenNextOutgoingUnidirectionalStream()) { - subscription.AddQueuedOutgoingDataStream(first_object); + subscription.AddQueuedOutgoingDataStream(parameters); // The subscription will notify the session about how to update the // session's queue. // TODO: limit the number of streams in the queue. return nullptr; } - return OpenDataStream(subscription, first_object); + return OpenDataStream(subscription, parameters); } webtransport::Stream* MoqtSession::OpenDataStream( - PublishedSubscription& subscription, Location first_object) { + PublishedSubscription& subscription, + const NewStreamParameters& parameters) { webtransport::Stream* new_stream = session_->OpenOutgoingUnidirectionalStream(); if (new_stream == nullptr) { @@ -762,8 +791,8 @@ webtransport::Stream* MoqtSession::OpenDataStream( return nullptr; } new_stream->SetVisitor(std::make_unique( - this, new_stream, subscription, first_object)); - subscription.OnDataStreamCreated(new_stream->GetStreamId(), first_object); + this, new_stream, subscription, parameters)); + subscription.OnDataStreamCreated(new_stream->GetStreamId(), parameters.index); return new_stream; } @@ -796,8 +825,8 @@ SubscribeRemoteTrack* MoqtSession::RemoteTrackByAlias(uint64_t track_alias) { return it->second; } -RemoteTrack* MoqtSession::RemoteTrackById(uint64_t subscribe_id) { - auto it = upstream_by_id_.find(subscribe_id); +RemoteTrack* MoqtSession::RemoteTrackById(uint64_t request_id) { + auto it = upstream_by_id_.find(request_id); if (it == upstream_by_id_.end()) { return nullptr; } @@ -833,10 +862,11 @@ void MoqtSession::OnCanCreateNewOutgoingUnidirectionalStream() { } // Pop the item from the subscription's queue, which might update // subscribes_with_queued_outgoing_data_streams_. - Location next_queued_stream = + NewStreamParameters next_queued_stream = subscription->second->NextQueuedOutgoingDataStream(); // Check if Group is too old. - if (next_queued_stream.group < subscription->second->first_active_group()) { + if (next_queued_stream.index.group < + subscription->second->first_active_group()) { // The stream is too old to be sent. continue; } @@ -850,19 +880,18 @@ void MoqtSession::OnCanCreateNewOutgoingUnidirectionalStream() { } void MoqtSession::UpdateQueuedSendOrder( - uint64_t subscribe_id, - std::optional old_send_order, + uint64_t request_id, std::optional old_send_order, std::optional new_send_order) { if (old_send_order == new_send_order) { return; } if (old_send_order.has_value()) { subscribes_with_queued_outgoing_data_streams_.erase( - SubscriptionWithQueuedStream{*old_send_order, subscribe_id}); + SubscriptionWithQueuedStream{*old_send_order, request_id}); } if (new_send_order.has_value()) { subscribes_with_queued_outgoing_data_streams_.emplace(*new_send_order, - subscribe_id); + request_id); } } @@ -971,23 +1000,22 @@ void MoqtSession::ControlStream::OnServerSetupMessage( void MoqtSession::ControlStream::SendSubscribeError( uint64_t request_id, RequestErrorCode error_code, - absl::string_view reason_phrase, uint64_t track_alias) { + absl::string_view reason_phrase) { MoqtSubscribeError subscribe_error; subscribe_error.request_id = request_id; subscribe_error.error_code = error_code; subscribe_error.reason_phrase = reason_phrase; - subscribe_error.track_alias = track_alias; SendOrBufferMessage( session_->framer_.SerializeSubscribeError(subscribe_error)); } void MoqtSession::ControlStream::SendFetchError( - uint64_t subscribe_id, RequestErrorCode error_code, - absl::string_view reason_phrase) { + uint64_t request_id, RequestErrorCode error_code, + absl::string_view error_reason) { MoqtFetchError fetch_error; - fetch_error.subscribe_id = subscribe_id; + fetch_error.request_id = request_id; fetch_error.error_code = error_code; - fetch_error.reason_phrase = reason_phrase; + fetch_error.error_reason = error_reason; SendOrBufferMessage(session_->framer_.SerializeFetchError(fetch_error)); } @@ -1001,7 +1029,7 @@ void MoqtSession::ControlStream::OnSubscribeMessage( if (session_->sent_goaway_) { QUIC_DLOG(INFO) << ENDPOINT << "Received a SUBSCRIBE after GOAWAY"; SendSubscribeError(message.request_id, RequestErrorCode::kUnauthorized, - "SUBSCRIBE after GOAWAY", message.track_alias); + "SUBSCRIBE after GOAWAY"); return; } if (session_->subscribed_track_names_.contains(message.full_track_name)) { @@ -1017,7 +1045,7 @@ void MoqtSession::ControlStream::OnSubscribeMessage( << " rejected by the application: " << track_publisher.status(); SendSubscribeError(message.request_id, RequestErrorCode::kTrackDoesNotExist, - track_publisher.status().message(), message.track_alias); + track_publisher.status().message()); return; } @@ -1048,7 +1076,7 @@ void MoqtSession::ControlStream::OnSubscribeOkMessage( RemoteTrack* track = session_->RemoteTrackById(message.request_id); if (track == nullptr) { QUIC_DLOG(INFO) << ENDPOINT << "Received the SUBSCRIBE_OK for " - << "subscribe_id = " << message.request_id + << "request_id = " << message.request_id << " but no track exists"; // Subscription state might have been destroyed for internal reasons. return; @@ -1060,16 +1088,23 @@ void MoqtSession::ControlStream::OnSubscribeOkMessage( } if (message.largest_location.has_value()) { QUIC_DLOG(INFO) << ENDPOINT << "Received the SUBSCRIBE_OK for " - << "subscribe_id = " << message.request_id << " " + << "request_id = " << message.request_id << " " << track->full_track_name() << " largest_id = " << *message.largest_location; } else { QUIC_DLOG(INFO) << ENDPOINT << "Received the SUBSCRIBE_OK for " - << "subscribe_id = " << message.request_id << " " + << "request_id = " << message.request_id << " " << track->full_track_name(); } SubscribeRemoteTrack* subscribe = static_cast(track); subscribe->OnObjectOrOk(); + auto [it, success] = + session_->subscribe_by_alias_.try_emplace(message.track_alias, subscribe); + if (!success) { + session_->Error(MoqtError::kDuplicateTrackAlias, ""); + return; + } + subscribe->set_track_alias(message.track_alias); // TODO(martinduke): Handle expires field. if (message.largest_location.has_value()) { subscribe->TruncateStart(message.largest_location->next()); @@ -1085,7 +1120,7 @@ void MoqtSession::ControlStream::OnSubscribeErrorMessage( RemoteTrack* track = session_->RemoteTrackById(message.request_id); if (track == nullptr) { QUIC_DLOG(INFO) << ENDPOINT << "Received the SUBSCRIBE_ERROR for " - << "subscribe_id = " << message.request_id + << "request_id = " << message.request_id << " but no track exists"; // Subscription state might have been destroyed for internal reasons. return; @@ -1101,7 +1136,7 @@ void MoqtSession::ControlStream::OnSubscribeErrorMessage( return; } QUIC_DLOG(INFO) << ENDPOINT << "Received the SUBSCRIBE_ERROR for " - << "subscribe_id = " << message.request_id << " (" + << "request_id = " << message.request_id << " (" << track->full_track_name() << ")" << ", error = " << static_cast(message.error_code) << " (" << message.reason_phrase << ")"; @@ -1110,22 +1145,16 @@ void MoqtSession::ControlStream::OnSubscribeErrorMessage( // an error due to a duplicate track name. The other entries for this // subscribe will be deleted after calling Subscribe(). session_->subscribe_by_name_.erase(subscribe->full_track_name()); - if (message.error_code == RequestErrorCode::kRetryTrackAlias) { - // Automatically resubscribe with new alias. - MoqtSubscribe& subscribe_message = subscribe->GetSubscribe(); - session_->Subscribe(subscribe_message, subscribe->visitor(), - message.track_alias); - } else if (subscribe->visitor() != nullptr) { + if (subscribe->visitor() != nullptr) { subscribe->visitor()->OnReply(subscribe->full_track_name(), std::nullopt, message.reason_phrase); } - session_->subscribe_by_alias_.erase(subscribe->track_alias()); session_->upstream_by_id_.erase(subscribe->request_id()); } void MoqtSession::ControlStream::OnUnsubscribeMessage( const MoqtUnsubscribe& message) { - auto it = session_->published_subscriptions_.find(message.subscribe_id); + auto it = session_->published_subscriptions_.find(message.request_id); if (it == session_->published_subscriptions_.end()) { return; } @@ -1136,7 +1165,7 @@ void MoqtSession::ControlStream::OnUnsubscribeMessage( void MoqtSession::ControlStream::OnSubscribeDoneMessage( const MoqtSubscribeDone& message) { - auto it = session_->upstream_by_id_.find(message.subscribe_id); + auto it = session_->upstream_by_id_.find(message.request_id); if (it == session_->upstream_by_id_.end()) { return; } @@ -1163,12 +1192,15 @@ void MoqtSession::ControlStream::OnSubscribeUpdateMessage( void MoqtSession::ControlStream::OnAnnounceMessage( const MoqtAnnounce& message) { + if (!session_->ValidateRequestId(message.request_id)) { + return; + } if (session_->sent_goaway_) { QUIC_DLOG(INFO) << ENDPOINT << "Received an ANNOUNCE after GOAWAY"; MoqtAnnounceError error; - error.track_namespace = message.track_namespace; + error.request_id = message.request_id; error.error_code = RequestErrorCode::kUnauthorized; - error.reason_phrase = "ANNOUNCE after GOAWAY"; + error.error_reason = "ANNOUNCE after GOAWAY"; SendOrBufferMessage(session_->framer_.SerializeAnnounceError(error)); return; } @@ -1177,14 +1209,14 @@ void MoqtSession::ControlStream::OnAnnounceMessage( message.parameters); if (error.has_value()) { MoqtAnnounceError reply; - reply.track_namespace = message.track_namespace; + reply.request_id = message.request_id; reply.error_code = error->error_code; - reply.reason_phrase = error->reason_phrase; + reply.error_reason = error->reason_phrase; SendOrBufferMessage(session_->framer_.SerializeAnnounceError(reply)); return; } MoqtAnnounceOk ok; - ok.track_namespace = message.track_namespace; + ok.request_id = message.request_id; SendOrBufferMessage(session_->framer_.SerializeAnnounceOk(ok)); } @@ -1192,24 +1224,41 @@ void MoqtSession::ControlStream::OnAnnounceMessage( // ERROR, we immediately destroy the state. void MoqtSession::ControlStream::OnAnnounceOkMessage( const MoqtAnnounceOk& message) { - auto it = session_->outgoing_announces_.find(message.track_namespace); - if (it == session_->outgoing_announces_.end()) { - return; // State might have been destroyed due to UNANNOUNCE. + auto it = session_->pending_outgoing_announces_.find(message.request_id); + if (it == session_->pending_outgoing_announces_.end()) { + session_->Error(MoqtError::kProtocolViolation, + "Received ANNOUNCE_OK for unknown request_id"); + return; } - std::move(it->second)(message.track_namespace, std::nullopt); + TrackNamespace track_namespace = it->second; + session_->pending_outgoing_announces_.erase(it); + auto callback_it = session_->outgoing_announces_.find(track_namespace); + if (callback_it == session_->outgoing_announces_.end()) { + // It might have already been destroyed due to UNANNOUNCE. + return; + } + std::move(callback_it->second)(track_namespace, std::nullopt); } void MoqtSession::ControlStream::OnAnnounceErrorMessage( const MoqtAnnounceError& message) { - auto it = session_->outgoing_announces_.find(message.track_namespace); - if (it == session_->outgoing_announces_.end()) { + auto it = session_->pending_outgoing_announces_.find(message.request_id); + if (it == session_->pending_outgoing_announces_.end()) { + session_->Error(MoqtError::kProtocolViolation, + "Received ANNOUNCE_ERROR for unknown request_id"); + return; + } + TrackNamespace track_namespace = it->second; + session_->pending_outgoing_announces_.erase(it); + auto it2 = session_->outgoing_announces_.find(track_namespace); + if (it2 == session_->outgoing_announces_.end()) { return; // State might have been destroyed due to UNANNOUNCE. } - std::move(it->second)( - message.track_namespace, + std::move(it2->second)( + track_namespace, MoqtAnnounceErrorReason{message.error_code, - std::string(message.reason_phrase)}); - session_->outgoing_announces_.erase(it); + std::string(message.error_reason)}); + session_->outgoing_announces_.erase(it2); } void MoqtSession::ControlStream::OnAnnounceCancelMessage( @@ -1225,10 +1274,38 @@ void MoqtSession::ControlStream::OnAnnounceCancelMessage( std::move(it->second)( message.track_namespace, MoqtAnnounceErrorReason{message.error_code, - std::string(message.reason_phrase)}); + std::string(message.error_reason)}); session_->outgoing_announces_.erase(it); } +void MoqtSession::ControlStream::OnTrackStatusRequestMessage( + const MoqtTrackStatusRequest& message) { + if (!session_->ValidateRequestId(message.request_id)) { + return; + } + if (session_->sent_goaway_) { + QUIC_DLOG(INFO) << ENDPOINT + << "Received a TRACK_STATUS_REQUEST after GOAWAY"; + SendOrBufferMessage(session_->framer_.SerializeTrackStatus( + MoqtTrackStatus(message.request_id, MoqtTrackStatusCode::kDoesNotExist, + Location(0, 0)))); + return; + } + // TODO(martinduke): Handle authentication. + absl::StatusOr> track = + session_->publisher_->GetTrack(message.full_track_name); + if (!track.ok()) { + SendOrBufferMessage(session_->framer_.SerializeTrackStatus( + MoqtTrackStatus(message.request_id, MoqtTrackStatusCode::kDoesNotExist, + Location(0, 0)))); + return; + } + session_->incoming_track_status_.emplace( + std::pair( + message.request_id, + DownstreamTrackStatus(message.request_id, session_, track->get()))); +} + void MoqtSession::ControlStream::OnUnannounceMessage( const MoqtUnannounce& message) { session_->callbacks_.incoming_announce_callback(message.track_namespace, @@ -1256,14 +1333,17 @@ void MoqtSession::ControlStream::OnGoAwayMessage(const MoqtGoAway& message) { void MoqtSession::ControlStream::OnSubscribeAnnouncesMessage( const MoqtSubscribeAnnounces& message) { + if (!session_->ValidateRequestId(message.request_id)) { + return; + } // TODO(martinduke): Handle authentication. if (session_->sent_goaway_) { QUIC_DLOG(INFO) << ENDPOINT << "Received a SUBSCRIBE_ANNOUNCES after GOAWAY"; MoqtSubscribeAnnouncesError error; - error.track_namespace = message.track_namespace; + error.request_id = message.request_id; error.error_code = RequestErrorCode::kUnauthorized; - error.reason_phrase = "SUBSCRIBE_ANNOUNCES after GOAWAY"; + error.error_reason = "SUBSCRIBE_ANNOUNCES after GOAWAY"; SendOrBufferMessage( session_->framer_.SerializeSubscribeAnnouncesError(error)); return; @@ -1273,49 +1353,45 @@ void MoqtSession::ControlStream::OnSubscribeAnnouncesMessage( message.track_namespace, message.parameters); if (result.has_value()) { MoqtSubscribeAnnouncesError error; - error.track_namespace = message.track_namespace; + error.request_id = message.request_id; error.error_code = result->error_code; - error.reason_phrase = result->reason_phrase; + error.error_reason = result->reason_phrase; SendOrBufferMessage( session_->framer_.SerializeSubscribeAnnouncesError(error)); return; } MoqtSubscribeAnnouncesOk ok; - ok.track_namespace = message.track_namespace; + ok.request_id = message.request_id; SendOrBufferMessage(session_->framer_.SerializeSubscribeAnnouncesOk(ok)); } void MoqtSession::ControlStream::OnSubscribeAnnouncesOkMessage( const MoqtSubscribeAnnouncesOk& message) { auto it = - session_->outgoing_subscribe_announces_.find(message.track_namespace); - if (it == session_->outgoing_subscribe_announces_.end()) { + session_->pending_outgoing_subscribe_announces_.find(message.request_id); + if (it == session_->pending_outgoing_subscribe_announces_.end()) { + session_->Error(MoqtError::kProtocolViolation, + "Received SUBSCRIBE_ANNOUNCES_OK for unknown request_id"); return; // UNSUBSCRIBE_ANNOUNCES may already have deleted the entry. } - if (it->second == nullptr) { - session_->Error(MoqtError::kProtocolViolation, - "Two responses to SUBSCRIBE_ANNOUNCES"); - return; - } - std::move(it->second)(message.track_namespace, std::nullopt, ""); - it->second = nullptr; + std::move(it->second.callback)(it->second.track_namespace, std::nullopt, ""); + session_->pending_outgoing_subscribe_announces_.erase(it); } void MoqtSession::ControlStream::OnSubscribeAnnouncesErrorMessage( const MoqtSubscribeAnnouncesError& message) { auto it = - session_->outgoing_subscribe_announces_.find(message.track_namespace); - if (it == session_->outgoing_subscribe_announces_.end()) { + session_->pending_outgoing_subscribe_announces_.find(message.request_id); + if (it == session_->pending_outgoing_subscribe_announces_.end()) { + session_->Error( + MoqtError::kProtocolViolation, + "Received SUBSCRIBE_ANNOUNCES_ERROR for unknown request_id"); return; // UNSUBSCRIBE_ANNOUNCES may already have deleted the entry. } - if (it->second == nullptr) { - session_->Error(MoqtError::kProtocolViolation, - "Two responses to SUBSCRIBE_ANNOUNCES"); - return; - } - std::move(it->second)(message.track_namespace, message.error_code, - absl::string_view(message.reason_phrase)); - session_->outgoing_subscribe_announces_.erase(it); + std::move(it->second.callback)(it->second.track_namespace, message.error_code, + absl::string_view(message.error_reason)); + session_->outgoing_subscribe_announces_.erase(it->second.track_namespace); + session_->pending_outgoing_subscribe_announces_.erase(it); } void MoqtSession::ControlStream::OnUnsubscribeAnnouncesMessage( @@ -1340,12 +1416,12 @@ void MoqtSession::ControlStream::OnMaxRequestIdMessage( } void MoqtSession::ControlStream::OnFetchMessage(const MoqtFetch& message) { - if (!session_->ValidateRequestId(message.fetch_id)) { + if (!session_->ValidateRequestId(message.request_id)) { return; } if (session_->sent_goaway_) { QUIC_DLOG(INFO) << ENDPOINT << "Received a FETCH after GOAWAY"; - SendFetchError(message.fetch_id, RequestErrorCode::kUnauthorized, + SendFetchError(message.request_id, RequestErrorCode::kUnauthorized, "FETCH after GOAWAY"); return; } @@ -1353,14 +1429,26 @@ void MoqtSession::ControlStream::OnFetchMessage(const MoqtFetch& message) { Location start_object; uint64_t end_group; std::optional end_object; - if (message.joining_fetch.has_value()) { - uint64_t joining_subscribe_id = message.joining_fetch->joining_subscribe_id; + if (std::holds_alternative(message.fetch)) { + const StandaloneFetch& standalone_fetch = + std::get(message.fetch); + track_name = standalone_fetch.full_track_name; + start_object = standalone_fetch.start_object; + end_group = standalone_fetch.end_group; + end_object = standalone_fetch.end_object; + } else { + uint64_t joining_subscribe_id = + std::holds_alternative(message.fetch) + ? std::get(message.fetch) + .joining_subscribe_id + : std::get(message.fetch) + .joining_subscribe_id; auto it = session_->published_subscriptions_.find(joining_subscribe_id); if (it == session_->published_subscriptions_.end()) { QUIC_DLOG(INFO) << ENDPOINT << "Received a JOINING_FETCH for " << "subscribe_id " << joining_subscribe_id << " that does not exist"; - SendFetchError(message.fetch_id, RequestErrorCode::kTrackDoesNotExist, + SendFetchError(message.request_id, RequestErrorCode::kTrackDoesNotExist, "Joining Fetch for non-existent subscribe"); return; } @@ -1377,21 +1465,26 @@ void MoqtSession::ControlStream::OnFetchMessage(const MoqtFetch& message) { } track_name = it->second->publisher().GetTrackName(); Location fetch_end = it->second->GetWindowStart(); - if (message.joining_fetch->preceding_group_offset > fetch_end.group) { - start_object = Location(0, 0); + if (std::holds_alternative(message.fetch)) { + const JoiningFetchRelative& relative_fetch = + std::get(message.fetch); + if (relative_fetch.joining_start > fetch_end.group) { + start_object = Location(0, 0); + } else { + start_object = + Location(fetch_end.group - relative_fetch.joining_start, 0); + } } else { - start_object = Location( - fetch_end.group - message.joining_fetch->preceding_group_offset, 0, - 0); + const JoiningFetchAbsolute& absolute_fetch = + std::get(message.fetch); + start_object = + Location(fetch_end.group - absolute_fetch.joining_start, 0); } end_group = fetch_end.group; end_object = fetch_end.object - 1; - } else { - track_name = message.full_track_name; - start_object = message.start_object; - end_group = message.end_group; - end_object = message.end_object; } + // The check for end_object < start_object is done in + // MoqtTrackPublisher::Fetch(). QUIC_DLOG(INFO) << ENDPOINT << "Received a FETCH for " << track_name; absl::StatusOr> track_publisher = session_->publisher_->GetTrack(track_name); @@ -1399,7 +1492,7 @@ void MoqtSession::ControlStream::OnFetchMessage(const MoqtFetch& message) { QUIC_DLOG(INFO) << ENDPOINT << "FETCH for " << track_name << " rejected by the application: " << track_publisher.status(); - SendFetchError(message.fetch_id, RequestErrorCode::kTrackDoesNotExist, + SendFetchError(message.request_id, RequestErrorCode::kTrackDoesNotExist, track_publisher.status().message()); return; } @@ -1411,23 +1504,23 @@ void MoqtSession::ControlStream::OnFetchMessage(const MoqtFetch& message) { if (!fetch->GetStatus().ok()) { QUIC_DLOG(INFO) << ENDPOINT << "FETCH for " << track_name << " could not initialize the task"; - SendFetchError(message.fetch_id, RequestErrorCode::kInvalidRange, + SendFetchError(message.request_id, RequestErrorCode::kInvalidRange, fetch->GetStatus().message()); return; } auto published_fetch = std::make_unique( - message.fetch_id, session_, std::move(fetch)); - auto result = session_->incoming_fetches_.emplace(message.fetch_id, + message.request_id, session_, std::move(fetch)); + auto result = session_->incoming_fetches_.emplace(message.request_id, std::move(published_fetch)); if (!result.second) { // Emplace failed. QUIC_DLOG(INFO) << ENDPOINT << "FETCH for " << track_name << " could not be added to the session"; - SendFetchError(message.fetch_id, RequestErrorCode::kInternalError, + SendFetchError(message.request_id, RequestErrorCode::kInternalError, "Could not initialize FETCH state"); } MoqtFetchTask* fetch_task = result.first->second->fetch_task(); fetch_task->SetFetchResponseCallback( - [this, request_id = message.fetch_id, fetch_start = start_object, + [this, request_id = message.request_id, fetch_start = start_object, fetch_end = Location(end_group, end_object.value_or(UINT64_MAX))]( std::variant message) { if (!session_->incoming_fetches_.contains(request_id)) { @@ -1435,11 +1528,11 @@ void MoqtSession::ControlStream::OnFetchMessage(const MoqtFetch& message) { } if (std::holds_alternative(message)) { MoqtFetchOk& fetch_ok = std::get(message); - fetch_ok.subscribe_id = request_id; - if (fetch_ok.largest_id < fetch_start || - fetch_ok.largest_id > fetch_end) { + fetch_ok.request_id = request_id; + if (fetch_ok.end_location < fetch_start || + fetch_ok.end_location > fetch_end) { // TODO(martinduke): Add end_of_track to fetch_ok and check it's - // larger than largest_id. + // larger than end_location. QUIC_BUG(quic_bug_fetch_ok_status_error) << "FETCH_OK end or end_of_track is invalid"; session_->Error(MoqtError::kInternalError, "FETCH_OK status error"); @@ -1449,14 +1542,14 @@ void MoqtSession::ControlStream::OnFetchMessage(const MoqtFetch& message) { return; } MoqtFetchError& fetch_error = std::get(message); - fetch_error.subscribe_id = request_id; + fetch_error.request_id = request_id; SendOrBufferMessage(session_->framer_.SerializeFetchError(fetch_error)); }); // Set a temporary new-object callback that creates a data stream. When // created, the stream visitor will replace this callback. fetch_task->SetObjectAvailableCallback( [this, send_order = SendOrderForFetch(message.subscriber_priority), - request_id = message.fetch_id]() { + request_id = message.request_id]() { auto it = session_->incoming_fetches_.find(request_id); if (it == session_->incoming_fetches_.end()) { return; @@ -1475,10 +1568,10 @@ void MoqtSession::ControlStream::OnFetchMessage(const MoqtFetch& message) { } void MoqtSession::ControlStream::OnFetchOkMessage(const MoqtFetchOk& message) { - RemoteTrack* track = session_->RemoteTrackById(message.subscribe_id); + RemoteTrack* track = session_->RemoteTrackById(message.request_id); if (track == nullptr) { QUIC_DLOG(INFO) << ENDPOINT << "Received the FETCH_OK for " - << "subscribe_id = " << message.subscribe_id + << "request_id = " << message.request_id << " but no track exists"; // Subscription state might have been destroyed for internal reasons. return; @@ -1488,21 +1581,20 @@ void MoqtSession::ControlStream::OnFetchOkMessage(const MoqtFetchOk& message) { "Received FETCH_OK for a SUBSCRIBE"); return; } - QUIC_DLOG(INFO) << ENDPOINT << "Received the FETCH_OK for subscribe_id = " - << message.subscribe_id << " " << track->full_track_name(); + QUIC_DLOG(INFO) << ENDPOINT << "Received the FETCH_OK for request_id = " + << message.request_id << " " << track->full_track_name(); UpstreamFetch* fetch = static_cast(track); - fetch->OnFetchResult(message.largest_id, absl::OkStatus(), - [=, session = session_]() { - session->CancelFetch(message.subscribe_id); - }); + fetch->OnFetchResult( + message.end_location, message.group_order, absl::OkStatus(), + [=, session = session_]() { session->CancelFetch(message.request_id); }); } void MoqtSession::ControlStream::OnFetchErrorMessage( const MoqtFetchError& message) { - RemoteTrack* track = session_->RemoteTrackById(message.subscribe_id); + RemoteTrack* track = session_->RemoteTrackById(message.request_id); if (track == nullptr) { QUIC_DLOG(INFO) << ENDPOINT << "Received the FETCH_ERROR for " - << "subscribe_id = " << message.subscribe_id + << "request_id = " << message.request_id << " but no track exists"; // Subscription state might have been destroyed for internal reasons. return; @@ -1518,15 +1610,16 @@ void MoqtSession::ControlStream::OnFetchErrorMessage( return; } QUIC_DLOG(INFO) << ENDPOINT << "Received the FETCH_ERROR for " - << "subscribe_id = " << message.subscribe_id << " (" + << "request_id = " << message.request_id << " (" << track->full_track_name() << ")" << ", error = " << static_cast(message.error_code) - << " (" << message.reason_phrase << ")"; + << " (" << message.error_reason << ")"; UpstreamFetch* fetch = static_cast(track); absl::Status status = - RequestErrorCodeToStatus(message.error_code, message.reason_phrase); - fetch->OnFetchResult(Location(0, 0), status, nullptr); - session_->upstream_by_id_.erase(message.subscribe_id); + RequestErrorCodeToStatus(message.error_code, message.error_reason); + fetch->OnFetchResult(Location(0, 0), MoqtDeliveryOrder::kAscending, status, + nullptr); + session_->upstream_by_id_.erase(message.request_id); } void MoqtSession::ControlStream::OnRequestsBlockedMessage( @@ -1534,6 +1627,24 @@ void MoqtSession::ControlStream::OnRequestsBlockedMessage( // TODO(martinduke): Derive logic for granting more subscribes. } +void MoqtSession::ControlStream::OnPublishMessage(const MoqtPublish& message) { + if (!session_->ValidateRequestId(message.request_id)) { + return; + } + MoqtPublishError publish_error = { + .request_id = message.request_id, + .error_code = RequestErrorCode::kNotSupported, + .error_reason = "PUBLISH is not supported", + }; + if (session_->sent_goaway_) { + QUIC_DLOG(INFO) << ENDPOINT << "Received a PUBLISH after GOAWAY"; + publish_error.error_code = RequestErrorCode::kUnauthorized; + publish_error.error_reason = "Received a PUBLISH after GOAWAY"; + } + // TODO(martinduke): Process these messages. + SendOrBufferMessage(session_->framer_.SerializePublishError(publish_error)); +} + void MoqtSession::ControlStream::OnParsingError(MoqtError error_code, absl::string_view reason) { session_->Error(error_code, absl::StrCat("Parse error: ", reason)); @@ -1547,7 +1658,7 @@ void MoqtSession::ControlStream::SendOrBufferMessage( // 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()}; + std::array write_vector = {quiche::QuicheMemSlice(std::move(message))}; absl::Status success = stream_->Writev(absl::MakeSpan(write_vector), options); if (!success.ok()) { session_->Error(MoqtError::kInternalError, @@ -1580,18 +1691,20 @@ void MoqtSession::IncomingDataStream::OnObjectMessage(const MoqtObject& message, payload = absl::string_view(partial_object_); } } - QUICHE_BUG_IF(quic_bug_object_with_no_stream_type, - !parser_.stream_type().has_value()) - << "Object delivered without a stream type"; + if (!parser_.stream_type().has_value()) { + QUICHE_BUG(quic_bug_object_with_no_stream_type) + << "Object delivered without a stream type"; + return; + } // Get a pointer to the upstream state. RemoteTrack* track = track_.GetIfAvailable(); if (track == nullptr) { - track = (*parser_.stream_type() == MoqtDataStreamType::kStreamHeaderFetch) + track = (parser_.stream_type()->IsFetch()) // message.track_alias is actually a fetch ID for fetches. ? session_->RemoteTrackById(message.track_alias) : session_->RemoteTrackByAlias(message.track_alias); if (track == nullptr) { - stream_->SendStopSending(kResetCodeSubscriptionGone); + stream_->SendStopSending(kResetCodeCanceled); // Received object for nonexistent track. return; } @@ -1607,24 +1720,50 @@ void MoqtSession::IncomingDataStream::OnObjectMessage(const MoqtObject& message, return; } if (!track->is_fetch()) { + if (no_more_objects_) { + // Already got a stream-ending object. + session_->OnMalformedTrack(track); + return; + } + if (message.object_id < next_object_id_) { + session_->OnMalformedTrack(track); + return; + } + if (end_of_message) { + next_object_id_ = message.object_id + 1; + if (message.object_status == MoqtObjectStatus::kEndOfTrack || + message.object_status == MoqtObjectStatus::kEndOfGroup) { + no_more_objects_ = true; + } + } SubscribeRemoteTrack* subscribe = static_cast(track); - subscribe->OnObject(/*is_datagram=*/false); + if (!subscribe->OnObject(/*is_datagram=*/false)) { + session_->OnMalformedTrack(track); + return; + } if (subscribe->visitor() != nullptr) { // TODO(martinduke): Send extension headers. - subscribe->visitor()->OnObjectFragment( - track->full_track_name(), - Location{message.group_id, message.subgroup_id.value_or(0), - message.object_id}, - message.publisher_priority, message.object_status, payload, - end_of_message); + PublishedObjectMetadata metadata; + metadata.location = Location(message.group_id, message.object_id); + metadata.subgroup = message.subgroup_id; + metadata.status = message.object_status; + metadata.publisher_priority = message.publisher_priority; + metadata.arrival_time = session_->callbacks_.clock->Now(); + subscribe->visitor()->OnObjectFragment(track->full_track_name(), metadata, + payload, end_of_message); } } else { // FETCH track->OnObjectOrOk(); UpstreamFetch* fetch = static_cast(track); + if (!fetch->LocationIsValid(Location(message.group_id, message.object_id), + message.object_status, end_of_message)) { + session_->OnMalformedTrack(track); + return; + } UpstreamFetch::UpstreamFetchTask* task = fetch->task(); if (task == nullptr) { // The application killed the FETCH. - stream_->SendStopSending(kResetCodeSubscriptionGone); + stream_->SendStopSending(kResetCodeCanceled); return; } if (!task->HasObject()) { @@ -1649,8 +1788,9 @@ MoqtSession::IncomingDataStream::~IncomingDataStream() { if (!track_.IsValid()) { return; } - if (parser_.stream_type() == MoqtDataStreamType::kStreamHeaderFetch) { + if (parser_.stream_type().has_value() && parser_.stream_type()->IsFetch()) { session_->upstream_by_id_.erase(*parser_.track_alias()); + return; } // It's a subscribe. SubscribeRemoteTrack* subscribe = @@ -1664,7 +1804,7 @@ MoqtSession::IncomingDataStream::~IncomingDataStream() { void MoqtSession::IncomingDataStream::MaybeReadOneObject() { if (!parser_.track_alias().has_value() || - parser_.stream_type() != MoqtDataStreamType::kStreamHeaderFetch) { + !parser_.stream_type().has_value() || !parser_.stream_type()->IsFetch()) { QUICHE_BUG(quic_bug_read_one_object_parser_unexpected_state) << "Requesting object, parser in unexpected state"; } @@ -1698,7 +1838,7 @@ void MoqtSession::IncomingDataStream::OnCanRead() { } } bool knew_track_alias = parser_.track_alias().has_value(); - if (parser_.stream_type() == MoqtDataStreamType::kStreamHeaderSubgroup) { + if (parser_.stream_type()->IsSubgroup()) { parser_.ReadAllData(); } else if (!knew_track_alias) { parser_.ReadTrackAlias(); @@ -1706,7 +1846,7 @@ void MoqtSession::IncomingDataStream::OnCanRead() { if (!parser_.track_alias().has_value()) { return; } - if (parser_.stream_type() == MoqtDataStreamType::kStreamHeaderSubgroup) { + if (parser_.stream_type()->IsSubgroup()) { if (knew_track_alias) { return; } @@ -1715,9 +1855,9 @@ void MoqtSession::IncomingDataStream::OnCanRead() { if (it == session_->subscribe_by_alias_.end()) { QUIC_DLOG(INFO) << ENDPOINT << "Received object for a track with no SUBSCRIBE"; - // This is a not a session error because there might be an UNSUBSCRIBE in - // flight. - stream_->SendStopSending(kResetCodeSubscriptionGone); + // This is a not a session error because there might be an UNSUBSCRIBE or + // SUBSCRIBE_OK (containing the track alias) in flight. + stream_->SendStopSending(kResetCodeCanceled); return; } it->second->OnStreamOpened(); @@ -1728,7 +1868,7 @@ void MoqtSession::IncomingDataStream::OnCanRead() { QUIC_DLOG(INFO) << ENDPOINT << "Received object for a track with no FETCH"; // This is a not a session error because there might be an UNSUBSCRIBE in // flight. - stream_->SendStopSending(kResetCodeSubscriptionGone); + stream_->SendStopSending(kResetCodeCanceled); return; } if (it->second == nullptr) { @@ -1764,7 +1904,6 @@ MoqtSession::PublishedSubscription::PublishedSubscription( : session_(session), track_publisher_(track_publisher), request_id_(subscribe.request_id), - track_alias_(subscribe.track_alias), filter_type_(subscribe.filter_type), forward_(subscribe.forward), window_(SubscribeMessageToWindow(subscribe)), @@ -1773,7 +1912,7 @@ MoqtSession::PublishedSubscription::PublishedSubscription( monitoring_interface_(monitoring_interface) { if (monitoring_interface_ != nullptr) { monitoring_interface_->OnObjectAckSupportKnown( - subscribe.parameters.oack_window_size.has_value()); + subscribe.parameters.oack_window_size); } QUIC_DLOG(INFO) << ENDPOINT << "Created subscription for " << subscribe.full_track_name; @@ -1792,8 +1931,7 @@ SendStreamMap& MoqtSession::PublishedSubscription::stream_map() { if (!lazily_initialized_stream_map_.has_value()) { QUICHE_DCHECK( DoesTrackStatusImplyHavingData(*track_publisher_->GetTrackStatus())); - lazily_initialized_stream_map_.emplace( - track_publisher_->GetForwardingPreference()); + lazily_initialized_stream_map_.emplace(); } return *lazily_initialized_stream_map_; } @@ -1860,30 +1998,37 @@ void MoqtSession::PublishedSubscription::OnSubscribeAccepted() { } MoqtSubscribeOk subscribe_ok; subscribe_ok.request_id = request_id_; + subscribe_ok.track_alias = session_->next_local_track_alias_++; subscribe_ok.group_order = track_publisher_->GetDeliveryOrder(); subscribe_ok.largest_location = largest_location; + track_alias_.emplace(subscribe_ok.track_alias); // TODO(martinduke): Support sending DELIVERY_TIMEOUT parameter as the // publisher. stream->SendOrBufferMessage( session_->framer_.SerializeSubscribeOk(subscribe_ok)); + if (!PublisherHasData(*track_publisher_)) { + return; + } + // TODO(martinduke): If we buffer objects that arrived previously, the arrival + // of the track alias disambiguates what subscription they belong to. Send + // them. } void MoqtSession::PublishedSubscription::OnSubscribeRejected( MoqtSubscribeErrorReason reason, std::optional track_alias) { session_->GetControlStream()->SendSubscribeError( - request_id_, reason.error_code, reason.reason_phrase, - track_alias.value_or(track_alias_)); + request_id_, reason.error_code, reason.reason_phrase); session_->published_subscriptions_.erase(request_id_); // No class access below this line! } void MoqtSession::PublishedSubscription::OnNewObjectAvailable( - Location sequence) { + Location sequence, uint64_t subgroup) { if (!InWindow(sequence)) { return; } - if (reset_subgroups_.contains( - Location{sequence.group, sequence.subgroup, 0})) { + DataStreamIndex index(sequence.group, subgroup); + if (reset_subgroups_.contains(index)) { // This subgroup has already been reset, ignore. return; } @@ -1917,12 +2062,14 @@ void MoqtSession::PublishedSubscription::OnNewObjectAvailable( } std::optional stream_id = - stream_map().GetStreamForSequence(sequence); + stream_map().GetStreamFor(index); webtransport::Stream* raw_stream = nullptr; if (stream_id.has_value()) { raw_stream = session_->session_->GetStreamById(*stream_id); } else { - raw_stream = session_->OpenOrQueueDataStream(request_id_, sequence); + raw_stream = session_->OpenOrQueueDataStream( + request_id_, + NewStreamParameters(sequence.group, subgroup, sequence.object)); } if (raw_stream == nullptr) { return; @@ -1938,18 +2085,20 @@ void MoqtSession::PublishedSubscription::OnTrackPublisherGone() { "Publisher is gone"); } -void MoqtSession::PublishedSubscription::OnNewFinAvailable(Location sequence) { - if (!InWindow(sequence)) { +// TODO(martinduke): Revise to check if the last object has been delivered. +void MoqtSession::PublishedSubscription::OnNewFinAvailable(Location location, + uint64_t subgroup) { + if (!GroupInWindow(location.group)) { return; } - if (reset_subgroups_.contains( - Location{sequence.group, sequence.subgroup, 0})) { + DataStreamIndex index(location.group, subgroup); + if (reset_subgroups_.contains(index)) { // This subgroup has already been reset, ignore. return; } - QUICHE_DCHECK_GE(sequence.group, first_active_group_); + QUICHE_DCHECK_GE(location.group, first_active_group_); std::optional stream_id = - stream_map().GetStreamForSequence(sequence); + stream_map().GetStreamFor(index); if (!stream_id.has_value()) { return; } @@ -1960,22 +2109,23 @@ void MoqtSession::PublishedSubscription::OnNewFinAvailable(Location sequence) { } OutgoingDataStream* stream = static_cast(raw_stream->visitor()); - stream->Fin(sequence); + stream->Fin(location); } void MoqtSession::PublishedSubscription::OnSubgroupAbandoned( - Location sequence, webtransport::StreamErrorCode error_code) { - if (!InWindow(sequence)) { + uint64_t group, uint64_t subgroup, + webtransport::StreamErrorCode error_code) { + if (!GroupInWindow(group)) { return; } - if (reset_subgroups_.contains( - Location{sequence.group, sequence.subgroup, 0})) { + DataStreamIndex index(group, subgroup); + if (reset_subgroups_.contains(index)) { // This subgroup has already been reset, ignore. return; } - QUICHE_DCHECK_GE(sequence.group, first_active_group_); + QUICHE_DCHECK_GE(group, first_active_group_); std::optional stream_id = - stream_map().GetStreamForSequence(sequence); + stream_map().GetStreamFor(index); if (!stream_id.has_value()) { return; } @@ -1995,17 +2145,26 @@ void MoqtSession::PublishedSubscription::OnGroupAbandoned(uint64_t group_id) { } std::vector streams = stream_map().GetStreamsForGroup(group_id); + if (delivery_timeout_.IsInfinite() && largest_sent_.has_value() && + largest_sent_->group <= group_id) { + session_->SubscribeIsDone(request_id_, SubscribeDoneCode::kTooFarBehind, + ""); + // No class access below this line! + return; + } for (webtransport::StreamId stream_id : streams) { webtransport::Stream* raw_stream = session_->session_->GetStreamById(stream_id); if (raw_stream == nullptr) { continue; } - raw_stream->ResetWithUserCode(kResetCodeTimedOut); + raw_stream->ResetWithUserCode(kResetCodeDeliveryTimeout); + // Sending the Reset will call the destructor for OutgoingDataStream, which + // will erase it from the SendStreamMap. } first_active_group_ = std::max(first_active_group_, group_id + 1); - absl::erase_if(reset_subgroups_, [&](const Location& sequence) { - return sequence.group < first_active_group_; + absl::erase_if(reset_subgroups_, [&](const DataStreamIndex& index) { + return index.group < first_active_group_; }); } @@ -2018,7 +2177,7 @@ MoqtSession::PublishedSubscription::GetAllStreams() const { } webtransport::SendOrder MoqtSession::PublishedSubscription::GetSendOrder( - Location sequence) const { + Location sequence, uint64_t subgroup) const { MoqtForwardingPreference forwarding_preference = track_publisher_->GetForwardingPreference(); @@ -2031,21 +2190,23 @@ webtransport::SendOrder MoqtSession::PublishedSubscription::GetSendOrder( delivery_order); } return SendOrderForStream(subscriber_priority_, publisher_priority, - sequence.group, sequence.subgroup, delivery_order); + sequence.group, subgroup, delivery_order); } // Returns the highest send order in the subscription. void MoqtSession::PublishedSubscription::AddQueuedOutgoingDataStream( - Location first_object) { + const NewStreamParameters& parameters) { std::optional start_send_order = queued_outgoing_data_streams_.empty() ? std::optional() : queued_outgoing_data_streams_.rbegin()->first; - webtransport::SendOrder send_order = GetSendOrder(first_object); + webtransport::SendOrder send_order = + GetSendOrder(Location(parameters.index.group, parameters.first_object), + parameters.index.subgroup); // Zero out the subscriber priority bits, since these will be added when // updating the session. queued_outgoing_data_streams_.emplace( - UpdateSendOrderForSubscriberPriority(send_order, 0), first_object); + UpdateSendOrderForSubscriberPriority(send_order, 0), parameters); if (!start_send_order.has_value()) { session_->UpdateQueuedSendOrder(request_id_, std::nullopt, send_order); } else if (*start_send_order < send_order) { @@ -2054,14 +2215,18 @@ void MoqtSession::PublishedSubscription::AddQueuedOutgoingDataStream( } } -Location MoqtSession::PublishedSubscription::NextQueuedOutgoingDataStream() { +MoqtSession::NewStreamParameters +MoqtSession::PublishedSubscription::NextQueuedOutgoingDataStream() { QUICHE_DCHECK(!queued_outgoing_data_streams_.empty()); if (queued_outgoing_data_streams_.empty()) { - return Location(); + QUICHE_BUG(NextQueuedOutgoingDataStream_no_stream) + << "NextQueuedOutgoingDataStream called when there are no streams " + "pending."; + return NewStreamParameters(0, 0, 0); } auto it = queued_outgoing_data_streams_.rbegin(); webtransport::SendOrder old_send_order = FinalizeSendOrder(it->first); - Location first_object = it->second; + NewStreamParameters first_stream = it->second; // converting a reverse iterator to an iterator involves incrementing it and // then taking base(). queued_outgoing_data_streams_.erase((++it).base()); @@ -2075,17 +2240,17 @@ Location MoqtSession::PublishedSubscription::NextQueuedOutgoingDataStream() { new_send_order); } } - return first_object; + return first_stream; } void MoqtSession::PublishedSubscription::OnDataStreamCreated( - webtransport::StreamId id, Location start_sequence) { + webtransport::StreamId id, DataStreamIndex start_sequence) { ++streams_opened_; stream_map().AddStream(start_sequence, id); } void MoqtSession::PublishedSubscription::OnDataStreamDestroyed( - webtransport::StreamId id, Location end_sequence) { - stream_map().RemoveStream(end_sequence, id); + webtransport::StreamId id, DataStreamIndex end_sequence) { + stream_map().RemoveStream(end_sequence); } void MoqtSession::PublishedSubscription::OnObjectSent(Location sequence) { @@ -2099,11 +2264,16 @@ void MoqtSession::PublishedSubscription::OnObjectSent(Location sequence) { MoqtSession::OutgoingDataStream::OutgoingDataStream( MoqtSession* session, webtransport::Stream* stream, - PublishedSubscription& subscription, Location first_object) + PublishedSubscription& subscription, const NewStreamParameters& parameters) : session_(session), stream_(stream), subscription_id_(subscription.request_id()), - next_object_(first_object), + index_(parameters.index), + // Always include extension header length, because it's difficult to know + // a priori if they're going to appear on a stream. + stream_type_(MoqtDataStreamType::Subgroup( + index_.subgroup, parameters.first_object, false)), + next_object_(parameters.first_object), session_liveness_(session->liveness_token_) { UpdateSendOrder(subscription); } @@ -2124,7 +2294,7 @@ MoqtSession::OutgoingDataStream::~OutgoingDataStream() { } auto it = session_->published_subscriptions_.find(subscription_id_); if (it != session_->published_subscriptions_.end()) { - it->second->OnDataStreamDestroyed(stream_->GetStreamId(), next_object_); + it->second->OnDataStreamDestroyed(stream_->GetStreamId(), index_); } } @@ -2140,16 +2310,16 @@ void MoqtSession::OutgoingDataStream::DeliveryTimeoutDelegate::OnAlarm() { auto it = stream_->session_->published_subscriptions_.find( stream_->subscription_id_); if (it != stream_->session_->published_subscriptions_.end()) { - it->second->OnStreamTimeout(stream_->next_object_); + it->second->OnStreamTimeout(stream_->index()); } - stream_->stream_->ResetWithUserCode(kResetCodeTimedOut); + stream_->stream_->ResetWithUserCode(kResetCodeDeliveryTimeout); } MoqtSession::PublishedSubscription* MoqtSession::OutgoingDataStream::GetSubscriptionIfValid() { auto it = session_->published_subscriptions_.find(subscription_id_); if (it == session_->published_subscriptions_.end()) { - stream_->ResetWithUserCode(kResetCodeSubscriptionGone); + stream_->ResetWithUserCode(kResetCodeCanceled); return nullptr; } @@ -2173,13 +2343,22 @@ MoqtSession::OutgoingDataStream::GetSubscriptionIfValid() { void MoqtSession::OutgoingDataStream::SendObjects( PublishedSubscription& subscription) { + if (!subscription.track_alias().has_value()) { + return; + } while (stream_->CanWrite()) { std::optional object = - subscription.publisher().GetCachedObject(next_object_); + subscription.publisher().GetCachedObject(index_.group, index_.subgroup, + next_object_); if (!object.has_value()) { break; } - if (!subscription.InWindow(next_object_)) { + + QUICHE_DCHECK_EQ(object->metadata.location.group, index_.group); + QUICHE_DCHECK(object->metadata.subgroup == index_.subgroup); + QUICHE_DCHECK(subscription.publisher().GetForwardingPreference() == + MoqtForwardingPreference::kSubgroup); + if (!subscription.InWindow(object->metadata.location)) { // It is possible that the next object became irrelevant due to a // SUBSCRIBE_UPDATE. Close the stream if so. bool success = stream_->SendFin(); @@ -2187,42 +2366,38 @@ void MoqtSession::OutgoingDataStream::SendObjects( << "Writing FIN failed despite CanWrite() being true."; return; } + quic::QuicTimeDelta delivery_timeout = subscription.delivery_timeout(); if (!session_->alternate_delivery_timeout_ && - session_->callbacks_.clock->ApproximateNow() - object->arrival_time > + session_->callbacks_.clock->ApproximateNow() - + object->metadata.arrival_time > delivery_timeout) { - subscription.OnStreamTimeout(next_object_); - stream_->ResetWithUserCode(kResetCodeTimedOut); + subscription.OnStreamTimeout(index_); + stream_->ResetWithUserCode(kResetCodeDeliveryTimeout); return; } - QUICHE_DCHECK(next_object_ <= object->sequence); - MoqtTrackPublisher& publisher = subscription.publisher(); - QUICHE_DCHECK(DoesTrackStatusImplyHavingData(*publisher.GetTrackStatus())); - MoqtForwardingPreference forwarding_preference = - publisher.GetForwardingPreference(); - UpdateSendOrder(subscription); - if (forwarding_preference == MoqtForwardingPreference::kDatagram) { - QUICHE_BUG(quic_bug_SendObjects_for_Datagram) - << "Datagram Track requesting SendObjects"; - return; - } - next_object_ = object->sequence.next(); - if (session_->WriteObjectToStream( - stream_, subscription.track_alias(), *object, - MoqtDataStreamType::kStreamHeaderSubgroup, !stream_header_written_, + if (!session_->WriteObjectToStream( + stream_, *subscription.track_alias(), object->metadata, + std::move(object->payload), stream_type_, !stream_header_written_, object->fin_after_this)) { - stream_header_written_ = true; - subscription.OnObjectSent(object->sequence); + // WriteObjectToStream() closes the connection on error, meaning that + // there is no need to process the stream any further. + return; } + ++next_object_; + stream_header_written_ = true; + subscription.OnObjectSent(object->metadata.location); + if (object->fin_after_this && !delivery_timeout.IsInfinite() && !session_->alternate_delivery_timeout_) { - CreateAndSetAlarm(object->arrival_time + delivery_timeout); + CreateAndSetAlarm(object->metadata.arrival_time + delivery_timeout); } } } void MoqtSession::OutgoingDataStream::Fin(Location last_object) { - if (next_object_ <= last_object) { + QUICHE_DCHECK_EQ(last_object.group, index_.group); + if (next_object_ <= last_object.object) { // There is still data to send, do nothing. return; } @@ -2242,28 +2417,30 @@ void MoqtSession::OutgoingDataStream::Fin(Location last_object) { } bool MoqtSession::WriteObjectToStream(webtransport::Stream* stream, uint64_t id, - const PublishedObject& object, + const PublishedObjectMetadata& metadata, + quiche::QuicheMemSlice payload, MoqtDataStreamType type, bool is_first_on_stream, bool fin) { QUICHE_DCHECK(stream->CanWrite()); MoqtObject header; header.track_alias = id; - header.group_id = object.sequence.group; - header.subgroup_id = object.sequence.subgroup; - header.object_id = object.sequence.object; - header.publisher_priority = object.publisher_priority; - header.object_status = object.status; - header.payload_length = object.payload.length(); + header.group_id = metadata.location.group; + header.subgroup_id = metadata.subgroup; + header.object_id = metadata.location.object; + header.publisher_priority = metadata.publisher_priority; + header.object_status = metadata.status; + header.payload_length = payload.length(); quiche::QuicheBuffer serialized_header = framer_.SerializeObjectHeader(header, type, is_first_on_stream); // 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()}; + std::array write_vector = { + quiche::QuicheMemSlice(std::move(serialized_header)), std::move(payload)}; quiche::StreamWriteOptions options; options.set_send_fin(fin); - absl::Status write_status = stream->Writev(write_vector, options); + absl::Status write_status = + stream->Writev(absl::MakeSpan(write_vector), options); if (!write_status.ok()) { QUICHE_BUG(MoqtSession_WriteObjectToStream_write_failed) << "Writing into MoQT stream failed despite CanWrite() being true " @@ -2274,23 +2451,39 @@ bool MoqtSession::WriteObjectToStream(webtransport::Stream* stream, uint64_t id, } QUIC_DVLOG(1) << "Stream " << stream->GetStreamId() << " successfully wrote " - << object.sequence << ", fin = " << fin; + << metadata.location << ", fin = " << fin; return true; } -void MoqtSession::CancelFetch(uint64_t subscribe_id) { +void MoqtSession::OnMalformedTrack(RemoteTrack* track) { + if (!track->is_fetch()) { + static_cast(track)->visitor()->OnMalformedTrack( + track->full_track_name()); + Unsubscribe(track->full_track_name()); + return; + } + UpstreamFetch::UpstreamFetchTask* task = + static_cast(track)->task(); + if (task != nullptr) { + task->OnStreamAndFetchClosed(kResetCodeMalformedTrack, + "Malformed track received"); + } + CancelFetch(track->request_id()); +} + +void MoqtSession::CancelFetch(uint64_t request_id) { if (is_closing_) { return; } // This is only called from the callback where UpstreamFetchTask has been // destroyed, so there is no need to notify the application. - upstream_by_id_.erase(subscribe_id); + upstream_by_id_.erase(request_id); ControlStream* stream = GetControlStream(); if (stream == nullptr) { return; } MoqtFetchCancel message; - message.subscribe_id = subscribe_id; + message.request_id = request_id; stream->SendOrBufferMessage(framer_.SerializeFetchCancel(message)); // The FETCH_CANCEL will cause a RESET_STREAM to return, which would be the // same as a STOP_SENDING. However, a FETCH_CANCEL works even if the stream @@ -2299,32 +2492,35 @@ void MoqtSession::CancelFetch(uint64_t subscribe_id) { void MoqtSession::PublishedSubscription::SendDatagram(Location sequence) { std::optional object = - track_publisher_->GetCachedObject(sequence); + track_publisher_->GetCachedObject(sequence.group, 0, sequence.object); if (!object.has_value()) { QUICHE_BUG(PublishedSubscription_SendDatagram_object_not_in_cache) << "Got notification about an object that is not in the cache"; return; } - + if (!track_alias_.has_value()) { + return; + } MoqtObject header; - header.track_alias = track_alias(); - header.group_id = object->sequence.group; - header.object_id = object->sequence.object; - header.publisher_priority = object->publisher_priority; - header.object_status = object->status; - header.subgroup_id = std::nullopt; + header.track_alias = *track_alias_; + header.group_id = object->metadata.location.group; + header.object_id = object->metadata.location.object; + header.publisher_priority = object->metadata.publisher_priority; + header.object_status = object->metadata.status; + header.subgroup_id = header.object_id; header.payload_length = object->payload.length(); quiche::QuicheBuffer datagram = session_->framer_.SerializeObjectDatagram( header, object->payload.AsStringView()); session_->session_->SendOrQueueDatagram(datagram.AsStringView()); - OnObjectSent(object->sequence); + OnObjectSent(object->metadata.location); } void MoqtSession::OutgoingDataStream::UpdateSendOrder( PublishedSubscription& subscription) { - stream_->SetPriority( - webtransport::StreamPriority{/*send_group_id=*/kMoqtSendGroupId, - subscription.GetSendOrder(next_object_)}); + stream_->SetPriority(webtransport::StreamPriority{ + /*send_group_id=*/kMoqtSendGroupId, + subscription.GetSendOrder(Location(index_.group, next_object_), + index_.subgroup)}); } void MoqtSession::OutgoingDataStream::CreateAndSetAlarm( 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 b7e5301cd5..3bb2f3d49f 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 @@ -5,6 +5,7 @@ #ifndef QUICHE_QUIC_MOQT_MOQT_SESSION_H_ #define QUICHE_QUIC_MOQT_MOQT_SESSION_H_ +#include #include #include #include @@ -12,15 +13,15 @@ #include #include +#include "absl/base/nullability.h" #include "absl/container/btree_map.h" #include "absl/container/btree_set.h" #include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" +#include "absl/status/statusor.h" #include "absl/strings/string_view.h" #include "quiche/quic/core/quic_alarm.h" #include "quiche/quic/core/quic_alarm_factory.h" -#include "quiche/quic/core/quic_clock.h" -#include "quiche/quic/core/quic_default_clock.h" #include "quiche/quic/core/quic_time.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/moqt/moqt_framer.h" @@ -34,7 +35,7 @@ #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/quiche_mem_slice.h" #include "quiche/common/quiche_weak_ptr.h" #include "quiche/web_transport/web_transport.h" @@ -61,7 +62,8 @@ class MoqtPublishingMonitorInterface { public: virtual ~MoqtPublishingMonitorInterface() = default; - virtual void OnObjectAckSupportKnown(bool supported) = 0; + virtual void OnObjectAckSupportKnown( + std::optional time_window) = 0; virtual void OnObjectAckReceived(uint64_t group_id, uint64_t object_id, quic::QuicTimeDelta delta_from_deadline) = 0; }; @@ -155,19 +157,19 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, // in the FETCH will not be filled by with ObjectDoesNotExist. If the FETCH // fails for any reason, the application will not receive a notification; it // will just appear to be missing objects. - bool JoiningFetch(const FullTrackName& name, - SubscribeRemoteTrack::Visitor* visitor, - uint64_t num_previous_groups, - VersionSpecificParameters parameters) override; + bool RelativeJoiningFetch(const FullTrackName& name, + SubscribeRemoteTrack::Visitor* visitor, + uint64_t num_previous_groups, + VersionSpecificParameters parameters) override; // Sends both a SUBSCRIBE and a joining FETCH, beginning |num_previous_groups| // groups before the current group. The application provides |callback| to // fully control acceptance of Fetched objects. - bool JoiningFetch(const FullTrackName& name, - SubscribeRemoteTrack::Visitor* visitor, - FetchResponseCallback callback, - uint64_t num_previous_groups, MoqtPriority priority, - std::optional delivery_order, - VersionSpecificParameters parameters) override; + bool RelativeJoiningFetch(const FullTrackName& name, + SubscribeRemoteTrack::Visitor* visitor, + FetchResponseCallback callback, + uint64_t num_previous_groups, MoqtPriority priority, + std::optional delivery_order, + VersionSpecificParameters parameters) override; // Send a GOAWAY message to the peer. |new_session_uri| must be empty if // called by the client. @@ -213,6 +215,15 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, struct Empty {}; + struct NewStreamParameters { + DataStreamIndex index; + uint64_t first_object; + + NewStreamParameters(uint64_t group, uint64_t subgroup, + uint64_t first_object) + : index(group, subgroup), first_object(first_object) {} + }; + class QUICHE_EXPORT ControlStream : public webtransport::StreamVisitor, public MoqtControlParserVisitor { public: @@ -240,7 +251,7 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, void OnAnnounceErrorMessage(const MoqtAnnounceError& message) override; void OnAnnounceCancelMessage(const MoqtAnnounceCancel& message) override; void OnTrackStatusRequestMessage( - const MoqtTrackStatusRequest& message) override {}; + const MoqtTrackStatusRequest& message) override; void OnUnannounceMessage(const MoqtUnannounce& /*message*/) override; void OnTrackStatusMessage(const MoqtTrackStatus& message) override {} void OnGoAwayMessage(const MoqtGoAway& /*message*/) override; @@ -258,6 +269,9 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, void OnFetchOkMessage(const MoqtFetchOk& message) override; void OnFetchErrorMessage(const MoqtFetchError& message) override; void OnRequestsBlockedMessage(const MoqtRequestsBlocked& message) override; + void OnPublishMessage(const MoqtPublish& message) override; + void OnPublishOkMessage(const MoqtPublishOk& message) override {}; + void OnPublishErrorMessage(const MoqtPublishError& message) override {}; void OnObjectAckMessage(const MoqtObjectAck& message) override { auto subscription_it = session_->published_subscriptions_.find(message.subscribe_id); @@ -280,13 +294,12 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, void SendOrBufferMessage(quiche::QuicheBuffer message, bool fin = false); void SendSubscribeError(uint64_t request_id, RequestErrorCode error_code, - absl::string_view reason_phrase, - uint64_t track_alias); + absl::string_view reason_phrase); private: friend class test::MoqtSessionPeer; - void SendFetchError(uint64_t subscribe_id, RequestErrorCode error_code, - absl::string_view reason_phrase); + void SendFetchError(uint64_t request_id, RequestErrorCode error_code, + absl::string_view error_reason); MoqtSession* session_; webtransport::Stream* stream_; @@ -325,6 +338,8 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, friend class test::MoqtSessionPeer; void OnControlMessageReceived(); + uint64_t next_object_id_ = 0; + bool no_more_objects_ = false; // EndOfGroup or EndOfTrack was received. MoqtSession* session_; webtransport::Stream* stream_; // Once the subscribe ID is identified, set it here. @@ -350,7 +365,7 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, uint64_t request_id() const { return request_id_; } MoqtTrackPublisher& publisher() { return *track_publisher_; } - uint64_t track_alias() const { return track_alias_; } + std::optional track_alias() const { return track_alias_; } std::optional largest_sent() const { return largest_sent_; } MoqtPriority subscriber_priority() const { return subscriber_priority_; } std::optional subscriber_delivery_order() const { @@ -364,10 +379,10 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, MoqtSubscribeErrorReason reason, std::optional track_alias = std::nullopt) override; // This is only called for objects that have just arrived. - void OnNewObjectAvailable(Location sequence) override; + void OnNewObjectAvailable(Location location, uint64_t subgroup) override; void OnTrackPublisherGone() override; - void OnNewFinAvailable(Location sequence) override; - void OnSubgroupAbandoned(Location sequence, + void OnNewFinAvailable(Location location, uint64_t subgroup) override; + void OnSubgroupAbandoned(uint64_t group, uint64_t subgroup, webtransport::StreamErrorCode error_code) override; void OnGroupAbandoned(uint64_t group_id) override; void ProcessObjectAck(const MoqtObjectAck& message) { @@ -386,6 +401,9 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, bool InWindow(Location sequence) { return forward_ && window_.has_value() && window_->InWindow(sequence); } + bool GroupInWindow(uint64_t group) { + return forward_ && window_.has_value() && window_->GroupInWindow(group); + } Location GetWindowStart() const { QUICHE_CHECK(window_.has_value()); return window_->start(); @@ -393,44 +411,45 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, MoqtFilterType filter_type() const { return filter_type_; }; void OnDataStreamCreated(webtransport::StreamId id, - Location start_sequence); + DataStreamIndex start_sequence); void OnDataStreamDestroyed(webtransport::StreamId id, - Location end_sequence); + DataStreamIndex end_sequence); void OnObjectSent(Location sequence); std::vector GetAllStreams() const; - webtransport::SendOrder GetSendOrder(Location sequence) const; + webtransport::SendOrder GetSendOrder(Location sequence, + uint64_t subgroup) const; - void AddQueuedOutgoingDataStream(Location first_object); + void AddQueuedOutgoingDataStream(const NewStreamParameters& parameters); // Pops the pending outgoing data stream, with the highest send order. // The session keeps track of which subscribes have pending streams. This // function will trigger a QUICHE_DCHECK if called when there are no pending // streams. - Location NextQueuedOutgoingDataStream(); + NewStreamParameters NextQueuedOutgoingDataStream(); quic::QuicTimeDelta delivery_timeout() const { return delivery_timeout_; } void set_delivery_timeout(quic::QuicTimeDelta timeout) { delivery_timeout_ = timeout; } - void OnStreamTimeout(Location sequence) { - sequence.object = 0; - reset_subgroups_.insert(sequence); + void OnStreamTimeout(DataStreamIndex index) { + reset_subgroups_.insert(index); if (session_->alternate_delivery_timeout_) { - first_active_group_ = std::max(first_active_group_, sequence.group + 1); + first_active_group_ = std::max(first_active_group_, index.group + 1); } } uint64_t first_active_group() const { return first_active_group_; } - absl::flat_hash_set& reset_subgroups() { + absl::flat_hash_set& reset_subgroups() { return reset_subgroups_; } uint64_t streams_opened() const { return streams_opened_; } private: + friend class test::MoqtSessionPeer; SendStreamMap& stream_map(); quic::Perspective perspective() const { return session_->parameters_.perspective; @@ -446,7 +465,7 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, MoqtSession* session_; std::shared_ptr track_publisher_; uint64_t request_id_; - uint64_t track_alias_; + std::optional track_alias_; MoqtFilterType filter_type_; bool forward_; // If window_ is nullopt, any arriving objects are ignored. This could be @@ -461,7 +480,7 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, uint64_t first_active_group_ = 0; // If a stream has been reset due to delivery timeout, do not open a new // stream if more object arrive for it. - absl::flat_hash_set reset_subgroups_; + absl::flat_hash_set reset_subgroups_; // The min of DELIVERY_TIMEOUT from SUBSCRIBE and SUBSCRIBE_OK. quic::QuicTimeDelta delivery_timeout_ = quic::QuicTimeDelta::Infinite(); @@ -474,14 +493,14 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, // Store the send order of queued outgoing data streams. Use a // subscriber_priority_ of zero to avoid having to update it, and call // FinalizeSendOrder() whenever delivering it to the MoqtSession. - absl::btree_multimap + absl::btree_multimap queued_outgoing_data_streams_; }; class QUICHE_EXPORT OutgoingDataStream : public webtransport::StreamVisitor { public: OutgoingDataStream(MoqtSession* session, webtransport::Stream* stream, PublishedSubscription& subscription, - Location first_object); + const NewStreamParameters& parameters); ~OutgoingDataStream(); // webtransport::StreamVisitor implementation. @@ -519,6 +538,8 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, // alarm is already created. void CreateAndSetAlarm(quic::QuicTime deadline); + DataStreamIndex index() const { return index_; } + private: friend class test::MoqtSessionPeer; friend class DeliveryTimeoutDelegate; @@ -530,10 +551,12 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, MoqtSession* session_; webtransport::Stream* stream_; uint64_t subscription_id_; - // A Location with the minimum object ID that should go out next. The - // session doesn't know what the next object ID in the stream is because - // the next object could be in a different subgroup or simply be skipped. - Location next_object_; + DataStreamIndex index_; + MoqtDataStreamType stream_type_; + // Minimum object ID that should go out next. The session doesn't know the + // exact ID of the next object in the stream because the next object could + // be in a different subgroup or simply be skipped. + uint64_t next_object_; bool stream_header_written_ = false; // If this data stream is for SUBSCRIBE, reset it if an object has been // excessively delayed per Section 7.1.1.2. @@ -545,9 +568,11 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, class QUICHE_EXPORT PublishedFetch { public: - PublishedFetch(uint64_t fetch_id, MoqtSession* session, + PublishedFetch(uint64_t request_id, MoqtSession* session, std::unique_ptr fetch) - : session_(session), fetch_(std::move(fetch)), fetch_id_(fetch_id) {} + : session_(session), + fetch_(std::move(fetch)), + request_id_(request_id) {} class FetchStreamVisitor : public webtransport::StreamVisitor { public: @@ -560,7 +585,7 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, ~FetchStreamVisitor() { std::shared_ptr fetch = fetch_.lock(); if (fetch != nullptr) { - fetch->session()->incoming_fetches_.erase(fetch->fetch_id_); + fetch->session()->incoming_fetches_.erase(fetch->request_id_); } } // webtransport::StreamVisitor implementation. @@ -580,17 +605,81 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, MoqtFetchTask* fetch_task() { return fetch_.get(); } MoqtSession* session() { return session_; } - uint64_t fetch_id() const { return fetch_id_; } + uint64_t request_id() const { return request_id_; } void SetStreamId(webtransport::StreamId id) { stream_id_ = id; } private: MoqtSession* session_; std::unique_ptr fetch_; - uint64_t fetch_id_; + uint64_t request_id_; // Store the stream ID in case a FETCH_CANCEL requires a reset. std::optional stream_id_; }; + class QUICHE_EXPORT DownstreamTrackStatus : public MoqtObjectListener { + public: + DownstreamTrackStatus(uint64_t request_id, + MoqtSession* absl_nonnull session, + MoqtTrackPublisher* absl_nonnull publisher) + : request_id_(request_id), session_(session), publisher_(publisher) { + publisher_->AddObjectListener(this); + } + ~DownstreamTrackStatus() { + if (publisher_ != nullptr) { + publisher_->RemoveObjectListener(this); + } + } + + void OnSubscribeAccepted() override { + MoqtTrackStatus track_status; + track_status.request_id = request_id_; + QUICHE_CHECK(publisher_ != nullptr); + absl::StatusOr status = publisher_->GetTrackStatus(); + if (!status.ok()) { + session_->Error(MoqtError::kInternalError, + "Failed to get track status"); + return; + } + track_status.status_code = *status; + if (*status != MoqtTrackStatusCode::kDoesNotExist && + *status != MoqtTrackStatusCode::kNotYetBegun) { + track_status.largest_location = publisher_->GetLargestLocation(); + } // Else, leave it at (0,0). + session_->SendControlMessage( + session_->framer_.SerializeTrackStatus(track_status)); + session_->incoming_track_status_.erase(request_id_); + // No class access below this line! + } + + // TODO(martinduke): In draft-13, this will trigger TRACK_STATUS_ERROR. + void OnSubscribeRejected(MoqtSubscribeErrorReason /*error_code*/, + std::optional /*track_alias*/) override { + OnSubscribeAccepted(); + } + + void OnNewObjectAvailable(Location sequence, uint64_t subgroup) override {} + void OnNewFinAvailable(Location location, uint64_t subgroup) override {} + void OnSubgroupAbandoned( + uint64_t group, uint64_t subgroup, + webtransport::StreamErrorCode error_code) override {} + void OnGroupAbandoned(uint64_t group_id) override {} + void OnTrackPublisherGone() override { + publisher_ = nullptr; + MoqtTrackStatus track_status; + track_status.request_id = request_id_; + track_status.status_code = MoqtTrackStatusCode::kDoesNotExist; + track_status.largest_location = Location(0, 0); + session_->SendControlMessage( + session_->framer_.SerializeTrackStatus(track_status)); + session_->incoming_track_status_.erase(request_id_); + } + + private: + uint64_t request_id_; + MoqtSession* session_; + MoqtTrackPublisher* publisher_; + }; + class GoAwayTimeoutDelegate : public quic::QuicAlarm::DelegateWithoutContext { public: explicit GoAwayTimeoutDelegate(MoqtSession* session) : session_(session) {} @@ -614,8 +703,8 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, // Private members of MoqtSession. // Returns true if SUBSCRIBE_DONE was sent. - bool SubscribeIsDone(uint64_t subscribe_id, SubscribeDoneCode code, - absl::string_view reason_phrase); + bool SubscribeIsDone(uint64_t request_id, SubscribeDoneCode code, + absl::string_view error_reason); void MaybeDestroySubscription(SubscribeRemoteTrack* subscribe); void DestroySubscription(SubscribeRemoteTrack* subscribe); @@ -625,19 +714,18 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, // is present. void SendControlMessage(quiche::QuicheBuffer message); - // Returns false if the SUBSCRIBE isn't sent. |provided_track_alias| has a - // value only if this call is due to a SUBSCRIBE_ERROR. - bool Subscribe(MoqtSubscribe& message, SubscribeRemoteTrack::Visitor* visitor, - std::optional provided_track_alias = std::nullopt); + // Returns false if the SUBSCRIBE isn't sent. + bool Subscribe(MoqtSubscribe& message, + SubscribeRemoteTrack::Visitor* visitor); // Opens a new data stream, or queues it if the session is flow control // blocked. - webtransport::Stream* OpenOrQueueDataStream(uint64_t subscription_id, - Location first_object); + webtransport::Stream* OpenOrQueueDataStream( + uint64_t subscription_id, const NewStreamParameters& parameters); // Same as above, except the session is required to be not flow control // blocked. webtransport::Stream* OpenDataStream(PublishedSubscription& subscription, - Location first_object); + const NewStreamParameters& parameters); // Returns false if creation failed. [[nodiscard]] bool OpenDataStream(std::shared_ptr fetch, webtransport::SendOrder send_order); @@ -654,11 +742,12 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, // and metadata in |object|. Not for use with datagrams. Returns |true| if // the write was successful. bool WriteObjectToStream(webtransport::Stream* stream, uint64_t id, - const PublishedObject& object, + const PublishedObjectMetadata& metadata, + quiche::QuicheMemSlice payload, MoqtDataStreamType type, bool is_first_on_stream, bool fin); - void CancelFetch(uint64_t subscribe_id); + void CancelFetch(uint64_t request_id); // Sends an OBJECT_ACK message for a specific subscribe ID. void SendObjectAck(uint64_t subscribe_id, uint64_t group_id, @@ -679,6 +768,12 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, bool SupportsObjectAck() const { return parameters_.support_object_acks && peer_supports_object_ack_; } + + // Called when the incoming track is malformed per Section 2.5 of + // draft-ietf-moqt-moq-transport-12. Unsubscribe and notify the application so + // the error can be propagated downstream, if necessary. + void OnMalformedTrack(RemoteTrack* track); + bool is_closing_ = false; webtransport::Session* session_; @@ -700,8 +795,7 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, absl::flat_hash_map subscribe_by_alias_; // All SUBSCRIBEs, indexed by track name. absl::flat_hash_map subscribe_by_name_; - // The next track alias to guess on a SUBSCRIBE. - uint64_t next_remote_track_alias_ = 0; + // The next subscribe ID that the local endpoint can send. uint64_t next_request_id_ = 0; // The local endpoint can send subscribe IDs less than this value. @@ -730,21 +824,29 @@ class QUICHE_EXPORT MoqtSession : public MoqtSessionInterface, absl::flat_hash_map> incoming_fetches_; + absl::flat_hash_map incoming_track_status_; + // Monitoring interfaces for expected incoming subscriptions. absl::flat_hash_map monitoring_interfaces_for_published_tracks_; - // Indexed by track namespace. If the value is not nullptr, no OK or ERROR - // has been received. The entry is deleted after sending UNANNOUNCE or - // receiving ANNOUNCE_CANCEL. + // Outgoing ANNOUNCE for which no OK or ERROR has been received. + absl::flat_hash_map pending_outgoing_announces_; + // All outgoing ANNOUNCE. absl::flat_hash_map outgoing_announces_; + // The value is nullptr after OK or ERROR is received. The entry is deleted // when sending UNSUBSCRIBE_ANNOUNCES, to make sure the application doesn't // unsubscribe from something that it isn't subscribed to. ANNOUNCEs that // result from this subscription use incoming_announce_callback. - absl::flat_hash_map - outgoing_subscribe_announces_; + struct PendingSubscribeAnnouncesData { + TrackNamespace track_namespace; + MoqtOutgoingSubscribeAnnouncesCallback callback; + }; + absl::flat_hash_map + pending_outgoing_subscribe_announces_; + absl::flat_hash_set outgoing_subscribe_announces_; // The minimum request ID the peer can use that is monotonically increasing. uint64_t next_incoming_request_id_ = 0; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_session_interface.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_session_interface.h index 8e822f91de..6846c96523 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_session_interface.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_session_interface.h @@ -94,20 +94,21 @@ class MoqtSessionInterface { // in the FETCH will not be filled by with ObjectDoesNotExist. If the FETCH // fails for any reason, the application will not receive a notification; it // will just appear to be missing objects. - virtual bool JoiningFetch(const FullTrackName& name, - SubscribeRemoteTrack::Visitor* visitor, - uint64_t num_previous_groups, - VersionSpecificParameters parameters) = 0; + virtual bool RelativeJoiningFetch(const FullTrackName& name, + SubscribeRemoteTrack::Visitor* visitor, + uint64_t num_previous_groups, + VersionSpecificParameters parameters) = 0; // Sends both a SUBSCRIBE and a joining FETCH, beginning `num_previous_groups` // groups before the current group. `callback` acts the same way as the // callback for the regular Fetch() call. - virtual bool JoiningFetch(const FullTrackName& name, - SubscribeRemoteTrack::Visitor* visitor, - FetchResponseCallback callback, - uint64_t num_previous_groups, MoqtPriority priority, - std::optional delivery_order, - VersionSpecificParameters parameters) = 0; + virtual bool RelativeJoiningFetch( + const FullTrackName& name, SubscribeRemoteTrack::Visitor* visitor, + FetchResponseCallback callback, uint64_t num_previous_groups, + MoqtPriority priority, std::optional delivery_order, + VersionSpecificParameters parameters) = 0; + + // TODO(martinduke): Add an API for absolute joining fetch. // TODO: Add SubscribeAnnounces, UnsubscribeAnnounces method. // TODO: Add Announce, Unannounce method. 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 2fb7225af8..fd156985aa 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 @@ -5,9 +5,11 @@ #include "quiche/quic/moqt/moqt_subscribe_windows.h" #include +#include #include #include +#include "quiche/quic/core/quic_interval.h" #include "quiche/quic/moqt/moqt_messages.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" #include "quiche/common/platform/api/quiche_logging.h" @@ -15,59 +17,23 @@ namespace moqt { -ReducedSequenceIndex::ReducedSequenceIndex( - Location sequence, MoqtForwardingPreference preference) { - switch (preference) { - case MoqtForwardingPreference::kSubgroup: - sequence_ = Location(sequence.group, sequence.subgroup, 0); - break; - case MoqtForwardingPreference::kDatagram: - sequence_ = Location(sequence.group, 0, sequence.object); - return; - } -} - -std::optional SendStreamMap::GetStreamForSequence( - Location sequence) const { - QUICHE_DCHECK(forwarding_preference_ == MoqtForwardingPreference::kSubgroup); - Location index = - ReducedSequenceIndex(sequence, forwarding_preference_).sequence(); - auto group_it = send_streams_.find(index.group); - if (group_it == send_streams_.end()) { +std::optional SendStreamMap::GetStreamFor( + DataStreamIndex index) const { + auto it = send_streams_.find(index); + if (it == send_streams_.end()) { return std::nullopt; } - auto subgroup_it = group_it->second.find(index.subgroup); - if (subgroup_it == group_it->second.end()) { - return std::nullopt; - } - return subgroup_it->second; + return it->second; } -void SendStreamMap::AddStream(Location sequence, +void SendStreamMap::AddStream(DataStreamIndex index, webtransport::StreamId stream_id) { - Location index = - ReducedSequenceIndex(sequence, forwarding_preference_).sequence(); - auto [it, result] = send_streams_.insert({index.group, Group()}); - auto [sg, success] = it->second.try_emplace(index.subgroup, stream_id); + auto [it, success] = send_streams_.emplace(index, stream_id); QUIC_BUG_IF(quic_bug_moqt_draft_03_02, !success) << "Stream already added"; } -void SendStreamMap::RemoveStream(Location sequence, - webtransport::StreamId stream_id) { - Location index = - ReducedSequenceIndex(sequence, forwarding_preference_).sequence(); - auto group_it = send_streams_.find(index.group); - if (group_it == send_streams_.end()) { - QUICHE_NOTREACHED(); - return; - } - auto subgroup_it = group_it->second.find(index.subgroup); - if (subgroup_it == group_it->second.end() || - subgroup_it->second != stream_id) { - QUICHE_NOTREACHED(); - return; - } - group_it->second.erase(subgroup_it); +void SendStreamMap::RemoveStream(DataStreamIndex index) { + send_streams_.erase(index); } bool SubscribeWindow::TruncateStart(Location start) { @@ -96,25 +62,30 @@ bool SubscribeWindow::TruncateEnd(Location largest_id) { std::vector SendStreamMap::GetAllStreams() const { std::vector ids; - for (const auto& [group, subgroup_map] : send_streams_) { - for (const auto& [subgroup, stream_id] : subgroup_map) { - ids.push_back(stream_id); - } + for (const auto& [index, stream_id] : send_streams_) { + ids.push_back(stream_id); } return ids; } std::vector SendStreamMap::GetStreamsForGroup( uint64_t group_id) const { + const auto start_it = send_streams_.lower_bound(DataStreamIndex(group_id, 0)); + const auto end_it = send_streams_.upper_bound( + DataStreamIndex(group_id, std::numeric_limits::max())); std::vector ids; - auto it = send_streams_.find(group_id); - if (it == send_streams_.end()) { - return ids; - } - for (const auto& [subgroup, stream_id] : it->second) { - ids.push_back(stream_id); + for (auto it = start_it; it != end_it; ++it) { + ids.push_back(it->second); } return ids; } +bool SubscribeWindow::GroupInWindow(uint64_t group) const { + const quic::QuicInterval group_window( + Location(group, 0), + Location(group, std::numeric_limits::max())); + const quic::QuicInterval subscription_window(start_, end_); + return group_window.Intersects(subscription_window); +} + } // 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 f1eea5d85a..0348044f8a 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,7 +10,9 @@ #include #include "absl/container/btree_map.h" +#include "quiche/quic/core/quic_interval.h" #include "quiche/quic/moqt/moqt_messages.h" +#include "quiche/quic/moqt/moqt_publisher.h" #include "quiche/common/platform/api/quiche_export.h" #include "quiche/web_transport/web_transport.h" @@ -37,6 +39,7 @@ class QUICHE_EXPORT SubscribeWindow { bool InWindow(const Location& seq) const { return start_ <= seq && seq <= end_; } + bool GroupInWindow(uint64_t group) const; Location start() const { return start_; } Location end() const { return end_; } @@ -55,47 +58,43 @@ class QUICHE_EXPORT SubscribeWindow { Location end_ = Location(UINT64_MAX, UINT64_MAX); }; -// 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: - ReducedSequenceIndex(Location sequence, MoqtForwardingPreference preference); +// A tuple uniquely identifying a WebTransport data stream associated with a +// subscription. By convention, if a DataStreamIndex is necessary for a datagram +// track, `subgroup` is set to zero. +struct DataStreamIndex { + uint64_t group = 0; + uint64_t subgroup = 0; - bool operator==(const ReducedSequenceIndex& other) const { - return sequence_ == other.sequence_; - } - bool operator!=(const ReducedSequenceIndex& other) const { - return sequence_ != other.sequence_; - } - Location sequence() { return sequence_; } + DataStreamIndex() = default; + DataStreamIndex(uint64_t group, uint64_t subgroup) + : group(group), subgroup(subgroup) {} + explicit DataStreamIndex(const PublishedObject& object) + : group(object.metadata.location.group), + subgroup(object.metadata.subgroup) {} + + auto operator<=>(const DataStreamIndex&) const = default; template - friend H AbslHashValue(H h, const ReducedSequenceIndex& m) { - return H::combine(std::move(h), m.sequence_); + friend H AbslHashValue(H h, const DataStreamIndex& index) { + return H::combine(std::move(h), index.group, index.subgroup); } - - private: - Location 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) {} + SendStreamMap() = default; - std::optional GetStreamForSequence( - Location sequence) const; - void AddStream(Location sequence, webtransport::StreamId stream_id); - void RemoveStream(Location sequence, webtransport::StreamId stream_id); + std::optional GetStreamFor( + DataStreamIndex index) const; + void AddStream(DataStreamIndex index, webtransport::StreamId stream_id); + void RemoveStream(DataStreamIndex index); std::vector GetAllStreams() const; std::vector GetStreamsForGroup( uint64_t group_id) const; private: - using Group = absl::btree_map; - absl::btree_map send_streams_; - MoqtForwardingPreference forwarding_preference_; + absl::btree_map send_streams_; }; } // 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 index b62f5b4c49..5deee1cf50 100644 --- 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 @@ -16,7 +16,9 @@ #include "quiche/quic/core/quic_alarm.h" #include "quiche/quic/core/quic_clock.h" #include "quiche/quic/core/quic_time.h" +#include "quiche/quic/moqt/moqt_failed_fetch.h" #include "quiche/quic/moqt/moqt_messages.h" +#include "quiche/quic/moqt/moqt_priority.h" #include "quiche/quic/moqt/moqt_publisher.h" #include "quiche/common/platform/api/quiche_bug_tracker.h" #include "quiche/common/quiche_buffer_allocator.h" @@ -36,10 +38,12 @@ constexpr quic::QuicTimeDelta kMaxSubscribeDoneTimeout = } // namespace bool RemoteTrack::CheckDataStreamType(MoqtDataStreamType type) { - if (data_stream_type_.has_value()) { - return data_stream_type_.value() == type; + if (is_fetch() && !type.IsFetch()) { + return false; + } + if (!is_fetch() && !type.IsSubgroup()) { + return false; } - data_stream_type_ = type; return true; } @@ -98,8 +102,7 @@ void SubscribeRemoteTrack::FetchObjects() { PublishedObject object; switch (fetch_task_->GetNextObject(object)) { case MoqtFetchTask::GetNextObjectResult::kSuccess: - visitor_->OnObjectFragment(full_track_name(), object.sequence, - object.publisher_priority, object.status, + visitor_->OnObjectFragment(full_track_name(), object.metadata, object.payload.AsStringView(), true); break; case MoqtFetchTask::GetNextObjectResult::kError: @@ -121,8 +124,30 @@ UpstreamFetch::~UpstreamFetch() { } void UpstreamFetch::OnFetchResult(Location largest_location, + MoqtDeliveryOrder group_order, absl::Status status, TaskDestroyedCallback callback) { + if (group_order_.has_value()) { + // Data stream already implied a group order. + if (*group_order_ != group_order) { + // The track is malformed. Tell the application it failed. + std::move(ok_callback_)( + std::make_unique(MoqtStreamErrorToStatus( + kResetCodeMalformedTrack, "Group order violation"))); + // Tell the session this failed, so it can cancel the FETCH. + std::move(callback)(); + return; + } + } else { + group_order_ = group_order; + } + if (!status.ok()) { + std::move(ok_callback_)(std::make_unique(status)); + // This is called from OnFetchError, which will delete UpstreamFetch. So + // there is no need to call |callback|, which would inappropriately send a + // FETCH_CANCEL. + return; + } auto task = std::make_unique(largest_location, status, std::move(callback)); task_ = task->weak_ptr(); @@ -142,6 +167,38 @@ void UpstreamFetch::OnStreamOpened(CanReadCallback can_read_callback) { } } +bool UpstreamFetch::LocationIsValid(Location location, MoqtObjectStatus status, + bool end_of_message) { + if (no_more_objects_) { + return false; + } + if (end_of_message && status == MoqtObjectStatus::kEndOfTrack) { + no_more_objects_ = true; + } + bool last_group_is_finished = last_group_is_finished_; + last_group_is_finished_ = + status == MoqtObjectStatus::kEndOfGroup && end_of_message; + std::optional last_location = last_location_; + if (end_of_message) { + last_location_ = location; + } + if (!last_location.has_value()) { + return true; + } + if (last_location->group == location.group) { + return (!last_group_is_finished && location.object > last_location->object); + } + // Group ID has changed. + if (!group_order_.has_value()) { + group_order_ = location.group > last_location->group + ? MoqtDeliveryOrder::kAscending + : MoqtDeliveryOrder::kDescending; + return true; + } + return ((location.group > last_location->group) == + (*group_order_ == MoqtDeliveryOrder::kAscending)); +} + UpstreamFetch::UpstreamFetchTask::~UpstreamFetchTask() { if (task_destroyed_callback_) { std::move(task_destroyed_callback_)(); @@ -164,13 +221,14 @@ UpstreamFetch::UpstreamFetchTask::GetNextObject(PublishedObject& output) { quiche::QuicheMemSlice message_slice(std::move(payload_)); output.payload = std::move(message_slice); } - output.sequence = - Location(next_object_->group_id, next_object_->subgroup_id.value_or(0), - next_object_->object_id); - output.status = next_object_->object_status; - output.publisher_priority = next_object_->publisher_priority; + output.metadata.location = + Location(next_object_->group_id, next_object_->object_id); + output.metadata.subgroup = next_object_->subgroup_id; + output.metadata.status = next_object_->object_status; + output.metadata.publisher_priority = next_object_->publisher_priority; output.fin_after_this = false; - if (output.sequence == largest_location_) { // This is the last object. + if (output.metadata.location == + largest_location_) { // This is the last object. eof_ = true; } next_object_.reset(); @@ -210,7 +268,7 @@ void UpstreamFetch::UpstreamFetchTask::NotifyNewObject() { void UpstreamFetch::UpstreamFetchTask::OnStreamAndFetchClosed( std::optional error, absl::string_view reason_phrase) { - if (eof_ || error.has_value()) { + if (eof_ || !status_.ok()) { return; } // Delete callbacks, because IncomingDataStream and UpstreamFetch are gone. 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 d9abd82454..d2bfc187d0 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 @@ -52,17 +52,9 @@ class RemoteTrack { virtual void OnObjectOrOk() { error_is_allowed_ = false; } bool ErrorIsAllowed() const { return error_is_allowed_; } - // When called while processing the first object in the track, sets the - // data stream type to the value indicated by the incoming encoding. - // Otherwise, returns true if the incoming object does not violate the rule - // that the type is consistent. + // Makes sure the data stream type is consistent with the track type. bool CheckDataStreamType(MoqtDataStreamType type); - bool is_fetch() const { - return data_stream_type_.has_value() && - *data_stream_type_ == MoqtDataStreamType::kStreamHeaderFetch; - } - uint64_t request_id() const { return request_id_; } // Is the object one that was requested? @@ -79,6 +71,8 @@ class RemoteTrack { subscriber_priority_ = priority; } + virtual bool is_fetch() const = 0; + protected: SubscribeWindow& window_mutable() { return window_; }; @@ -87,7 +81,6 @@ class RemoteTrack { const uint64_t request_id_; MoqtPriority subscriber_priority_; SubscribeWindow window_; - std::optional data_stream_type_; // If false, an object or OK message has been received, so any ERROR message // is a protocol violation. bool error_is_allowed_ = true; @@ -117,23 +110,23 @@ class SubscribeRemoteTrack : public RemoteTrack { virtual void OnCanAckObjects(MoqtObjectAckFunction ack_function) = 0; // Called when an object fragment (or an entire object) is received. virtual void OnObjectFragment(const FullTrackName& full_track_name, - Location sequence, - MoqtPriority publisher_priority, - MoqtObjectStatus object_status, + const PublishedObjectMetadata& metadata, absl::string_view object, bool end_of_message) = 0; virtual void OnSubscribeDone(FullTrackName full_track_name) = 0; + // Called when the track is malformed per Section 2.5 of + // draft-ietf-moqt-moq-transport-12. If the application is a relay, it MUST + // terminate downstream delivery of the track. + virtual void OnMalformedTrack(const FullTrackName& full_track_name) = 0; }; SubscribeRemoteTrack(const MoqtSubscribe& subscribe, Visitor* visitor) : RemoteTrack(subscribe.full_track_name, subscribe.request_id, SubscribeWindow(subscribe.start.value_or(Location()), subscribe.end_group), subscribe.subscriber_priority), - track_alias_(subscribe.track_alias), forward_(subscribe.forward), visitor_(visitor), - delivery_timeout_(subscribe.parameters.delivery_timeout), - subscribe_(std::make_unique(subscribe)) {} + delivery_timeout_(subscribe.parameters.delivery_timeout) {} ~SubscribeRemoteTrack() override { if (subscribe_done_alarm_ != nullptr) { subscribe_done_alarm_->PermanentCancel(); @@ -141,25 +134,22 @@ class SubscribeRemoteTrack : public RemoteTrack { } void OnObjectOrOk() override { - subscribe_.reset(); // No SUBSCRIBE_ERROR, no need to store this anymore. RemoteTrack::OnObjectOrOk(); } - uint64_t track_alias() const { return track_alias_; } - Visitor* visitor() { return visitor_; } - MoqtSubscribe& GetSubscribe() { - return *subscribe_; - // This class will soon be destroyed, so there's no need to null the - // unique_ptr; + std::optional track_alias() const { return track_alias_; } + void set_track_alias(uint64_t track_alias) { + track_alias_.emplace(track_alias); } + Visitor* visitor() { return visitor_; } + // Returns false if the forwarding preference is changing on the track. bool OnObject(bool is_datagram) { OnObjectOrOk(); if (!is_datagram_.has_value()) { is_datagram_ = is_datagram; return true; - } else { - return (is_datagram_ == is_datagram); } + return (is_datagram_ == is_datagram); } // Called on SUBSCRIBE_OK or SUBSCRIBE_UPDATE. bool TruncateStart(Location start) { @@ -186,6 +176,8 @@ class SubscribeRemoteTrack : public RemoteTrack { bool forward() const { return forward_; } void set_forward(bool forward) { forward_ = forward; } + bool is_fetch() const override { return false; } + private: friend class test::MoqtSessionPeer; friend class test::SubscribeRemoteTrackPeer; @@ -195,7 +187,7 @@ class SubscribeRemoteTrack : public RemoteTrack { void FetchObjects(); std::unique_ptr fetch_task_; - const uint64_t track_alias_; + std::optional track_alias_; bool forward_; Visitor* visitor_; std::optional is_datagram_; @@ -209,10 +201,6 @@ class SubscribeRemoteTrack : public RemoteTrack { quic::QuicTimeDelta delivery_timeout_ = quic::QuicTimeDelta::Infinite(); std::unique_ptr subscribe_done_alarm_ = nullptr; const quic::QuicClock* clock_ = nullptr; - - // For convenience, store the subscribe message if it has to be re-sent with - // a new track alias. - std::unique_ptr subscribe_; }; // MoqtSession calls this when a FETCH_OK or FETCH_ERROR is received. The @@ -234,17 +222,30 @@ using TaskDestroyedCallback = quiche::SingleUseCallback; // when a FETCH_OK or FETCH_ERROR is received. class UpstreamFetch : public RemoteTrack { public: - UpstreamFetch(const MoqtFetch& fetch, FetchResponseCallback callback) - : RemoteTrack(fetch.full_track_name, fetch.fetch_id, - fetch.joining_fetch.has_value() - ? SubscribeWindow(Location(0, 0)) - : SubscribeWindow(fetch.start_object, fetch.end_group, - fetch.end_object), - fetch.subscriber_priority), - ok_callback_(std::move(callback)) { - // Immediately set the data stream type. - CheckDataStreamType(MoqtDataStreamType::kStreamHeaderFetch); - } + // Standalone Fetch constructor + UpstreamFetch(const MoqtFetch& fetch, const StandaloneFetch standalone, + FetchResponseCallback callback) + : RemoteTrack( + standalone.full_track_name, fetch.request_id, + SubscribeWindow(standalone.start_object, standalone.end_group, + standalone.end_object), + fetch.subscriber_priority), + ok_callback_(std::move(callback)) {} + // Relative Joining Fetch constructor + UpstreamFetch(const MoqtFetch& fetch, FullTrackName full_track_name, + FetchResponseCallback callback) + : RemoteTrack(full_track_name, fetch.request_id, + SubscribeWindow(Location(0, 0)), fetch.subscriber_priority), + ok_callback_(std::move(callback)) {} + // Absolute Joining Fetch constructor + UpstreamFetch(const MoqtFetch& fetch, FullTrackName full_track_name, + JoiningFetchAbsolute absolute_joining, + FetchResponseCallback callback) + : RemoteTrack( + full_track_name, fetch.request_id, + SubscribeWindow(Location(absolute_joining.joining_start, 0)), + fetch.subscriber_priority), + ok_callback_(std::move(callback)) {} UpstreamFetch(const UpstreamFetch&) = delete; ~UpstreamFetch(); @@ -306,7 +307,7 @@ class UpstreamFetch : public RemoteTrack { private: Location largest_location_; - absl::Status status_; + absl::Status status_ = absl::OkStatus(); TaskDestroyedCallback task_destroyed_callback_; // Object delivery state. The payload_length member is used to track the @@ -332,15 +333,27 @@ class UpstreamFetch : public RemoteTrack { }; // Arrival of FETCH_OK/FETCH_ERROR. - void OnFetchResult(Location largest_location, absl::Status status, - TaskDestroyedCallback callback); + void OnFetchResult(Location largest_location, MoqtDeliveryOrder group_order, + absl::Status status, TaskDestroyedCallback callback); UpstreamFetchTask* task() { return task_.GetIfAvailable(); } // Manage the relationship with the data stream. void OnStreamOpened(CanReadCallback callback); + bool is_fetch() const override { return true; } + + // Validate that the track is not malformed due to a location violating group + // order or Object ID order. + bool LocationIsValid(Location location, MoqtObjectStatus status, + bool end_of_message); + private: + std::optional group_order_; // nullopt if not yet known. + std::optional last_location_; + bool last_group_is_finished_ = false; // Received EndOfGroup. + bool no_more_objects_ = false; // Received EndOfTrack + quiche::QuicheWeakPtr task_; // Before FetchTask is created, an incoming stream will register the callback diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/mock_moqt_session.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/mock_moqt_session.cc deleted file mode 100644 index d9c2e1bca4..0000000000 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/mock_moqt_session.cc +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright 2025 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/mock_moqt_session.h" - -#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_failed_fetch.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_subscribe_windows.h" -#include "quiche/quic/moqt/moqt_track.h" -#include "quiche/common/platform/api/quiche_logging.h" -#include "quiche/common/platform/api/quiche_test.h" -#include "quiche/web_transport/web_transport.h" - -namespace moqt::test { - -namespace { -using ::testing::_; -} - -// Object listener that forwards all of the objects to the -// SubcribeRemoteTrack::Visitor provided. -class MockMoqtSession::LoopbackObjectListener : public MoqtObjectListener { - public: - LoopbackObjectListener(FullTrackName name, - SubscribeRemoteTrack::Visitor* visitor, - std::shared_ptr publisher, - SubscribeWindow window) - : name_(name), - visitor_(visitor), - publisher_(std::move(publisher)), - window_(std::move(window)) { - publisher_->AddObjectListener(this); - } - ~LoopbackObjectListener() { publisher_->RemoveObjectListener(this); } - - LoopbackObjectListener(const LoopbackObjectListener&) = delete; - LoopbackObjectListener(LoopbackObjectListener&&) = delete; - LoopbackObjectListener& operator=(const LoopbackObjectListener&) = delete; - LoopbackObjectListener& operator=(LoopbackObjectListener&&) = delete; - - void OnSubscribeAccepted() override { - visitor_->OnReply(name_, - HasObjects() - ? std::make_optional(publisher_->GetLargestLocation()) - : std::nullopt, - std::nullopt); - } - - void OnSubscribeRejected(MoqtSubscribeErrorReason reason, - std::optional track_alias) { - visitor_->OnReply(name_, std::nullopt, reason.reason_phrase); - } - - void OnNewObjectAvailable(Location sequence) { - std::optional object = - publisher_->GetCachedObject(sequence); - if (!object.has_value()) { - QUICHE_LOG(FATAL) - << "GetCachedObject() returned nullopt for a sequence passed into " - "OnNewObjectAvailable()"; - return; - } - if (!window_.InWindow(object->sequence)) { - return; - } - visitor_->OnObjectFragment(name_, sequence, object->publisher_priority, - object->status, object->payload.AsStringView(), - /*end_of_message=*/true); - } - - void OnNewFinAvailable(Location sequence) override {} - void OnSubgroupAbandoned(Location sequence, - webtransport::StreamErrorCode error_code) override {} - void OnGroupAbandoned(uint64_t group_id) override {} - void OnTrackPublisherGone() override { visitor_->OnSubscribeDone(name_); } - - private: - bool HasObjects() { - absl::StatusOr status = publisher_->GetTrackStatus(); - if (!status.ok()) { - return false; - } - return *status == MoqtTrackStatusCode::kInProgress || - *status == MoqtTrackStatusCode::kFinished; - } - - FullTrackName name_; - SubscribeRemoteTrack::Visitor* visitor_; - std::shared_ptr publisher_; - SubscribeWindow window_; -}; - -bool MockMoqtSession::Subscribe(const FullTrackName& name, - SubscribeRemoteTrack::Visitor* visitor, - SubscribeWindow window) { - auto track_publisher = publisher_->GetTrack(name); - if (!track_publisher.ok()) { - visitor->OnReply(name, std::nullopt, track_publisher.status().ToString()); - return false; - } - auto [it, inserted] = receiving_subscriptions_.insert( - {name, - std::make_unique( - name, visitor, *std::move(track_publisher), std::move(window))}); - return inserted; -} - -MockMoqtSession::MockMoqtSession(MoqtPublisher* publisher) - : publisher_(publisher) { - ON_CALL(*this, Error) - .WillByDefault([](MoqtError code, absl::string_view error) { - ADD_FAILURE() << "Unhandled MoQT fatal error, with code " - << static_cast(code) << " and message: " << error; - }); - if (publisher_ != nullptr) { - ON_CALL(*this, SubscribeCurrentObject) - .WillByDefault([this](const FullTrackName& name, - SubscribeRemoteTrack::Visitor* visitor, - VersionSpecificParameters) { - return Subscribe(name, visitor, SubscribeWindow()); - }); - ON_CALL(*this, SubscribeAbsolute(_, _, _, _, _)) - .WillByDefault([this](const FullTrackName& name, uint64_t start_group, - uint64_t start_object, - SubscribeRemoteTrack::Visitor* visitor, - VersionSpecificParameters) { - return Subscribe( - name, visitor, - SubscribeWindow(Location(start_group, start_object))); - }); - ON_CALL(*this, SubscribeAbsolute(_, _, _, _, _, _)) - .WillByDefault([this](const FullTrackName& name, uint64_t start_group, - uint64_t start_object, uint64_t end_group, - SubscribeRemoteTrack::Visitor* visitor, - VersionSpecificParameters) { - return Subscribe( - name, visitor, - SubscribeWindow(Location(start_group, start_object), end_group)); - }); - ON_CALL(*this, Unsubscribe) - .WillByDefault([this](const FullTrackName& name) { - receiving_subscriptions_.erase(name); - }); - ON_CALL(*this, Fetch) - .WillByDefault( - [this](const FullTrackName& name, FetchResponseCallback callback, - Location start, uint64_t end_group, - std::optional end_object, MoqtPriority priority, - std::optional delivery_order, - VersionSpecificParameters parameters) { - auto track_publisher = publisher_->GetTrack(name); - if (!track_publisher.ok()) { - std::move(callback)(std::make_unique( - track_publisher.status())); - return true; - } - std::move(callback)(track_publisher->get()->Fetch( - start, end_group, end_object, - delivery_order.value_or(MoqtDeliveryOrder::kAscending))); - return true; - }); - ON_CALL(*this, JoiningFetch(_, _, _, _)) - .WillByDefault([this](const FullTrackName& name, - SubscribeRemoteTrack::Visitor* visitor, - uint64_t num_previous_groups, - VersionSpecificParameters parameters) { - return JoiningFetch( - name, visitor, - [name, visitor](std::unique_ptr fetch) { - PublishedObject object; - while (fetch->GetNextObject(object) == - MoqtFetchTask::kSuccess) { - visitor->OnObjectFragment( - name, object.sequence, object.publisher_priority, - object.status, object.payload.AsStringView(), true); - } - }, - num_previous_groups, 0x80, std::nullopt, parameters); - }); - ON_CALL(*this, JoiningFetch(_, _, _, _, _, _, _)) - .WillByDefault([this](const FullTrackName& name, - SubscribeRemoteTrack::Visitor* visitor, - FetchResponseCallback callback, - uint64_t num_previous_groups, - MoqtPriority priority, - std::optional delivery_order, - VersionSpecificParameters parameters) { - SubscribeCurrentObject(name, visitor, parameters); - auto track_publisher = publisher_->GetTrack(name); - if (!track_publisher.ok()) { - std::move(callback)( - std::make_unique(track_publisher.status())); - return true; - } - if (track_publisher->get()->GetTrackStatus().value_or( - MoqtTrackStatusCode::kStatusNotAvailable) == - MoqtTrackStatusCode::kNotYetBegun) { - return Fetch(name, std::move(callback), Location(0, 0), 0, 0, - priority, delivery_order, std::move(parameters)); - } - Location largest = track_publisher->get()->GetLargestLocation(); - uint64_t start_group = largest.group >= num_previous_groups - ? largest.group - num_previous_groups + 1 - : 0; - return Fetch(name, std::move(callback), Location(start_group, 0), - largest.group, largest.object, priority, delivery_order, - std::move(parameters)); - }); - } -} - -MockMoqtSession::~MockMoqtSession() = default; - -} // namespace moqt::test diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/mock_moqt_session.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/mock_moqt_session.h deleted file mode 100644 index b80ed7bdf1..0000000000 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/mock_moqt_session.h +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2025 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_MOCK_MOQT_SESSION_H_ -#define QUICHE_QUIC_MOQT_TEST_TOOLS_MOCK_MOQT_SESSION_H_ - -#include -#include -#include - -#include "absl/container/flat_hash_map.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_callbacks.h" -#include "quiche/quic/moqt/moqt_session_interface.h" -#include "quiche/quic/moqt/moqt_subscribe_windows.h" -#include "quiche/quic/moqt/moqt_track.h" -#include "quiche/common/platform/api/quiche_logging.h" -#include "quiche/common/platform/api/quiche_test.h" - -namespace moqt::test { - -// Mock version of MoqtSession. If `publisher` is provided via constructor, all -// of the SUBSCRIBE and FETCH requests are routed towards it. -class MockMoqtSession : public MoqtSessionInterface { - public: - explicit MockMoqtSession(MoqtPublisher* publisher); - ~MockMoqtSession() override; - - MockMoqtSession(const MockMoqtSession&) = delete; - MockMoqtSession(MockMoqtSession&&) = delete; - MockMoqtSession& operator=(const MockMoqtSession&) = delete; - MockMoqtSession& operator=(MockMoqtSession&&) = delete; - - MoqtSessionCallbacks& callbacks() override { return callbacks_; } - - MOCK_METHOD(void, Error, (MoqtError code, absl::string_view error), - (override)); - MOCK_METHOD(bool, SubscribeAbsolute, - (const FullTrackName& name, uint64_t start_group, - uint64_t start_object, SubscribeRemoteTrack::Visitor* visitor, - VersionSpecificParameters parameters), - (override)); - MOCK_METHOD(bool, SubscribeAbsolute, - (const FullTrackName& name, uint64_t start_group, - uint64_t start_object, uint64_t end_group, - SubscribeRemoteTrack::Visitor* visitor, - VersionSpecificParameters parameters), - (override)); - MOCK_METHOD(bool, SubscribeCurrentObject, - (const FullTrackName& name, - SubscribeRemoteTrack::Visitor* visitor, - VersionSpecificParameters parameters), - (override)); - MOCK_METHOD(bool, SubscribeNextGroup, - (const FullTrackName& name, - SubscribeRemoteTrack::Visitor* visitor, - VersionSpecificParameters parameters), - (override)); - MOCK_METHOD(bool, SubscribeUpdate, - (const FullTrackName& name, std::optional start, - std::optional end_group, - std::optional subscriber_priority, - std::optional forward, - VersionSpecificParameters parameters), - (override)); - MOCK_METHOD(void, Unsubscribe, (const FullTrackName& name), (override)); - MOCK_METHOD(bool, Fetch, - (const FullTrackName& name, FetchResponseCallback callback, - Location start, uint64_t end_group, - std::optional end_object, MoqtPriority priority, - std::optional delivery_order, - VersionSpecificParameters parameters), - (override)); - MOCK_METHOD(bool, JoiningFetch, - (const FullTrackName& name, - SubscribeRemoteTrack::Visitor* visitor, - uint64_t num_previous_groups, - VersionSpecificParameters parameters), - (override)); - MOCK_METHOD(bool, JoiningFetch, - (const FullTrackName& name, - SubscribeRemoteTrack::Visitor* visitor, - FetchResponseCallback callback, uint64_t num_previous_groups, - MoqtPriority priority, - std::optional delivery_order, - VersionSpecificParameters parameters), - (override)); - - private: - class LoopbackObjectListener; - - bool Subscribe(const FullTrackName& name, - SubscribeRemoteTrack::Visitor* visitor, - SubscribeWindow window); - - MoqtPublisher* const publisher_ = nullptr; - MoqtSessionCallbacks callbacks_; - absl::flat_hash_map> - receiving_subscriptions_; -}; - -} // namespace moqt::test - -#endif // QUICHE_QUIC_MOQT_TEST_TOOLS_MOCK_MOQT_SESSION_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_framer_utils.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_framer_utils.cc index 921da7b52e..bc979d4bc7 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_framer_utils.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_framer_utils.cc @@ -104,6 +104,15 @@ struct TypeVisitor { MoqtMessageType operator()(const MoqtRequestsBlocked&) { return MoqtMessageType::kRequestsBlocked; } + MoqtMessageType operator()(const MoqtPublish&) { + return MoqtMessageType::kPublish; + } + MoqtMessageType operator()(const MoqtPublishOk&) { + return MoqtMessageType::kPublishOk; + } + MoqtMessageType operator()(const MoqtPublishError&) { + return MoqtMessageType::kPublishError; + } MoqtMessageType operator()(const MoqtObjectAck&) { return MoqtMessageType::kObjectAck; } @@ -188,6 +197,15 @@ struct FramingVisitor { quiche::QuicheBuffer operator()(const MoqtRequestsBlocked& message) { return framer.SerializeRequestsBlocked(message); } + quiche::QuicheBuffer operator()(const MoqtPublish& message) { + return framer.SerializePublish(message); + } + quiche::QuicheBuffer operator()(const MoqtPublishOk& message) { + return framer.SerializePublishOk(message); + } + quiche::QuicheBuffer operator()(const MoqtPublishError& message) { + return framer.SerializePublishError(message); + } quiche::QuicheBuffer operator()(const MoqtObjectAck& message) { return framer.SerializeObjectAck(message); } @@ -277,6 +295,15 @@ class GenericMessageParseVisitor : public MoqtControlParserVisitor { void OnRequestsBlockedMessage(const MoqtRequestsBlocked& message) { frames_.push_back(message); } + void OnPublishMessage(const MoqtPublish& message) { + frames_.push_back(message); + } + void OnPublishOkMessage(const MoqtPublishOk& message) { + frames_.push_back(message); + } + void OnPublishErrorMessage(const MoqtPublishError& message) { + frames_.push_back(message); + } void OnObjectAckMessage(const MoqtObjectAck& message) { frames_.push_back(message); } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_framer_utils.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_framer_utils.h index 8e704f02eb..1b6e996fb0 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_framer_utils.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_framer_utils.h @@ -18,6 +18,7 @@ #include "quiche/quic/moqt/moqt_messages.h" #include "quiche/common/platform/api/quiche_test.h" #include "quiche/common/quiche_data_reader.h" +#include "quiche/common/quiche_mem_slice.h" #include "quiche/common/quiche_stream.h" namespace moqt::test { @@ -33,7 +34,8 @@ using MoqtGenericFrame = MoqtGoAway, MoqtSubscribeAnnounces, MoqtSubscribeAnnouncesOk, MoqtSubscribeAnnouncesError, MoqtUnsubscribeAnnounces, MoqtMaxRequestId, MoqtFetch, MoqtFetchCancel, MoqtFetchOk, - MoqtFetchError, MoqtRequestsBlocked, MoqtObjectAck>; + MoqtFetchError, MoqtRequestsBlocked, MoqtPublish, + MoqtPublishOk, MoqtPublishError, MoqtObjectAck>; MoqtMessageType MessageTypeForGenericMessage(const MoqtGenericFrame& frame); @@ -45,13 +47,23 @@ std::vector ParseGenericMessage(absl::string_view body); MATCHER_P(SerializedControlMessage, message, "Matches against a specific expected MoQT message") { - std::string merged_message = absl::StrJoin(arg, ""); + std::vector data_written; + data_written.reserve(arg.size()); + for (const quiche::QuicheMemSlice& slice : arg) { + data_written.push_back(slice.AsStringView()); + } + std::string merged_message = absl::StrJoin(data_written, ""); return merged_message == SerializeGenericMessage(message); } MATCHER_P(ControlMessageOfType, expected_type, "Matches against an MoQT message of a specific type") { - std::string merged_message = absl::StrJoin(arg, ""); + std::vector data_written; + data_written.reserve(arg.size()); + for (const quiche::QuicheMemSlice& slice : arg) { + data_written.push_back(slice.AsStringView()); + } + std::string merged_message = absl::StrJoin(data_written, ""); quiche::QuicheDataReader reader(merged_message); uint64_t type_raw; if (!reader.ReadVarInt62(&type_raw)) { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_parser_test_visitor.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_parser_test_visitor.h index 759922c701..71ff1b3a51 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_parser_test_visitor.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_parser_test_visitor.h @@ -125,6 +125,15 @@ class MoqtParserTestVisitor : public MoqtControlParserVisitor, void OnRequestsBlockedMessage(const MoqtRequestsBlocked& message) override { OnControlMessage(message); } + void OnPublishMessage(const MoqtPublish& message) override { + OnControlMessage(message); + } + void OnPublishOkMessage(const MoqtPublishOk& message) override { + OnControlMessage(message); + } + void OnPublishErrorMessage(const MoqtPublishError& message) override { + OnControlMessage(message); + } void OnObjectAckMessage(const MoqtObjectAck& message) override { OnControlMessage(message); } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_session_peer.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_session_peer.h index e3ddb7b686..4064ed3a8d 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_session_peer.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_session_peer.h @@ -20,6 +20,7 @@ #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/moqt/tools/moqt_mock_visitor.h" #include "quiche/web_transport/test_tools/mock_web_transport.h" @@ -30,7 +31,7 @@ namespace moqt::test { class MoqtDataParserPeer { public: static void SetType(MoqtDataParser* parser, MoqtDataStreamType type) { - parser->type_ = type; + parser->type_.emplace(std::move(type)); } }; @@ -85,10 +86,13 @@ class MoqtSessionPeer { static void CreateRemoteTrack(MoqtSession* session, const MoqtSubscribe& subscribe, + const std::optional track_alias, SubscribeRemoteTrack::Visitor* visitor) { auto track = std::make_unique(subscribe, visitor); - session->subscribe_by_alias_.try_emplace(subscribe.track_alias, - track.get()); + if (track_alias.has_value()) { + track->set_track_alias(*track_alias); + session->subscribe_by_alias_.try_emplace(*track_alias, track.get()); + } session->subscribe_by_name_.try_emplace(subscribe.full_track_name, track.get()); session->upstream_by_id_.try_emplace(subscribe.request_id, @@ -101,7 +105,6 @@ class MoqtSessionPeer { uint64_t start_object) { MoqtSubscribe subscribe; subscribe.full_track_name = publisher->GetTrackName(); - subscribe.track_alias = track_alias; subscribe.request_id = subscribe_id; subscribe.forward = true; subscribe.filter_type = MoqtFilterType::kAbsoluteStart; @@ -111,6 +114,8 @@ class MoqtSessionPeer { subscribe_id, std::make_unique( session, std::move(publisher), subscribe, /*monitoring_interface=*/nullptr)); + session->published_subscriptions_[subscribe_id]->track_alias_.emplace( + track_alias); return session->published_subscriptions_[subscribe_id].get(); } @@ -177,31 +182,30 @@ class MoqtSessionPeer { // Adds an upstream fetch and a stream ready to receive data. static std::unique_ptr CreateUpstreamFetch( - MoqtSession* session, webtransport::Stream* stream) { + MoqtSession* session, webtransport::Stream* stream, + MoqtDeliveryOrder order = MoqtDeliveryOrder::kAscending) { MoqtFetch fetch_message = { 0, 128, std::nullopt, - std::nullopt, - FullTrackName{"foo", "bar"}, - Location{0, 0}, - 4, - std::nullopt, + StandaloneFetch(FullTrackName{"foo", "bar"}, Location{0, 0}, 4, + std::nullopt), VersionSpecificParameters(), }; std::unique_ptr task; auto [it, success] = session->upstream_by_id_.try_emplace( 0, std::make_unique( - fetch_message, [&](std::unique_ptr fetch_task) { + fetch_message, std::get(fetch_message.fetch), + [&](std::unique_ptr fetch_task) { task = std::move(fetch_task); })); QUICHE_DCHECK(success); UpstreamFetch* fetch = static_cast(it->second.get()); // Initialize the fetch task fetch->OnFetchResult( - Location{4, 10}, absl::OkStatus(), - [=, session_ptr = session, fetch_id = fetch_message.fetch_id]() { - session_ptr->CancelFetch(fetch_id); + Location{4, 10}, order, absl::OkStatus(), + [=, session_ptr = session, request_id = fetch_message.request_id]() { + session_ptr->CancelFetch(request_id); }); ; auto mock_session = @@ -247,11 +251,10 @@ class MoqtSessionPeer { } static bool SubgroupHasBeenReset(MoqtObjectListener* subscription, - Location sequence) { - sequence.object = 0; + DataStreamIndex index) { return static_cast(subscription) ->reset_subgroups() - .contains(sequence); + .contains(index); } }; 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 6614417094..b558c38d4e 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 @@ -23,6 +23,7 @@ #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" @@ -31,6 +32,24 @@ namespace moqt::test { inline constexpr absl::string_view kDefaultExtensionBlob( "\x00\x0c\x01\x03\x66\x6f\x6f", 7); +const MoqtDatagramType kMoqtDatagramTypes[] = { + MoqtDatagramType(false, false), + MoqtDatagramType(false, true), + MoqtDatagramType(true, false), + MoqtDatagramType(true, true), +}; + +const MoqtDataStreamType kMoqtDataStreamTypes[] = { + MoqtDataStreamType::Fetch(), + MoqtDataStreamType::Subgroup(0, 1, true), + MoqtDataStreamType::Subgroup(0, 1, false), + MoqtDataStreamType::Subgroup(1, 1, true), + MoqtDataStreamType::Subgroup(1, 1, false), + MoqtDataStreamType::Subgroup(2, 1, true), + MoqtDataStreamType::Subgroup(2, 1, false), + // Padding omitted. +}; + // Base class containing a wire image and the corresponding structured // representation of an example of each message. It allows parser and framer // tests to iterate through all message types without much specialized code. @@ -47,7 +66,8 @@ class QUICHE_NO_EXPORT TestMessageBase { MoqtGoAway, MoqtSubscribeAnnounces, MoqtSubscribeAnnouncesOk, MoqtSubscribeAnnouncesError, MoqtUnsubscribeAnnounces, MoqtMaxRequestId, MoqtFetch, MoqtFetchCancel, MoqtFetchOk, - MoqtFetchError, MoqtRequestsBlocked, MoqtObjectAck>; + MoqtFetchError, MoqtRequestsBlocked, MoqtPublish, + MoqtPublishOk, MoqtPublishError, MoqtObjectAck>; // The total actual size of the message. size_t total_message_size() const { return wire_image_size_; } @@ -207,61 +227,119 @@ class QUICHE_NO_EXPORT ObjectMessage : public TestMessageBase { /*publisher_priority=*/7, std::string(kDefaultExtensionBlob), /*object_status=*/MoqtObjectStatus::kNormal, - /*subgroup_id=*/std::nullopt, + /*subgroup_id=*/8, /*payload_length=*/3, }; }; class QUICHE_NO_EXPORT ObjectDatagramMessage : public ObjectMessage { public: - ObjectDatagramMessage() : ObjectMessage() { - SetWireImage(raw_packet_, sizeof(raw_packet_)); + ObjectDatagramMessage(MoqtDatagramType datagram_type) + : ObjectMessage(), datagram_type_(datagram_type) { + object_.subgroup_id = object_.object_id; + // Update ObjectMessage::object_ to match the datagram type. + if (datagram_type.has_status()) { + object_.object_status = MoqtObjectStatus::kEndOfGroup; + object_.payload_length = 0; + } else { + object_.object_status = MoqtObjectStatus::kNormal; + object_.payload_length = 3; + } + if (datagram_type.has_extension()) { + object_.extension_headers = std::string(kDefaultExtensionBlob); + } else { + object_.extension_headers = ""; + } + quic::QuicDataWriter writer(sizeof(raw_packet_), + reinterpret_cast(raw_packet_)); + EXPECT_TRUE(writer.WriteVarInt62(datagram_type.value())); + EXPECT_TRUE(writer.WriteStringPiece(kRawVarints)); + if (datagram_type.has_extension()) { + EXPECT_TRUE(writer.WriteStringPiece(kRawExtensions)); + } + if (datagram_type.has_status()) { + EXPECT_TRUE( + writer.WriteVarInt62(static_cast(object_.object_status))); + } else { + EXPECT_TRUE(writer.WriteStringPiece(kRawPayload)); + } + EXPECT_LE(writer.length(), kMaxMessageHeaderSize); + SetWireImage(raw_packet_, writer.length()); } void ExpandVarints() override { - ExpandVarintsImpl("vvvv-v-------v---", false); + if (datagram_type_.has_extension()) { + if (datagram_type_.has_status()) { + ExpandVarintsImpl("vvvv-v-------v", false); + } else { + ExpandVarintsImpl("vvvv-v----------", false); + } + } else { + if (datagram_type_.has_status()) { + ExpandVarintsImpl("vvvv-v", false); + } else { + ExpandVarintsImpl("vvvv----", false); + } + } } private: - uint8_t raw_packet_[17] = { - 0x01, 0x04, 0x05, 0x06, // varints - 0x07, 0x07, // publisher priority, 7B extensions - 0x00, 0x0c, 0x01, 0x03, 0x66, 0x6f, 0x6f, // extensions - 0x03, 0x66, 0x6f, 0x6f, // payload = "foo" - }; -}; - -class QUICHE_NO_EXPORT ObjectStatusDatagramMessage : public ObjectMessage { - public: - ObjectStatusDatagramMessage() : ObjectMessage() { - SetWireImage(raw_packet_, sizeof(raw_packet_)); - object_.object_status = MoqtObjectStatus::kEndOfGroup; - object_.payload_length = 0; - } - - void ExpandVarints() override { ExpandVarintsImpl("vvvv-v-------v", false); } - - private: - uint8_t raw_packet_[14] = { - 0x02, 0x04, 0x05, 0x06, // varints - 0x07, // publisher priority - 0x07, // 7B extensions - 0x00, 0x0c, 0x01, 0x03, 0x66, 0x6f, 0x6f, // extensions - 0x03, // kEndOfGroup - }; + uint8_t raw_packet_[17]; + MoqtDatagramType datagram_type_; + static constexpr absl::string_view kRawVarints = "\x04\x05\x06\x07"; + static constexpr absl::string_view kRawExtensions{ + "\x07\x00\x0c\x01\x03\x66\x6f\x6f", 8}; // see kDefaultExtensionBlob + static constexpr absl::string_view kRawPayload = "foo"; }; // Concatenation of the base header and the object-specific header. Follow-on // object headers are handled in a different class. class QUICHE_NO_EXPORT StreamHeaderSubgroupMessage : public ObjectMessage { public: - StreamHeaderSubgroupMessage() : ObjectMessage() { - SetWireImage(raw_packet_, sizeof(raw_packet_)); - object_.subgroup_id = 8; + explicit StreamHeaderSubgroupMessage(MoqtDataStreamType type) + : ObjectMessage(), type_(type) { + // Update ObjectMessage from the type; + if (type.SubgroupIsZero()) { + object_.subgroup_id = 0; + } else if (type.SubgroupIsFirstObjectId()) { + object_.subgroup_id = object_.object_id; + } + if (!type.AreExtensionHeadersPresent()) { + object_.extension_headers = ""; + } + // Build raw_packet_ from the type. + quic::QuicDataWriter writer(sizeof(raw_packet_), raw_packet_); + EXPECT_TRUE( + writer.WriteVarInt62(type.value()) && + writer.WriteBytes(kRawBeginning.data(), kRawBeginning.length())); + if (type.IsSubgroupPresent()) { + EXPECT_TRUE(writer.WriteUInt8(object_.subgroup_id)); + } + EXPECT_TRUE(writer.WriteBytes(kRawMiddle.data(), kRawMiddle.length())); + if (type.AreExtensionHeadersPresent()) { + EXPECT_TRUE( + writer.WriteBytes(kRawExtensions.data(), kRawExtensions.length())); + } + payload_length_offset_ = writer.length(); + EXPECT_TRUE(writer.WriteBytes(kRawPayload.data(), kRawPayload.length())); + EXPECT_LE(writer.length(), kMaxMessageHeaderSize); + SetWireImage(reinterpret_cast(raw_packet_), writer.length()); } void ExpandVarints() override { - ExpandVarintsImpl("vvvv-vv-------v---", false); + if (!type_.IsSubgroupPresent()) { + if (!type_.AreExtensionHeadersPresent()) { + ExpandVarintsImpl("vvv-vv---", false); + } else { + ExpandVarintsImpl("vvv-vv-------v---", false); + } + } else { + if (!type_.AreExtensionHeadersPresent()) { + ExpandVarintsImpl("vvvv-vv---", false); + } else { + ExpandVarintsImpl("vvvv-vv-------v---", false); + } + } } bool SetPayloadLength(uint8_t payload_length) { @@ -269,40 +347,64 @@ class QUICHE_NO_EXPORT StreamHeaderSubgroupMessage : public ObjectMessage { // This only supports one-byte varints. return false; } + int payload_length_change = payload_length - object_.payload_length; object_.payload_length = payload_length; - raw_packet_[14] = payload_length; - SetWireImage(raw_packet_, sizeof(raw_packet_)); + raw_packet_[payload_length_offset_] = static_cast(payload_length); + SetWireImage(reinterpret_cast(raw_packet_), total_message_size()); + set_wire_image_size(total_message_size() + payload_length_change); return true; } private: - uint8_t raw_packet_[18] = { - 0x04, // type field - 0x04, 0x05, 0x08, // varints - 0x07, // publisher priority - 0x06, 0x07, // object ID, 7B extensions - 0x00, 0x0c, 0x01, 0x03, 0x66, 0x6f, 0x6f, // extensions - 0x03, 0x66, 0x6f, 0x6f, // payload = "foo" - }; + MoqtDataStreamType type_; + static constexpr absl::string_view kRawBeginning = "\x04\x05"; + // track alias, group ID + static constexpr absl::string_view kRawMiddle = "\x07\x06"; + // publisher priority, object ID + static constexpr absl::string_view kRawExtensions{ + "\x07\x00\x0c\x01\x03\x66\x6f\x6f", 8}; // see kDefaultExtensionBlob + static constexpr absl::string_view kRawPayload = "\x03\x66\x6f\x6f"; + char raw_packet_[18]; + size_t payload_length_offset_; }; // Used only for tests that process multiple objects on one stream. class QUICHE_NO_EXPORT StreamMiddlerSubgroupMessage : public ObjectMessage { public: - StreamMiddlerSubgroupMessage() : ObjectMessage() { - SetWireImage(raw_packet_, sizeof(raw_packet_)); - object_.subgroup_id = 8; + StreamMiddlerSubgroupMessage(MoqtDataStreamType type) + : ObjectMessage(), type_(type) { + SetWireImage(reinterpret_cast(raw_packet_), sizeof(raw_packet_)); + if (type.SubgroupIsZero()) { + object_.subgroup_id = 0; + } else if (type.SubgroupIsFirstObjectId()) { + object_.subgroup_id = 6; // The object ID in the header. + } object_.object_id = 9; + quic::QuicDataWriter writer(sizeof(raw_packet_), raw_packet_); + EXPECT_TRUE(writer.WriteVarInt62(object_.object_id)); + if (type.AreExtensionHeadersPresent()) { + EXPECT_TRUE( + writer.WriteBytes(kRawExtensions.data(), kRawExtensions.length())); + } + EXPECT_TRUE(writer.WriteBytes(kRawPayload.data(), kRawPayload.length())); + EXPECT_LE(writer.length(), kMaxMessageHeaderSize); + SetWireImage(reinterpret_cast(raw_packet_), writer.length()); } - void ExpandVarints() override { ExpandVarintsImpl("vv-------v---", false); } + void ExpandVarints() override { + if (type_.AreExtensionHeadersPresent()) { + ExpandVarintsImpl("vv-------v---", false); + } else { + ExpandVarintsImpl("vv---", false); + } + } private: - uint8_t raw_packet_[13] = { - 0x09, 0x07, // object ID; 7B extensions - 0x00, 0x0c, 0x01, 0x03, 0x66, 0x6f, 0x6f, // extensions - 0x03, 0x62, 0x61, 0x72, // payload = "bar" - }; + MoqtDataStreamType type_; + static constexpr absl::string_view kRawExtensions{ + "\x07\x00\x0c\x01\x03\x66\x6f\x6f", 8}; // see kDefaultExtensionBlob + static constexpr absl::string_view kRawPayload = "\x03\x62\x61\x72"; + char raw_packet_[13]; }; class QUICHE_NO_EXPORT StreamHeaderFetchMessage : public ObjectMessage { @@ -354,9 +456,9 @@ class QUICHE_NO_EXPORT StreamMiddlerFetchMessage : public ObjectMessage { private: uint8_t raw_packet_[16] = { - 0x05, 0x08, 0x09, 0x07, 0x07, // Object metadata - 0x00, 0x0c, 0x01, 0x03, 0x66, 0x6f, 0x6f, // extensions - 0x03, 0x62, 0x61, 0x72, // Payload = "bar" + 0x05, 0x08, 0x09, 0x07, // Object metadata + 0x07, 0x00, 0x0c, 0x01, 0x03, 0x66, 0x6f, 0x6f, // extensions + 0x03, 0x62, 0x61, 0x72, // Payload = "bar" }; }; @@ -469,10 +571,6 @@ class QUICHE_NO_EXPORT SubscribeMessage : public TestMessageBase { QUIC_LOG(INFO) << "SUBSCRIBE subscribe ID mismatch"; return false; } - if (cast.track_alias != subscribe_.track_alias) { - QUIC_LOG(INFO) << "SUBSCRIBE track alias mismatch"; - return false; - } if (cast.full_track_name != subscribe_.full_track_name) { QUIC_LOG(INFO) << "SUBSCRIBE track name mismatch"; return false; @@ -509,7 +607,7 @@ class QUICHE_NO_EXPORT SubscribeMessage : public TestMessageBase { } void ExpandVarints() override { - ExpandVarintsImpl("vvvv---v-------vvvvv--vv-----"); + ExpandVarintsImpl("vvv---v-------vvvvv--vv-----"); } MessageStructuredData structured_data() const override { @@ -517,25 +615,43 @@ class QUICHE_NO_EXPORT SubscribeMessage : public TestMessageBase { } private: - uint8_t raw_packet_[32] = { - 0x03, 0x00, 0x1d, 0x01, 0x02, // id and alias - 0x01, 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" - 0x04, 0x61, 0x62, 0x63, 0x64, // track_name = "abcd" - 0x20, // subscriber priority = 0x20 - 0x02, // group order = descending - 0x01, // forward = true - 0x03, // Filter type: Absolute Start - 0x04, // start_group = 4 - 0x01, // start_object = 1 + uint8_t raw_packet_[31] = { + 0x03, + 0x00, + 0x1c, + 0x01, // request_id = 1 + 0x01, + 0x03, + 0x66, + 0x6f, + 0x6f, // track_namespace = "foo" + 0x04, + 0x61, + 0x62, + 0x63, + 0x64, // track_name = "abcd" + 0x20, // subscriber priority = 0x20 + 0x02, // group order = descending + 0x01, // forward = true + 0x03, // Filter type: Absolute Start + 0x04, // start_group = 4 + 0x01, // start_object = 1 // No EndGroup or EndObject - 0x02, // 2 parameters - 0x02, 0x67, 0x10, // delivery_timeout = 10000 ms - 0x01, 0x05, 0x03, 0x00, 0x62, 0x61, 0x72, // authorization_tag = "bar" + 0x02, // 2 parameters + 0x02, + 0x67, + 0x10, // delivery_timeout = 10000 ms + 0x03, + 0x05, + 0x03, + 0x00, + 0x62, + 0x61, + 0x72, // authorization_tag = "bar" }; MoqtSubscribe subscribe_ = { - /*subscribe_id=*/1, - /*track_alias=*/2, + /*request_id=*/1, FullTrackName("foo", "abcd"), /*subscriber_priority=*/0x20, /*group_order=*/MoqtDeliveryOrder::kDescending, @@ -560,6 +676,10 @@ class QUICHE_NO_EXPORT SubscribeOkMessage : public TestMessageBase { QUIC_LOG(INFO) << "SUBSCRIBE OK subscribe ID mismatch"; return false; } + if (cast.track_alias != subscribe_ok_.track_alias) { + QUIC_LOG(INFO) << "SUBSCRIBE OK track alias mismatch"; + return false; + } if (cast.expires != subscribe_ok_.expires) { QUIC_LOG(INFO) << "SUBSCRIBE OK expiration mismatch"; return false; @@ -579,34 +699,35 @@ class QUICHE_NO_EXPORT SubscribeOkMessage : public TestMessageBase { return true; } - void ExpandVarints() override { ExpandVarintsImpl("vv--vvvv--v--"); } + void ExpandVarints() override { ExpandVarintsImpl("vvv--vvvv--v--"); } MessageStructuredData structured_data() const override { return TestMessageBase::MessageStructuredData(subscribe_ok_); } void SetInvalidContentExists() { - raw_packet_[6] = 0x02; + raw_packet_[7] = 0x02; SetWireImage(raw_packet_, sizeof(raw_packet_)); } void SetInvalidDeliveryOrder() { - raw_packet_[5] = 0x10; + raw_packet_[6] = 0x10; SetWireImage(raw_packet_, sizeof(raw_packet_)); } private: - uint8_t raw_packet_[16] = { - 0x04, 0x00, 0x0d, 0x01, 0x03, // request_id = 1, expires = 3 - 0x02, 0x01, // group_order = 2, content exists - 0x0c, 0x14, // largest_location = (12, 20) - 0x02, // 2 parameters - 0x02, 0x67, 0x10, // delivery_timeout = 10000 - 0x04, 0x67, 0x10, // max_cache_duration = 10000 + uint8_t raw_packet_[17] = { + 0x04, 0x00, 0x0e, 0x01, 0x02, 0x03, // request_id, alias, expires + 0x02, 0x01, // group_order = 2, content exists + 0x0c, 0x14, // largest_location = (12, 20) + 0x02, // 2 parameters + 0x02, 0x67, 0x10, // delivery_timeout = 10000 + 0x04, 0x67, 0x10, // max_cache_duration = 10000 }; MoqtSubscribeOk subscribe_ok_ = { /*request_id=*/1, + /*track_alias=*/2, /*expires=*/quic::QuicTimeDelta::FromMilliseconds(3), /*group_order=*/MoqtDeliveryOrder::kDescending, /*largest_location=*/Location(12, 20), @@ -635,33 +756,27 @@ class QUICHE_NO_EXPORT SubscribeErrorMessage : public TestMessageBase { QUIC_LOG(INFO) << "SUBSCRIBE ERROR reason phrase mismatch"; return false; } - if (cast.track_alias != subscribe_error_.track_alias) { - QUIC_LOG(INFO) << "SUBSCRIBE ERROR track alias mismatch"; - return false; - } return true; } - void ExpandVarints() override { ExpandVarintsImpl("vvv---v"); } + void ExpandVarints() override { ExpandVarintsImpl("vvv---"); } MessageStructuredData structured_data() const override { return TestMessageBase::MessageStructuredData(subscribe_error_); } private: - uint8_t raw_packet_[10] = { - 0x05, 0x00, 0x07, + uint8_t raw_packet_[9] = { + 0x05, 0x00, 0x06, 0x02, // request_id = 2 0x05, // error_code = 5 0x03, 0x62, 0x61, 0x72, // reason_phrase = "bar" - 0x04, // track_alias = 4 }; MoqtSubscribeError subscribe_error_ = { /*request_id=*/2, /*error_code=*/RequestErrorCode::kInvalidRange, /*reason_phrase=*/"bar", - /*track_alias=*/4, }; }; @@ -673,8 +788,8 @@ class QUICHE_NO_EXPORT UnsubscribeMessage : public TestMessageBase { bool EqualFieldValues(MessageStructuredData& values) const override { auto cast = std::get(values); - if (cast.subscribe_id != unsubscribe_.subscribe_id) { - QUIC_LOG(INFO) << "UNSUBSCRIBE subscribe ID mismatch"; + if (cast.request_id != unsubscribe_.request_id) { + QUIC_LOG(INFO) << "UNSUBSCRIBE request ID mismatch"; return false; } return true; @@ -688,11 +803,11 @@ class QUICHE_NO_EXPORT UnsubscribeMessage : public TestMessageBase { private: uint8_t raw_packet_[4] = { - 0x0a, 0x00, 0x01, 0x03, // subscribe_id = 3 + 0x0a, 0x00, 0x01, 0x03, // request_id = 3 }; MoqtUnsubscribe unsubscribe_ = { - /*subscribe_id=*/3, + /*request_id=*/3, }; }; @@ -704,8 +819,8 @@ class QUICHE_NO_EXPORT SubscribeDoneMessage : public TestMessageBase { bool EqualFieldValues(MessageStructuredData& values) const override { auto cast = std::get(values); - if (cast.subscribe_id != subscribe_done_.subscribe_id) { - QUIC_LOG(INFO) << "SUBSCRIBE_DONE subscribe ID mismatch"; + if (cast.request_id != subscribe_done_.request_id) { + QUIC_LOG(INFO) << "SUBSCRIBE_DONE request ID mismatch"; return false; } if (cast.status_code != subscribe_done_.status_code) { @@ -716,8 +831,8 @@ class QUICHE_NO_EXPORT SubscribeDoneMessage : public TestMessageBase { QUIC_LOG(INFO) << "SUBSCRIBE_DONE stream count mismatch"; return false; } - if (cast.reason_phrase != subscribe_done_.reason_phrase) { - QUIC_LOG(INFO) << "SUBSCRIBE_DONE reason phrase mismatch"; + if (cast.error_reason != subscribe_done_.error_reason) { + QUIC_LOG(INFO) << "SUBSCRIBE_DONE error reason mismatch"; return false; } @@ -732,16 +847,16 @@ class QUICHE_NO_EXPORT SubscribeDoneMessage : public TestMessageBase { private: uint8_t raw_packet_[9] = { - 0x0b, 0x00, 0x06, 0x02, 0x02, // subscribe_id = 2, error_code = 2, + 0x0b, 0x00, 0x06, 0x02, 0x02, // request_id = 2, error_code = 2, 0x05, // stream_count = 5 - 0x02, 0x68, 0x69, // reason_phrase = "hi" + 0x02, 0x68, 0x69, // error_reason = "hi" }; MoqtSubscribeDone subscribe_done_ = { - /*subscribe_id=*/2, + /*request_id=*/2, /*error_code=*/SubscribeDoneCode::kTrackEnded, /*stream_count=*/5, - /*reason_phrase=*/"hi", + /*error_reason=*/"hi", }; }; @@ -813,32 +928,37 @@ class QUICHE_NO_EXPORT AnnounceMessage : public TestMessageBase { bool EqualFieldValues(MessageStructuredData& values) const override { auto cast = std::get(values); + if (cast.request_id != announce_.request_id) { + QUIC_LOG(INFO) << "ANNOUNCE request ID mismatch"; + return false; + } if (cast.track_namespace != announce_.track_namespace) { - QUIC_LOG(INFO) << "ANNOUNCE MESSAGE track namespace mismatch"; + QUIC_LOG(INFO) << "ANNOUNCE track namespace mismatch"; return false; } if (cast.parameters != announce_.parameters) { - QUIC_LOG(INFO) << "ANNOUNCE MESSAGE parameter mismatch"; + QUIC_LOG(INFO) << "ANNOUNCE parameter mismatch"; return false; } return true; } - void ExpandVarints() override { ExpandVarintsImpl("vv---vvv-----"); } + void ExpandVarints() override { ExpandVarintsImpl("vvv---vvv-----"); } MessageStructuredData structured_data() const override { return TestMessageBase::MessageStructuredData(announce_); } private: - uint8_t raw_packet_[16] = { - 0x06, 0x00, 0x0d, 0x01, 0x03, 0x66, 0x6f, - 0x6f, // track_namespace = "foo" + uint8_t raw_packet_[17] = { + 0x06, 0x00, 0x0e, 0x02, // request_id = 2 + 0x01, 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" 0x01, // 1 parameter - 0x01, 0x05, 0x03, 0x00, 0x62, 0x61, 0x72, // authorization_tag = "bar" + 0x03, 0x05, 0x03, 0x00, 0x62, 0x61, 0x72, // authorization_tag = "bar" }; MoqtAnnounce announce_ = { + /*request_id=*/2, TrackNamespace{"foo"}, VersionSpecificParameters(AuthTokenType::kOutOfBand, "bar"), }; @@ -852,27 +972,26 @@ class QUICHE_NO_EXPORT AnnounceOkMessage : public TestMessageBase { bool EqualFieldValues(MessageStructuredData& values) const override { auto cast = std::get(values); - if (cast.track_namespace != announce_ok_.track_namespace) { - QUIC_LOG(INFO) << "ANNOUNCE OK MESSAGE track namespace mismatch"; + if (cast.request_id != announce_ok_.request_id) { + QUIC_LOG(INFO) << "ANNOUNCE OK MESSAGE request ID mismatch"; return false; } return true; } - void ExpandVarints() override { ExpandVarintsImpl("vv---"); } + void ExpandVarints() override { ExpandVarintsImpl("v"); } MessageStructuredData structured_data() const override { return TestMessageBase::MessageStructuredData(announce_ok_); } private: - uint8_t raw_packet_[8] = { - 0x07, 0x00, 0x05, 0x01, - 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" + uint8_t raw_packet_[4] = { + 0x07, 0x00, 0x01, 0x01, // request_id = 1 }; MoqtAnnounceOk announce_ok_ = { - TrackNamespace("foo"), + /*request_id=*/1, }; }; @@ -884,37 +1003,36 @@ class QUICHE_NO_EXPORT AnnounceErrorMessage : public TestMessageBase { bool EqualFieldValues(MessageStructuredData& values) const override { auto cast = std::get(values); - if (cast.track_namespace != announce_error_.track_namespace) { - QUIC_LOG(INFO) << "ANNOUNCE ERROR track namespace mismatch"; + if (cast.request_id != announce_error_.request_id) { + QUIC_LOG(INFO) << "ANNOUNCE_ERROR request ID mismatch"; return false; } if (cast.error_code != announce_error_.error_code) { - QUIC_LOG(INFO) << "ANNOUNCE ERROR error code mismatch"; + QUIC_LOG(INFO) << "ANNOUNCE_ERROR error code mismatch"; return false; } - if (cast.reason_phrase != announce_error_.reason_phrase) { - QUIC_LOG(INFO) << "ANNOUNCE ERROR reason phrase mismatch"; + if (cast.error_reason != announce_error_.error_reason) { + QUIC_LOG(INFO) << "ANNOUNCE_ERROR error reason mismatch"; return false; } return true; } - void ExpandVarints() override { ExpandVarintsImpl("vv---vv---"); } + void ExpandVarints() override { ExpandVarintsImpl("vvv---"); } MessageStructuredData structured_data() const override { return TestMessageBase::MessageStructuredData(announce_error_); } private: - uint8_t raw_packet_[13] = { - 0x08, 0x00, 0x0a, 0x01, - 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" + uint8_t raw_packet_[9] = { + 0x08, 0x00, 0x06, 0x01, // request_id = 1 0x03, // error_code = 3 0x03, 0x62, 0x61, 0x72, // reason_phrase = "bar" }; MoqtAnnounceError announce_error_ = { - TrackNamespace("foo"), + /*request_id=*/1, RequestErrorCode::kNotSupported, /*reason_phrase=*/"bar", }; @@ -936,7 +1054,7 @@ class QUICHE_NO_EXPORT AnnounceCancelMessage : public TestMessageBase { QUIC_LOG(INFO) << "ANNOUNCE CANCEL error code mismatch"; return false; } - if (cast.reason_phrase != announce_cancel_.reason_phrase) { + if (cast.error_reason != announce_cancel_.error_reason) { QUIC_LOG(INFO) << "ANNOUNCE CANCEL reason phrase mismatch"; return false; } @@ -954,13 +1072,13 @@ class QUICHE_NO_EXPORT AnnounceCancelMessage : public TestMessageBase { 0x0c, 0x00, 0x0a, 0x01, 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" 0x03, // error_code = 3 - 0x03, 0x62, 0x61, 0x72, // reason_phrase = "bar" + 0x03, 0x62, 0x61, 0x72, // error_reason = "bar" }; MoqtAnnounceCancel announce_cancel_ = { TrackNamespace("foo"), RequestErrorCode::kNotSupported, - /*reason_phrase=*/"bar", + /*error_reason=*/"bar", }; }; @@ -972,6 +1090,10 @@ class QUICHE_NO_EXPORT TrackStatusRequestMessage : public TestMessageBase { bool EqualFieldValues(MessageStructuredData& values) const override { auto cast = std::get(values); + if (cast.request_id != track_status_request_.request_id) { + QUIC_LOG(INFO) << "TRACK STATUS REQUEST request ID mismatch"; + return false; + } if (cast.full_track_name != track_status_request_.full_track_name) { QUIC_LOG(INFO) << "TRACK STATUS REQUEST track name mismatch"; return false; @@ -983,22 +1105,23 @@ class QUICHE_NO_EXPORT TrackStatusRequestMessage : public TestMessageBase { return true; } - void ExpandVarints() override { ExpandVarintsImpl("vv---v----vvv-----"); } + void ExpandVarints() override { ExpandVarintsImpl("vvv---v----vvv-----"); } MessageStructuredData structured_data() const override { return TestMessageBase::MessageStructuredData(track_status_request_); } private: - uint8_t raw_packet_[21] = { - 0x0d, 0x00, 0x12, 0x01, 0x03, 0x66, 0x6f, - 0x6f, // track_namespace = "foo" + uint8_t raw_packet_[22] = { + 0x0d, 0x00, 0x13, 0x02, // request_id = 2 + 0x01, 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" 0x04, 0x61, 0x62, 0x63, 0x64, // track_name = "abcd" 0x01, // 1 parameter - 0x01, 0x05, 0x03, 0x00, 0x62, 0x61, 0x72, // authorization_tag = "bar" + 0x03, 0x05, 0x03, 0x00, 0x62, 0x61, 0x72, // authorization_tag = "bar" }; MoqtTrackStatusRequest track_status_request_ = { + /*request_id=*/2, FullTrackName("foo", "abcd"), VersionSpecificParameters(AuthTokenType::kOutOfBand, "bar"), }; @@ -1043,20 +1166,16 @@ class QUICHE_NO_EXPORT TrackStatusMessage : public TestMessageBase { bool EqualFieldValues(MessageStructuredData& values) const override { auto cast = std::get(values); - if (cast.full_track_name != track_status_.full_track_name) { - QUIC_LOG(INFO) << "TRACK STATUS track name mismatch"; + if (cast.request_id != track_status_.request_id) { + QUIC_LOG(INFO) << "TRACK STATUS request ID 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"; + if (cast.largest_location != track_status_.largest_location) { + QUIC_LOG(INFO) << "TRACK STATUS largest location mismatch"; return false; } if (cast.parameters != track_status_.parameters) { @@ -1066,28 +1185,25 @@ class QUICHE_NO_EXPORT TrackStatusMessage : public TestMessageBase { return true; } - void ExpandVarints() override { ExpandVarintsImpl("vv---v----vvvvv--v--"); } + void ExpandVarints() override { ExpandVarintsImpl("v-vvvv--v--"); } MessageStructuredData structured_data() const override { return TestMessageBase::MessageStructuredData(track_status_); } private: - uint8_t raw_packet_[23] = { - 0x0e, 0x00, 0x14, 0x01, 0x03, - 0x66, 0x6f, 0x6f, // track_namespace = "foo" - 0x04, 0x61, 0x62, 0x63, 0x64, // track_name = "abcd" - 0x00, 0x0c, 0x14, // status, last_group, last_object - 0x02, // 2 parameters - 0x02, 0x67, 0x10, // Delivery Timeout = 10000 - 0x04, 0x67, 0x10, // Max Cache Duration = 10000 + uint8_t raw_packet_[14] = { + 0x0e, 0x00, 0x0b, 0x02, // request_id = 2 + 0x00, 0x0c, 0x14, // status, last_group, last_object + 0x02, // 2 parameters + 0x02, 0x67, 0x10, // Delivery Timeout = 10000 + 0x04, 0x67, 0x10, // Max Cache Duration = 10000 }; MoqtTrackStatus track_status_ = { - FullTrackName("foo", "abcd"), + /*request_id=*/2, /*status_code=*/MoqtTrackStatusCode::kInProgress, - /*last_group=*/12, - /*last_object=*/20, + /*largest_location=*/Location(12, 20), VersionSpecificParameters(quic::QuicTimeDelta::FromMilliseconds(10000), quic::QuicTimeDelta::FromMilliseconds(10000)), }; @@ -1132,6 +1248,10 @@ class QUICHE_NO_EXPORT SubscribeAnnouncesMessage : public TestMessageBase { bool EqualFieldValues(MessageStructuredData& values) const override { auto cast = std::get(values); + if (cast.request_id != subscribe_namespace_.request_id) { + QUIC_LOG(INFO) << "SUBSCRIBE_NAMESPACE request_id mismatch"; + return false; + } if (cast.track_namespace != subscribe_namespace_.track_namespace) { QUIC_LOG(INFO) << "SUBSCRIBE_NAMESPACE track namespace mismatch"; return false; @@ -1143,20 +1263,22 @@ class QUICHE_NO_EXPORT SubscribeAnnouncesMessage : public TestMessageBase { return true; } - void ExpandVarints() override { ExpandVarintsImpl("vv---vvv-----"); } + void ExpandVarints() override { ExpandVarintsImpl("vvv---vvv-----"); } MessageStructuredData structured_data() const override { return TestMessageBase::MessageStructuredData(subscribe_namespace_); } private: - uint8_t raw_packet_[16] = { - 0x11, 0x00, 0x0d, 0x01, 0x03, 0x66, 0x6f, 0x6f, // namespace = "foo" - 0x01, // 1 parameter - 0x01, 0x05, 0x03, 0x00, 0x62, 0x61, 0x72, // authorization_tag = "bar" + uint8_t raw_packet_[17] = { + 0x11, 0x00, 0x0e, 0x01, // request_id = 1 + 0x01, 0x03, 0x66, 0x6f, 0x6f, // namespace = "foo" + 0x01, // 1 parameter + 0x03, 0x05, 0x03, 0x00, 0x62, 0x61, 0x72, // authorization_tag = "bar" }; MoqtSubscribeAnnounces subscribe_namespace_ = { + /*request_id=*/1, TrackNamespace("foo"), VersionSpecificParameters(AuthTokenType::kOutOfBand, "bar"), }; @@ -1170,26 +1292,26 @@ class QUICHE_NO_EXPORT SubscribeAnnouncesOkMessage : public TestMessageBase { bool EqualFieldValues(MessageStructuredData& values) const override { auto cast = std::get(values); - if (cast.track_namespace != subscribe_namespace_ok_.track_namespace) { - QUIC_LOG(INFO) << "SUBSCRIBE_NAMESPACE_OK track namespace mismatch"; + if (cast.request_id != subscribe_namespace_ok_.request_id) { + QUIC_LOG(INFO) << "SUBSCRIBE_NAMESPACE_OK request_id mismatch"; return false; } return true; } - void ExpandVarints() override { ExpandVarintsImpl("vv---"); } + void ExpandVarints() override { ExpandVarintsImpl("v"); } MessageStructuredData structured_data() const override { return TestMessageBase::MessageStructuredData(subscribe_namespace_ok_); } private: - uint8_t raw_packet_[8] = { - 0x12, 0x00, 0x05, 0x01, 0x03, 0x66, 0x6f, 0x6f, // namespace = "foo" + uint8_t raw_packet_[4] = { + 0x12, 0x00, 0x01, 0x01, // request_id = 1 }; MoqtSubscribeAnnouncesOk subscribe_namespace_ok_ = { - TrackNamespace("foo"), + /*request_id=*/1, }; }; @@ -1201,39 +1323,38 @@ class QUICHE_NO_EXPORT SubscribeAnnouncesErrorMessage : public TestMessageBase { bool EqualFieldValues(MessageStructuredData& values) const override { auto cast = std::get(values); - if (cast.track_namespace != subscribe_namespace_error_.track_namespace) { - QUIC_LOG(INFO) << "SUBSCRIBE_NAMESPACE_ERROR track namespace mismatch"; + if (cast.request_id != subscribe_namespace_error_.request_id) { + QUIC_LOG(INFO) << "SUBSCRIBE_NAMESPACE_ERROR request_id mismatch"; return false; } if (cast.error_code != subscribe_namespace_error_.error_code) { QUIC_LOG(INFO) << "SUBSCRIBE_NAMESPACE_ERROR error code mismatch"; return false; } - if (cast.reason_phrase != subscribe_namespace_error_.reason_phrase) { - QUIC_LOG(INFO) << "SUBSCRIBE_NAMESPACE_ERROR reason phrase mismatch"; + if (cast.error_reason != subscribe_namespace_error_.error_reason) { + QUIC_LOG(INFO) << "SUBSCRIBE_NAMESPACE_ERROR error reason mismatch"; return false; } return true; } - void ExpandVarints() override { ExpandVarintsImpl("vv---vv---"); } + void ExpandVarints() override { ExpandVarintsImpl("vvv---"); } MessageStructuredData structured_data() const override { return TestMessageBase::MessageStructuredData(subscribe_namespace_error_); } private: - uint8_t raw_packet_[13] = { - 0x13, 0x00, 0x0a, 0x01, - 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" + uint8_t raw_packet_[9] = { + 0x13, 0x00, 0x06, 0x01, // request_id = 1 0x01, // error_code = 1 - 0x03, 0x62, 0x61, 0x72, // reason_phrase = "bar" + 0x03, 0x62, 0x61, 0x72, // error_reason = "bar" }; MoqtSubscribeAnnouncesError subscribe_namespace_error_ = { - TrackNamespace("foo"), + /*request_id=*/1, /*error_code=*/RequestErrorCode::kUnauthorized, - /*reason_phrase=*/"bar", + /*error_reason=*/"bar", }; }; @@ -1309,8 +1430,8 @@ class QUICHE_NO_EXPORT FetchMessage : public TestMessageBase { } bool EqualFieldValues(MessageStructuredData& values) const override { auto cast = std::get(values); - if (cast.fetch_id != fetch_.fetch_id) { - QUIC_LOG(INFO) << "FETCH fetch_id mismatch"; + if (cast.request_id != fetch_.request_id) { + QUIC_LOG(INFO) << "FETCH request_id mismatch"; return false; } if (cast.subscriber_priority != fetch_.subscriber_priority) { @@ -1321,39 +1442,10 @@ class QUICHE_NO_EXPORT FetchMessage : public TestMessageBase { QUIC_LOG(INFO) << "FETCH group_order mismatch"; return false; } - if (cast.joining_fetch.has_value() != fetch_.joining_fetch.has_value()) { - QUIC_LOG(INFO) << "FETCH type mismatch"; + if (cast.fetch != fetch_.fetch) { + QUIC_LOG(INFO) << "FETCH mismatch"; return false; } - if (cast.joining_fetch.has_value()) { - if (cast.joining_fetch->joining_subscribe_id != - fetch_.joining_fetch->joining_subscribe_id) { - QUIC_LOG(INFO) << "FETCH joining_subscribe_id mismatch"; - return false; - } - if (cast.joining_fetch->preceding_group_offset != - fetch_.joining_fetch->preceding_group_offset) { - QUIC_LOG(INFO) << "FETCH preceding_group_offset mismatch"; - return false; - } - } else { - if (cast.full_track_name != fetch_.full_track_name) { - QUIC_LOG(INFO) << "FETCH full_track_name mismatch"; - return false; - } - if (cast.start_object != fetch_.start_object) { - QUIC_LOG(INFO) << "FETCH start_object mismatch"; - return false; - } - if (cast.end_group != fetch_.end_group) { - QUIC_LOG(INFO) << "FETCH end_group mismatch"; - return false; - } - if (cast.end_object != fetch_.end_object) { - QUIC_LOG(INFO) << "FETCH end_object mismatch"; - return false; - } - } if (cast.parameters != fetch_.parameters) { QUIC_LOG(INFO) << "FETCH parameters mismatch"; return false; @@ -1373,8 +1465,8 @@ class QUICHE_NO_EXPORT FetchMessage : public TestMessageBase { // Avoid varint nonsense. QUICHE_CHECK(group < 64); QUICHE_CHECK(!object.has_value() || *object < 64); - fetch_.end_group = group; - fetch_.end_object = object; + std::get(fetch_.fetch).end_group = group; + std::get(fetch_.fetch).end_object = object; raw_packet_[18] = group; raw_packet_[19] = object.has_value() ? (*object + 1) : 0; SetWireImage(raw_packet_, sizeof(raw_packet_)); @@ -1388,7 +1480,7 @@ class QUICHE_NO_EXPORT FetchMessage : public TestMessageBase { private: uint8_t raw_packet_[28] = { 0x16, 0x00, 0x19, - 0x01, // fetch_id = 1 + 0x01, // request_id = 1 0x02, // priority = kHigh 0x01, // group_order = kAscending 0x01, // type = kStandalone @@ -1396,33 +1488,35 @@ class QUICHE_NO_EXPORT FetchMessage : public TestMessageBase { 0x03, 0x62, 0x61, 0x72, // track_name = "bar" 0x01, 0x02, // start_object = 1, 2 0x05, 0x07, // end_object = 5, 6 - 0x01, 0x01, 0x05, 0x03, 0x00, 0x62, 0x61, 0x7a, // parameters = "baz" + 0x01, 0x03, 0x05, 0x03, 0x00, 0x62, 0x61, 0x7a, // parameters = "baz" }; MoqtFetch fetch_ = { - /*fetch_id =*/1, + /*request_id=*/1, /*subscriber_priority=*/2, /*group_order=*/MoqtDeliveryOrder::kAscending, - /*joining_fetch=*/std::optional(), - FullTrackName("foo", "bar"), - /*start_object=*/Location{1, 2}, - /*end_group=*/5, - /*end_object=*/6, + /*fetch =*/ + StandaloneFetch{ + FullTrackName("foo", "bar"), + /*start_object=*/Location{1, 2}, + /*end_group=*/5, + /*end_object=*/6, + }, VersionSpecificParameters(AuthTokenType::kOutOfBand, "baz"), }; }; // This is not used in the parameterized Parser and Framer tests, because it // does not have its own MoqtMessageType. -class QUICHE_NO_EXPORT JoiningFetchMessage : public TestMessageBase { +class QUICHE_NO_EXPORT RelativeJoiningFetchMessage : public TestMessageBase { public: - JoiningFetchMessage() : TestMessageBase() { + RelativeJoiningFetchMessage() : TestMessageBase() { SetWireImage(raw_packet_, sizeof(raw_packet_)); } bool EqualFieldValues(MessageStructuredData& values) const override { auto cast = std::get(values); - if (cast.fetch_id != fetch_.fetch_id) { - QUIC_LOG(INFO) << "FETCH fetch_id mismatch"; + if (cast.request_id != fetch_.request_id) { + QUIC_LOG(INFO) << "FETCH request_id mismatch"; return false; } if (cast.subscriber_priority != fetch_.subscriber_priority) { @@ -1433,39 +1527,10 @@ class QUICHE_NO_EXPORT JoiningFetchMessage : public TestMessageBase { QUIC_LOG(INFO) << "FETCH group_order mismatch"; return false; } - if (cast.joining_fetch.has_value() != fetch_.joining_fetch.has_value()) { - QUIC_LOG(INFO) << "FETCH type mismatch"; + if (cast.fetch != fetch_.fetch) { + QUIC_LOG(INFO) << "FETCH mismatch"; return false; } - if (cast.joining_fetch.has_value()) { - if (cast.joining_fetch->joining_subscribe_id != - fetch_.joining_fetch->joining_subscribe_id) { - QUIC_LOG(INFO) << "FETCH joining_subscribe_id mismatch"; - return false; - } - if (cast.joining_fetch->preceding_group_offset != - fetch_.joining_fetch->preceding_group_offset) { - QUIC_LOG(INFO) << "FETCH preceding_group_offset mismatch"; - return false; - } - } else { - if (cast.full_track_name != fetch_.full_track_name) { - QUIC_LOG(INFO) << "FETCH full_track_name mismatch"; - return false; - } - if (cast.start_object != fetch_.start_object) { - QUIC_LOG(INFO) << "FETCH start_object mismatch"; - return false; - } - if (cast.end_group != fetch_.end_group) { - QUIC_LOG(INFO) << "FETCH end_group mismatch"; - return false; - } - if (cast.end_object != fetch_.end_object) { - QUIC_LOG(INFO) << "FETCH end_object mismatch"; - return false; - } - } if (cast.parameters != fetch_.parameters) { QUIC_LOG(INFO) << "FETCH parameters mismatch"; return false; @@ -1489,28 +1554,187 @@ class QUICHE_NO_EXPORT JoiningFetchMessage : public TestMessageBase { private: uint8_t raw_packet_[17] = { 0x16, 0x00, 0x0e, - 0x01, // fetch_id = 1 + 0x01, // request_id = 1 0x02, // priority = kHigh 0x01, // group_order = kAscending - 0x02, // type = kJoining + 0x02, // type = kRelativeJoining 0x02, 0x02, // joining_subscribe_id = 2, 2 groups - 0x01, 0x01, 0x05, 0x03, 0x00, 0x62, 0x61, 0x7a, // parameters = "baz" + 0x01, 0x03, 0x05, 0x03, 0x00, 0x62, 0x61, 0x7a, // parameters = "baz" }; MoqtFetch fetch_ = { - /*fetch_id =*/1, + /*request_id =*/1, /*subscriber_priority=*/2, /*group_order=*/MoqtDeliveryOrder::kAscending, - /*joining_fetch=*/JoiningFetch{2, 2}, - /* the next four are ignored for joining fetches*/ - FullTrackName("foo", "bar"), - /*start_object=*/Location{1, 2}, - /*end_group=*/5, - /*end_object=*/6, + /*fetch=*/JoiningFetchRelative{2, 2}, VersionSpecificParameters(AuthTokenType::kOutOfBand, "baz"), }; }; +// This is not used in the parameterized Parser and Framer tests, because it +// does not have its own MoqtMessageType. +class QUICHE_NO_EXPORT AbsoluteJoiningFetchMessage : public TestMessageBase { + public: + AbsoluteJoiningFetchMessage() : TestMessageBase() { + SetWireImage(raw_packet_, sizeof(raw_packet_)); + } + bool EqualFieldValues(MessageStructuredData& values) const override { + auto cast = std::get(values); + if (cast.request_id != fetch_.request_id) { + QUIC_LOG(INFO) << "FETCH request_id mismatch"; + return false; + } + if (cast.subscriber_priority != fetch_.subscriber_priority) { + QUIC_LOG(INFO) << "FETCH subscriber_priority mismatch"; + return false; + } + if (cast.group_order != fetch_.group_order) { + QUIC_LOG(INFO) << "FETCH group_order mismatch"; + return false; + } + if (cast.fetch != fetch_.fetch) { + QUIC_LOG(INFO) << "FETCH mismatch"; + return false; + } + if (cast.parameters != fetch_.parameters) { + QUIC_LOG(INFO) << "FETCH parameters mismatch"; + return false; + } + return true; + } + + void ExpandVarints() override { + ExpandVarintsImpl("v--vvv---v---vvvvvv-----"); + } + + MessageStructuredData structured_data() const override { + return TestMessageBase::MessageStructuredData(fetch_); + } + + void SetGroupOrder(uint8_t group_order) { + raw_packet_[5] = static_cast(group_order); + SetWireImage(raw_packet_, sizeof(raw_packet_)); + } + + private: + uint8_t raw_packet_[17] = { + 0x16, 0x00, 0x0e, + 0x01, // request_id = 1 + 0x02, // priority = kHigh + 0x01, // group_order = kAscending + 0x03, // type = kAbsoluteJoining + 0x02, 0x02, // joining_subscribe_id = 2, group_id = 2 + 0x01, 0x03, 0x05, 0x03, 0x00, 0x62, 0x61, 0x7a, // parameters = "baz" + }; + + MoqtFetch fetch_ = { + /*request_id=*/1, + /*subscriber_priority=*/2, + /*group_order=*/MoqtDeliveryOrder::kAscending, + /*fetch=*/JoiningFetchAbsolute{2, 2}, + VersionSpecificParameters(AuthTokenType::kOutOfBand, "baz"), + }; +}; + +class QUICHE_NO_EXPORT FetchOkMessage : public TestMessageBase { + public: + FetchOkMessage() : TestMessageBase() { + SetWireImage(raw_packet_, sizeof(raw_packet_)); + } + bool EqualFieldValues(MessageStructuredData& values) const override { + auto cast = std::get(values); + if (cast.request_id != fetch_ok_.request_id) { + QUIC_LOG(INFO) << "FETCH_OK request_id mismatch"; + return false; + } + if (cast.group_order != fetch_ok_.group_order) { + QUIC_LOG(INFO) << "FETCH_OK group_order mismatch"; + return false; + } + if (cast.end_of_track != fetch_ok_.end_of_track) { + QUIC_LOG(INFO) << "FETCH_OK end_of_track mismatch"; + return false; + } + if (cast.end_location != fetch_ok_.end_location) { + QUIC_LOG(INFO) << "FETCH_OK end_location mismatch"; + return false; + } + if (cast.parameters != fetch_ok_.parameters) { + QUIC_LOG(INFO) << "FETCH_OK parameters mismatch"; + return false; + } + return true; + } + + void ExpandVarints() override { ExpandVarintsImpl("v--vvvvv---"); } + + MessageStructuredData structured_data() const override { + return TestMessageBase::MessageStructuredData(fetch_ok_); + } + + private: + uint8_t raw_packet_[12] = { + 0x18, 0x00, 0x09, + 0x01, // request_id = 1 + 0x01, // group_order = kAscending + 0x00, // end_of_track = false + 0x05, 0x04, // end_location = 5, 4 + 0x01, 0x04, 0x67, 0x10, // MaxCacheDuration = 10000 + }; + + MoqtFetchOk fetch_ok_ = { + /*request_id =*/1, + /*group_order=*/MoqtDeliveryOrder::kAscending, + /*end_of_track=*/false, + /*end_location=*/Location{5, 4}, + VersionSpecificParameters(quic::QuicTimeDelta::Infinite(), + quic::QuicTimeDelta::FromMilliseconds(10000)), + }; +}; + +class QUICHE_NO_EXPORT FetchErrorMessage : public TestMessageBase { + public: + FetchErrorMessage() : TestMessageBase() { + SetWireImage(raw_packet_, sizeof(raw_packet_)); + } + bool EqualFieldValues(MessageStructuredData& values) const override { + auto cast = std::get(values); + if (cast.request_id != fetch_error_.request_id) { + QUIC_LOG(INFO) << "FETCH_ERROR request_id mismatch"; + return false; + } + if (cast.error_code != fetch_error_.error_code) { + QUIC_LOG(INFO) << "FETCH_ERROR group_order mismatch"; + return false; + } + if (cast.error_reason != fetch_error_.error_reason) { + QUIC_LOG(INFO) << "FETCH_ERROR error_reason mismatch"; + return false; + } + return true; + } + + void ExpandVarints() override { ExpandVarintsImpl("vvv---"); } + + MessageStructuredData structured_data() const override { + return TestMessageBase::MessageStructuredData(fetch_error_); + } + + private: + uint8_t raw_packet_[9] = { + 0x19, 0x00, 0x06, + 0x01, // request_id = 1 + 0x01, // error_code = kUnauthorized + 0x03, 0x62, 0x61, 0x72, // error_reason = "bar" + }; + + MoqtFetchError fetch_error_ = { + /*request_id =*/1, + /*error_code=*/RequestErrorCode::kUnauthorized, + /*error_reason=*/"bar", + }; +}; + class QUICHE_NO_EXPORT FetchCancelMessage : public TestMessageBase { public: FetchCancelMessage() : TestMessageBase() { @@ -1518,7 +1742,7 @@ class QUICHE_NO_EXPORT FetchCancelMessage : public TestMessageBase { } bool EqualFieldValues(MessageStructuredData& values) const override { auto cast = std::get(values); - if (cast.subscribe_id != fetch_cancel_.subscribe_id) { + if (cast.request_id != fetch_cancel_.request_id) { QUIC_LOG(INFO) << "FETCH_CANCEL subscribe_id mismatch"; return false; } @@ -1534,104 +1758,11 @@ class QUICHE_NO_EXPORT FetchCancelMessage : public TestMessageBase { private: uint8_t raw_packet_[4] = { 0x17, 0x00, 0x01, - 0x01, // subscribe_id = 1 + 0x01, // request_id = 1 }; MoqtFetchCancel fetch_cancel_ = { - /*subscribe_id =*/1, - }; -}; - -class QUICHE_NO_EXPORT FetchOkMessage : public TestMessageBase { - public: - FetchOkMessage() : TestMessageBase() { - SetWireImage(raw_packet_, sizeof(raw_packet_)); - } - bool EqualFieldValues(MessageStructuredData& values) const override { - auto cast = std::get(values); - if (cast.subscribe_id != fetch_ok_.subscribe_id) { - QUIC_LOG(INFO) << "FETCH_OK subscribe_id mismatch"; - return false; - } - if (cast.group_order != fetch_ok_.group_order) { - QUIC_LOG(INFO) << "FETCH_OK group_order mismatch"; - return false; - } - if (cast.largest_id != fetch_ok_.largest_id) { - QUIC_LOG(INFO) << "FETCH_OK start_object mismatch"; - return false; - } - if (cast.parameters != fetch_ok_.parameters) { - QUIC_LOG(INFO) << "FETCH_OK parameters mismatch"; - return false; - } - return true; - } - - void ExpandVarints() override { ExpandVarintsImpl("v-vvvvv---"); } - - MessageStructuredData structured_data() const override { - return TestMessageBase::MessageStructuredData(fetch_ok_); - } - - private: - uint8_t raw_packet_[11] = { - 0x18, 0x00, 0x08, - 0x01, // subscribe_id = 1 - 0x01, // group_order = kAscending - 0x05, 0x04, // largest_object = 5, 4 - 0x01, 0x04, 0x67, 0x10, // MaxCacheDuration = 10000 - }; - - MoqtFetchOk fetch_ok_ = { - /*subscribe_id =*/1, - /*group_order=*/MoqtDeliveryOrder::kAscending, - /*start_object=*/Location{5, 4}, - VersionSpecificParameters(quic::QuicTimeDelta::Infinite(), - quic::QuicTimeDelta::FromMilliseconds(10000)), - }; -}; - -class QUICHE_NO_EXPORT FetchErrorMessage : public TestMessageBase { - public: - FetchErrorMessage() : TestMessageBase() { - SetWireImage(raw_packet_, sizeof(raw_packet_)); - } - bool EqualFieldValues(MessageStructuredData& values) const override { - auto cast = std::get(values); - if (cast.subscribe_id != fetch_error_.subscribe_id) { - QUIC_LOG(INFO) << "FETCH_ERROR subscribe_id mismatch"; - return false; - } - if (cast.error_code != fetch_error_.error_code) { - QUIC_LOG(INFO) << "FETCH_ERROR group_order mismatch"; - return false; - } - if (cast.reason_phrase != fetch_error_.reason_phrase) { - QUIC_LOG(INFO) << "FETCH_ERROR reason_phrase mismatch"; - return false; - } - return true; - } - - void ExpandVarints() override { ExpandVarintsImpl("vvv---"); } - - MessageStructuredData structured_data() const override { - return TestMessageBase::MessageStructuredData(fetch_error_); - } - - private: - uint8_t raw_packet_[9] = { - 0x19, 0x00, 0x06, - 0x01, // subscribe_id = 1 - 0x01, // error_code = kUnauthorized - 0x03, 0x62, 0x61, 0x72, // reason_phrase = "bar" - }; - - MoqtFetchError fetch_error_ = { - /*subscribe_id =*/1, - /*error_code=*/RequestErrorCode::kUnauthorized, - /*reason_phrase=*/"bar", + /*request_id =*/1, }; }; @@ -1666,6 +1797,191 @@ class QUICHE_NO_EXPORT RequestsBlockedMessage : public TestMessageBase { }; }; +class QUICHE_NO_EXPORT PublishMessage : public TestMessageBase { + public: + PublishMessage() : TestMessageBase() { + SetWireImage(raw_packet_, sizeof(raw_packet_)); + } + bool EqualFieldValues(MessageStructuredData& values) const override { + auto cast = std::get(values); + if (cast.request_id != publish_.request_id) { + QUIC_LOG(INFO) << "PUBLISH request_id mismatch"; + return false; + } + if (cast.full_track_name != publish_.full_track_name) { + QUIC_LOG(INFO) << "PUBLISH full_track_name mismatch"; + return false; + } + if (cast.track_alias != publish_.track_alias) { + QUIC_LOG(INFO) << "PUBLISH track_alias mismatch"; + return false; + } + if (cast.group_order != publish_.group_order) { + QUIC_LOG(INFO) << "PUBLISH group_order mismatch"; + return false; + } + if (cast.largest_location != publish_.largest_location) { + QUIC_LOG(INFO) << "PUBLISH largest_location mismatch"; + return false; + } + if (cast.forward != publish_.forward) { + QUIC_LOG(INFO) << "PUBLISH forward mismatch"; + return false; + } + if (cast.parameters != publish_.parameters) { + QUIC_LOG(INFO) << "PUBLISH parameters mismatch"; + return false; + } + return true; + } + + void ExpandVarints() override { + ExpandVarintsImpl("vvv---v---v--vv-vvv-----"); + } + + MessageStructuredData structured_data() const override { + return TestMessageBase::MessageStructuredData(publish_); + } + + private: + uint8_t raw_packet_[27] = { + 0x1d, 0x00, 0x18, + 0x01, // request_id = 1 + 0x01, 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" + 0x03, 0x62, 0x61, 0x72, // track_name = "bar" + 0x04, // track_alias = 4 + 0x01, // group_order = kAscending + 0x01, 0x0a, 0x01, // content exists, largest_location = 10, 1 + 0x01, // forward = true + 0x01, 0x03, 0x05, 0x03, 0x00, 0x62, 0x61, 0x7a, // parameters = "baz" + }; + + MoqtPublish publish_ = { + /*request_id=*/1, + FullTrackName("foo", "bar"), + /*track_alias=*/4, + MoqtDeliveryOrder::kAscending, + /*largest_location=*/Location(10, 1), + /*forward=*/true, + VersionSpecificParameters(AuthTokenType::kOutOfBand, "baz"), + }; +}; + +class QUICHE_NO_EXPORT PublishOkMessage : public TestMessageBase { + public: + PublishOkMessage() : TestMessageBase() { + SetWireImage(raw_packet_, sizeof(raw_packet_)); + } + bool EqualFieldValues(MessageStructuredData& values) const override { + auto cast = std::get(values); + if (cast.request_id != publish_ok_.request_id) { + QUIC_LOG(INFO) << "PUBLISH_OK request_id mismatch"; + return false; + } + if (cast.forward != publish_ok_.forward) { + QUIC_LOG(INFO) << "PUBLISH_OK forward mismatch"; + return false; + } + if (cast.subscriber_priority != publish_ok_.subscriber_priority) { + QUIC_LOG(INFO) << "PUBLISH_OK subscriber_priority mismatch"; + return false; + } + if (cast.group_order != publish_ok_.group_order) { + QUIC_LOG(INFO) << "PUBLISH_OK group_order mismatch"; + return false; + } + if (cast.filter_type != publish_ok_.filter_type) { + QUIC_LOG(INFO) << "PUBLISH_OK filter_type mismatch"; + return false; + } + if (cast.start != publish_ok_.start) { + QUIC_LOG(INFO) << "PUBLISH_OK start mismatch"; + return false; + } + if (cast.end_group != publish_ok_.end_group) { + QUIC_LOG(INFO) << "PUBLISH_OK end_group mismatch"; + return false; + } + if (cast.parameters != publish_ok_.parameters) { + QUIC_LOG(INFO) << "PUBLISH_OK parameters mismatch"; + return false; + } + return true; + } + + void ExpandVarints() override { ExpandVarintsImpl("v---vvvvvv--"); } + + MessageStructuredData structured_data() const override { + return TestMessageBase::MessageStructuredData(publish_ok_); + } + + private: + uint8_t raw_packet_[15] = { + 0x1e, 0x00, 0x0c, + 0x01, // request_id = 1 + 0x01, // forward = true + 0x02, // subscriber_priority = 2 + 0x01, // group_order = kAscending + 0x04, // filter_type = kAbsoluteRange + 0x05, 0x04, // start = 5, 4 + 0x06, // end_group = 6 + 0x01, 0x02, 0x67, 0x10, // delivery_timeout = 10000 ms + }; + MoqtPublishOk publish_ok_ = { + /*request_id=*/1, + /*forward=*/true, + /*subscriber_priority=*/2, + MoqtDeliveryOrder::kAscending, + MoqtFilterType::kAbsoluteRange, + /*start=*/Location(5, 4), + /*end_group=*/6, + VersionSpecificParameters(quic::QuicTimeDelta::FromMilliseconds(10000), + quic::QuicTimeDelta::Infinite()), + }; +}; + +class QUICHE_NO_EXPORT PublishErrorMessage : public TestMessageBase { + public: + PublishErrorMessage() : TestMessageBase() { + SetWireImage(raw_packet_, sizeof(raw_packet_)); + } + bool EqualFieldValues(MessageStructuredData& values) const override { + auto cast = std::get(values); + if (cast.request_id != publish_error_.request_id) { + QUIC_LOG(INFO) << "PUBLISH_ERROR request_id mismatch"; + return false; + } + if (cast.error_code != publish_error_.error_code) { + QUIC_LOG(INFO) << "PUBLISH_ERROR error_code mismatch"; + return false; + } + if (cast.error_reason != publish_error_.error_reason) { + QUIC_LOG(INFO) << "PUBLISH_ERROR error_reason mismatch"; + return false; + } + return true; + } + + void ExpandVarints() override { ExpandVarintsImpl("vvv---"); } + + MessageStructuredData structured_data() const override { + return TestMessageBase::MessageStructuredData(publish_error_); + } + + private: + uint8_t raw_packet_[9] = { + 0x1f, 0x00, 0x06, + 0x01, // request_id = 1 + 0x01, // error_code = kUnauthorized + 0x03, 0x62, 0x61, 0x72, // error_reason = "bar" + }; + MoqtPublishError publish_error_ = { + /*request_id=*/1, + /*error_code=*/RequestErrorCode::kUnauthorized, + /*error_reason=*/"bar", + }; +}; + class QUICHE_NO_EXPORT ObjectAckMessage : public TestMessageBase { public: ObjectAckMessage() : TestMessageBase() { @@ -1766,6 +2082,12 @@ static inline std::unique_ptr CreateTestMessage( return std::make_unique(); case MoqtMessageType::kRequestsBlocked: return std::make_unique(); + case MoqtMessageType::kPublish: + return std::make_unique(); + case MoqtMessageType::kPublishOk: + return std::make_unique(); + case MoqtMessageType::kPublishError: + return std::make_unique(); case MoqtMessageType::kObjectAck: return std::make_unique(); case MoqtMessageType::kClientSetup: @@ -1779,15 +2101,18 @@ static inline std::unique_ptr CreateTestMessage( static inline std::unique_ptr CreateTestDataStream( MoqtDataStreamType type) { - switch (type) { - case MoqtDataStreamType::kStreamHeaderSubgroup: - return std::make_unique(); - case MoqtDataStreamType::kStreamHeaderFetch: - return std::make_unique(); - case MoqtDataStreamType::kPadding: - return nullptr; + if (type.IsPadding()) { + return nullptr; } - return nullptr; + if (type.IsFetch()) { + return std::make_unique(); + } + return std::make_unique(type); +} + +static inline std::unique_ptr CreateTestDatagram( + MoqtDatagramType type) { + return std::make_unique(type); } } // namespace moqt::test diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_client.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_client.cc index f22ffda8ee..26525da204 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_client.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_client.cc @@ -25,6 +25,7 @@ #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_publisher.h" #include "quiche/quic/moqt/moqt_session.h" #include "quiche/quic/moqt/tools/moq_chat.h" #include "quiche/quic/moqt/tools/moqt_client.h" @@ -185,9 +186,9 @@ void ChatClient::RemoteTrackVisitor::OnReply( } void ChatClient::RemoteTrackVisitor::OnObjectFragment( - const FullTrackName& full_track_name, Location /*sequence*/, - MoqtPriority /*publisher_priority*/, MoqtObjectStatus /*status*/, - absl::string_view object, bool end_of_message) { + const FullTrackName& full_track_name, + const PublishedObjectMetadata& /*metadata*/, absl::string_view object, + bool end_of_message) { if (!end_of_message) { std::cerr << "Error: received partial message despite requesting " "buffering\n"; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_client.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_client.h index 93d4ae5e11..bf15fa781c 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_client.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_client.h @@ -17,6 +17,7 @@ #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_publisher.h" #include "quiche/quic/moqt/moqt_session.h" #include "quiche/quic/moqt/moqt_track.h" #include "quiche/quic/moqt/tools/moqt_client.h" @@ -98,13 +99,14 @@ class ChatClient { void OnCanAckObjects(MoqtObjectAckFunction) override {} void OnObjectFragment(const moqt::FullTrackName& full_track_name, - Location sequence, - moqt::MoqtPriority publisher_priority, - moqt::MoqtObjectStatus status, + const PublishedObjectMetadata& metadata, absl::string_view object, bool end_of_message) override; - void OnSubscribeDone(FullTrackName full_track_name) override {} + void OnSubscribeDone(FullTrackName /*full_track_name*/) override {} + + // TODO(martinduke): Implement this. + void OnMalformedTrack(const FullTrackName& /*full_track_name*/) override {} private: ChatClient* client_; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_server.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_server.cc index c3d9b7486a..268c912fb0 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_server.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_server.cc @@ -18,6 +18,7 @@ #include "quiche/quic/moqt/moqt_live_relay_queue.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/tools/moq_chat.h" #include "quiche/quic/moqt/tools/moqt_server.h" @@ -149,9 +150,9 @@ void ChatServer::RemoteTrackVisitor::OnReply( } void ChatServer::RemoteTrackVisitor::OnObjectFragment( - const moqt::FullTrackName& full_track_name, moqt::Location sequence, - moqt::MoqtPriority /*publisher_priority*/, moqt::MoqtObjectStatus status, - absl::string_view object, bool end_of_message) { + const moqt::FullTrackName& full_track_name, + const PublishedObjectMetadata& metadata, absl::string_view object, + bool end_of_message) { if (!end_of_message) { std::cerr << "Error: received partial message despite requesting " "buffering\n"; @@ -162,14 +163,14 @@ void ChatServer::RemoteTrackVisitor::OnObjectFragment( << full_track_name.ToString() << "\n"; return; } - if (status != MoqtObjectStatus::kNormal) { - it->second->AddObject(sequence, status); + if (metadata.status != MoqtObjectStatus::kNormal) { + it->second->AddObject(metadata, "", /*fin=*/false); return; } if (!server_->WriteToFile(GetUsername(full_track_name), object)) { std::cout << GetUsername(full_track_name) << ": " << object << "\n\n"; } - it->second->AddObject(sequence, object); + it->second->AddObject(metadata, object, /*fin=*/false); } ChatServer::ChatServer(std::unique_ptr proof_source, diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_server.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_server.h index 90e83e9c08..352b2ebf28 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_server.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_server.h @@ -43,12 +43,12 @@ class ChatServer { std::optional reason_phrase) override; void OnCanAckObjects(MoqtObjectAckFunction) override {} void OnObjectFragment(const moqt::FullTrackName& full_track_name, - Location sequence, - moqt::MoqtPriority /*publisher_priority*/, - moqt::MoqtObjectStatus /*status*/, + const PublishedObjectMetadata& metadata, absl::string_view object, bool end_of_message) override; void OnSubscribeDone(FullTrackName /*full_track_name*/) override {} + // TODO(martinduke): Implement this. + void OnMalformedTrack(const FullTrackName& full_track_name) override {} private: ChatServer* server_; 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 acc64a05e2..416f13328c 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 @@ -30,6 +30,7 @@ #include "absl/time/time.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_track.h" #include "quiche/quic/moqt/tools/moqt_server.h" @@ -154,8 +155,8 @@ class MoqtIngestionHandler { absl::StrSplit(track_list, ',', absl::AllowEmpty()); for (absl::string_view track : tracks_to_subscribe) { FullTrackName full_track_name(track_namespace, track); - session_->JoiningFetch(full_track_name, &it->second, 0, - VersionSpecificParameters()); + session_->RelativeJoiningFetch(full_track_name, &it->second, 0, + VersionSpecificParameters()); } return std::nullopt; @@ -180,13 +181,12 @@ class MoqtIngestionHandler { void OnCanAckObjects(MoqtObjectAckFunction) override {} void OnObjectFragment(const FullTrackName& full_track_name, - Location sequence, - MoqtPriority /*publisher_priority*/, - MoqtObjectStatus /*status*/, absl::string_view object, + const PublishedObjectMetadata& metadata, + absl::string_view object, bool /*end_of_message*/) override { std::string file_name = - absl::StrCat(sequence.group, "-", sequence.object, ".", - full_track_name.track_namespace().tuple().back()); + absl::StrCat(metadata.location.group, "-", metadata.location.object, + ".", full_track_name.track_namespace().tuple().back()); std::string file_path = quiche::JoinPath(directory_, file_name); std::ofstream output(file_path, std::ios::binary | std::ios::ate); output.write(object.data(), object.size()); @@ -194,6 +194,7 @@ class MoqtIngestionHandler { } void OnSubscribeDone(FullTrackName /*full_track_name*/) override {} + void OnMalformedTrack(const FullTrackName& /*full_track_name*/) override {} private: std::string directory_; 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 d45c99a423..ab2943c0d3 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 @@ -10,7 +10,6 @@ #include #include #include -#include #include "absl/status/status.h" #include "absl/status/statusor.h" @@ -65,9 +64,7 @@ class MockTrackPublisher : public MoqtTrackPublisher { const FullTrackName& GetTrackName() const override { return track_name_; } MOCK_METHOD(std::optional, GetCachedObject, - (Location sequence), (const, override)); - MOCK_METHOD(std::vector, GetCachedObjectsInRange, - (Location start, Location end), (const, override)); + (uint64_t, uint64_t, uint64_t), (const, override)); MOCK_METHOD(void, AddObjectListener, (MoqtObjectListener * listener), (override)); MOCK_METHOD(void, RemoveObjectListener, (MoqtObjectListener * listener), @@ -97,17 +94,20 @@ class MockSubscribeRemoteTrackVisitor : public SubscribeRemoteTrack::Visitor { MOCK_METHOD(void, OnCanAckObjects, (MoqtObjectAckFunction ack_function), (override)); MOCK_METHOD(void, OnObjectFragment, - (const FullTrackName& full_track_name, Location sequence, - MoqtPriority publisher_priority, MoqtObjectStatus status, + (const FullTrackName& full_track_name, + const PublishedObjectMetadata& metadata, absl::string_view object, bool end_of_message), (override)); MOCK_METHOD(void, OnSubscribeDone, (FullTrackName full_track_name), (override)); + MOCK_METHOD(void, OnMalformedTrack, (const FullTrackName& full_track_name), + (override)); }; class MockPublishingMonitorInterface : public MoqtPublishingMonitorInterface { public: - MOCK_METHOD(void, OnObjectAckSupportKnown, (bool supported), (override)); + MOCK_METHOD(void, OnObjectAckSupportKnown, + (std::optional time_window), (override)); MOCK_METHOD(void, OnObjectAckReceived, (uint64_t group_id, uint64_t object_id, quic::QuicTimeDelta delta_from_deadline), 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 index 3da0a9d101..9fbaeb9c1b 100644 --- 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 @@ -37,6 +37,7 @@ #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_publisher.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" @@ -259,10 +260,15 @@ class ObjectGenerator : public quic::simulator::Actor, } quic::QuicBandwidth GetCurrentBitrate() const override { return bitrate_; } - bool AdjustBitrate(quic::QuicBandwidth bandwidth) override { + bool CouldUseExtraBandwidth() override { return true; } + void ConsiderAdjustingBitrate(quic::QuicBandwidth bandwidth, + BitrateAdjustmentType type) override { + if (moqt::ShouldIgnoreBitrateAdjustment(bandwidth, type, bitrate_, + /*min_change=*/0.01)) { + return; + } bitrate_ = bandwidth; bitrate_history_.push_back(bandwidth); - return true; } std::string FormatBitrateHistory() const { std::vector bits; @@ -299,12 +305,12 @@ class ObjectReceiver : public SubscribeRemoteTrack::Visitor { object_ack_function_ = std::move(ack_function); } - void OnObjectFragment(const FullTrackName& full_track_name, Location sequence, - MoqtPriority /*publisher_priority*/, - MoqtObjectStatus status, absl::string_view object, + void OnObjectFragment(const FullTrackName& full_track_name, + const PublishedObjectMetadata& metadata, + absl::string_view object, bool end_of_message) override { QUICHE_DCHECK(full_track_name == TrackName()); - if (status != MoqtObjectStatus::kNormal) { + if (metadata.status != MoqtObjectStatus::kNormal) { QUICHE_DCHECK(end_of_message); return; } @@ -312,10 +318,11 @@ class ObjectReceiver : public SubscribeRemoteTrack::Visitor { QUICHE_LOG(DFATAL) << "Partial receiving of objects wasn't enabled"; return; } - OnFullObject(sequence, object); + OnFullObject(metadata.location, object); } void OnSubscribeDone(FullTrackName /*full_track_name*/) override {} + void OnMalformedTrack(const FullTrackName& /*full_track_name*/) override {} void OnFullObject(Location sequence, absl::string_view payload) { QUICHE_CHECK_GE(payload.size(), 8u); @@ -443,11 +450,14 @@ class MoqtSimulator { // some catching up to do. generator_.Start(); VersionSpecificParameters subscription_parameters; + if (parameters_.bitrate_adaptation) { + subscription_parameters.oack_window_size = parameters_.deadline; + } if (!parameters_.delivery_timeout.IsInfinite()) { subscription_parameters.delivery_timeout = parameters_.delivery_timeout; } - server_session()->JoiningFetch(TrackName(), &receiver_, 0, - subscription_parameters); + server_session()->RelativeJoiningFetch(TrackName(), &receiver_, 0, + subscription_parameters); simulator_.RunFor(parameters_.duration); // At the end, we wait for eight RTTs until the connection settles down. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/platform/api/quic_test.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/platform/api/quic_test.h index 0d1d2b0b16..d5a27a16cd 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/platform/api/quic_test.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/platform/api/quic_test.h @@ -5,8 +5,8 @@ #ifndef QUICHE_QUIC_PLATFORM_API_QUIC_TEST_H_ #define QUICHE_QUIC_PLATFORM_API_QUIC_TEST_H_ -#include "quiche/quic/platform/api/quic_logging.h" -#include "quiche/common/platform/api/quiche_test.h" +#include "quiche/quic/platform/api/quic_logging.h" // IWYU pragma: export +#include "quiche/common/platform/api/quiche_test.h" // IWYU pragma: export namespace quic::test { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.cc index 001e690e28..c0d713a42e 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.cc @@ -607,5 +607,12 @@ bool QuicConnectionPeer::CanReceiveAckFrequencyFrames( return connection->can_receive_ack_frequency_immediate_ack_; } +// static +uint8_t QuicConnectionPeer::GetNumPtosForRetransmittableOnWireTimeout( + const QuicConnection* connection) { + return connection->ping_manager_ + .num_ptos_for_retransmittable_on_wire_timeout_; +} + } // namespace test } // namespace quic diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.h index 06d8c97586..c1477a8cf1 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.h @@ -253,6 +253,9 @@ class QuicConnectionPeer { static void OnForwardProgressMade(QuicConnection* connection); static bool CanReceiveAckFrequencyFrames(QuicConnection* connection); + + static uint8_t GetNumPtosForRetransmittableOnWireTimeout( + const QuicConnection* connection); }; } // namespace test 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 b3e8790a71..2bc5c12067 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 @@ -223,7 +223,7 @@ QuicAckFrame MakeAckFrameWithGaps(uint64_t gap_size, size_t max_num_gaps, uint64_t largest_acked); // Returns the encryption level that corresponds to the header type in -// |header|. If the header is for GOOGLE_QUIC_PACKET instead of an +// |header|. If the header is for GOOGLE_QUIC_Q043_PACKET instead of an // IETF-invariants packet, this function returns ENCRYPTION_INITIAL. EncryptionLevel HeaderToEncryptionLevel(const QuicPacketHeader& header); @@ -973,11 +973,8 @@ class MockQuicSpdySession : public QuicSpdySession { (override)); MOCK_METHOD(QuicSpdyStream*, CreateOutgoingBidirectionalStream, (), (override)); - MOCK_METHOD(QuicSpdyStream*, CreateOutgoingUnidirectionalStream, (), - (override)); MOCK_METHOD(bool, ShouldCreateIncomingStream, (QuicStreamId id), (override)); MOCK_METHOD(bool, ShouldCreateOutgoingBidirectionalStream, (), (override)); - MOCK_METHOD(bool, ShouldCreateOutgoingUnidirectionalStream, (), (override)); MOCK_METHOD(QuicConsumedData, WritevData, (QuicStreamId id, size_t write_length, QuicStreamOffset offset, StreamSendingState state, TransmissionType type, @@ -1049,7 +1046,7 @@ class MockHttp3DebugVisitor : public Http3DebugVisitor { (override)); MOCK_METHOD(void, OnHeadersFrameReceived, (QuicStreamId, QuicByteCount), (override)); - MOCK_METHOD(void, OnHeadersDecoded, (QuicStreamId, QuicHeaderList), + MOCK_METHOD(void, OnHeadersDecoded, (QuicStreamId, const QuicHeaderList&), (override)); MOCK_METHOD(void, OnUnknownFrameReceived, (QuicStreamId, uint64_t, QuicByteCount), (override)); @@ -1084,8 +1081,6 @@ class TestQuicSpdyServerSession : public QuicServerSessionBase { (override)); MOCK_METHOD(QuicSpdyStream*, CreateOutgoingBidirectionalStream, (), (override)); - MOCK_METHOD(QuicSpdyStream*, CreateOutgoingUnidirectionalStream, (), - (override)); MOCK_METHOD(std::vector::const_iterator, SelectAlpn, (const std::vector&), (const, override)); MOCK_METHOD(void, OnAlpnSelected, (absl::string_view), (override)); @@ -1151,11 +1146,8 @@ class TestQuicSpdyClientSession : public QuicSpdyClientSessionBase { (override)); MOCK_METHOD(QuicSpdyStream*, CreateOutgoingBidirectionalStream, (), (override)); - MOCK_METHOD(QuicSpdyStream*, CreateOutgoingUnidirectionalStream, (), - (override)); MOCK_METHOD(bool, ShouldCreateIncomingStream, (QuicStreamId id), (override)); MOCK_METHOD(bool, ShouldCreateOutgoingBidirectionalStream, (), (override)); - MOCK_METHOD(bool, ShouldCreateOutgoingUnidirectionalStream, (), (override)); MOCK_METHOD(std::vector, GetAlpnsToOffer, (), (const, override)); MOCK_METHOD(void, OnAlpnSelected, (absl::string_view), (override)); MOCK_METHOD(void, OnConfigNegotiated, (), (override)); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_session.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_session.cc index 3c44348736..6c74d900f2 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_session.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_session.cc @@ -95,19 +95,6 @@ QuicSpdyStream* QuicSimpleServerSession::CreateOutgoingBidirectionalStream() { return stream; } -QuicSimpleServerStream* -QuicSimpleServerSession::CreateOutgoingUnidirectionalStream() { - if (!ShouldCreateOutgoingUnidirectionalStream()) { - return nullptr; - } - - QuicSimpleServerStream* stream = new QuicSimpleServerStream( - GetNextOutgoingUnidirectionalStreamId(), this, WRITE_UNIDIRECTIONAL, - quic_simple_server_backend_); - ActivateStream(absl::WrapUnique(stream)); - return stream; -} - QuicStream* QuicSimpleServerSession::ProcessBidirectionalPendingStream( PendingStream* pending) { QUICHE_DCHECK(IsEncryptionEstablished()); 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 476f074669..69f3d0e5d1 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 @@ -55,7 +55,6 @@ class QuicSimpleServerSession : public QuicServerSessionBase { QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override; QuicSpdyStream* CreateIncomingStream(PendingStream* pending) override; QuicSpdyStream* CreateOutgoingBidirectionalStream() override; - QuicSimpleServerStream* CreateOutgoingUnidirectionalStream() override; // QuicServerSessionBaseMethod: std::unique_ptr CreateQuicCryptoServerStream( diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/web_transport_test_visitors.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/web_transport_test_visitors.h index 685a892605..e33eedd5af 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/web_transport_test_visitors.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/web_transport_test_visitors.h @@ -22,7 +22,8 @@ namespace quic { // Discards any incoming data. class WebTransportDiscardVisitor : public WebTransportStreamVisitor { public: - WebTransportDiscardVisitor(WebTransportStream* stream) : stream_(stream) {} + WebTransportDiscardVisitor(WebTransportStream* stream, bool bidi) + : stream_(stream), bidi_(bidi) {} void OnCanRead() override { std::string buffer; @@ -30,6 +31,10 @@ class WebTransportDiscardVisitor : public WebTransportStreamVisitor { QUIC_DVLOG(2) << "Read " << result.bytes_read << " bytes from WebTransport stream " << stream_->GetStreamId() << ", fin: " << result.fin; + if (bidi_ && result.fin) { + absl::Status status = quiche::SendFinOnStream(*stream_); + QUICHE_DCHECK(status.ok()) << status; + } } void OnCanWrite() override {} @@ -40,6 +45,7 @@ class WebTransportDiscardVisitor : public WebTransportStreamVisitor { private: WebTransportStream* stream_; + bool bidi_; }; class DiscardWebTransportSessionVisitor : public WebTransportVisitor { @@ -58,7 +64,8 @@ class DiscardWebTransportSessionVisitor : public WebTransportVisitor { if (stream == nullptr) { return; } - stream->SetVisitor(std::make_unique(stream)); + stream->SetVisitor( + std::make_unique(stream, /*bidi=*/true)); stream->visitor()->OnCanRead(); } } @@ -70,7 +77,8 @@ class DiscardWebTransportSessionVisitor : public WebTransportVisitor { if (stream == nullptr) { return; } - stream->SetVisitor(std::make_unique(stream)); + stream->SetVisitor( + std::make_unique(stream, /*bidi=*/false)); stream->visitor()->OnCanRead(); } } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/web_transport/encapsulated/encapsulated_web_transport.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/web_transport/encapsulated/encapsulated_web_transport.cc index 7371945cb9..5a00803dda 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/web_transport/encapsulated/encapsulated_web_transport.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/web_transport/encapsulated/encapsulated_web_transport.cc @@ -34,6 +34,7 @@ #include "quiche/common/quiche_buffer_allocator.h" #include "quiche/common/quiche_callbacks.h" #include "quiche/common/quiche_circular_deque.h" +#include "quiche/common/quiche_mem_slice.h" #include "quiche/common/quiche_status_utils.h" #include "quiche/common/quiche_stream.h" #include "quiche/common/vectorized_io_utils.h" @@ -257,9 +258,10 @@ DatagramStatus EncapsulatedSession::SendOrQueueDatagram( // allows us to avoid a copy. quiche::QuicheBuffer buffer = quiche::SerializeDatagramCapsuleHeader(datagram.size(), allocator_); - std::array spans = {buffer.AsStringView(), datagram}; + std::array spans = {quiche::QuicheMemSlice(std::move(buffer)), + quiche::QuicheMemSlice::Copy(datagram)}; absl::Status write_status = - writer_->Writev(absl::MakeConstSpan(spans), quiche::StreamWriteOptions()); + writer_->Writev(absl::MakeSpan(spans), quiche::StreamWriteOptions()); if (!write_status.ok()) { OnWriteError(write_status); return DatagramStatus{ @@ -611,8 +613,15 @@ bool EncapsulatedSession::InnerStream::SkipBytes(size_t bytes) { } absl::Status EncapsulatedSession::InnerStream::Writev( - const absl::Span data, + const absl::Span data, const quiche::StreamWriteOptions& options) { + // TODO: support zero copy. + std::vector views; + views.reserve(data.size()); + for (const quiche::QuicheMemSlice& slice : data) { + views.push_back(slice.AsStringView()); + } + if (write_side_closed_) { return absl::FailedPreconditionError( "Trying to write into an already-closed stream"); @@ -636,7 +645,7 @@ absl::Status EncapsulatedSession::InnerStream::Writev( !pending_write_.empty(); if (write_blocked) { fin_buffered_ = options.send_fin(); - for (absl::string_view chunk : data) { + for (absl::string_view chunk : views) { absl::StrAppend(&pending_write_, chunk); } absl::Status status = session_->scheduler_.Schedule(id_); @@ -648,12 +657,12 @@ absl::Status EncapsulatedSession::InnerStream::Writev( return absl::OkStatus(); } - size_t bytes_written = WriteInner(data, options.send_fin()); + size_t bytes_written = WriteInner(views, options.send_fin()); // TODO: handle partial writes when flow control requires those. QUICHE_DCHECK(bytes_written == 0 || - bytes_written == quiche::TotalStringViewSpanSize(data)); + bytes_written == quiche::TotalStringViewSpanSize(views)); if (bytes_written == 0) { - for (absl::string_view chunk : data) { + for (absl::string_view chunk : views) { absl::StrAppend(&pending_write_, chunk); } } @@ -700,12 +709,15 @@ size_t EncapsulatedSession::InnerStream::WriteInner( quiche::QuicheBuffer header = quiche::SerializeWebTransportStreamCapsuleHeader(id_, fin, total_size, session_->allocator_); - std::vector views_to_write; + std::vector views_to_write; views_to_write.reserve(data.size() + 1); - views_to_write.push_back(header.AsStringView()); - absl::c_copy(data, std::back_inserter(views_to_write)); + views_to_write.push_back(quiche::QuicheMemSlice(std::move(header))); + for (absl::string_view view : data) { + // TODO: support zero copy. + views_to_write.push_back(quiche::QuicheMemSlice::Copy(view)); + } absl::Status write_status = session_->writer_->Writev( - views_to_write, quiche::kDefaultStreamWriteOptions); + absl::MakeSpan(views_to_write), quiche::kDefaultStreamWriteOptions); if (!write_status.ok()) { session_->OnWriteError(write_status); return 0; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/web_transport/encapsulated/encapsulated_web_transport.h b/naiveproxy/src/net/third_party/quiche/src/quiche/web_transport/encapsulated/encapsulated_web_transport.h index e4e7f7ae9a..44f489a51b 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/web_transport/encapsulated/encapsulated_web_transport.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/web_transport/encapsulated/encapsulated_web_transport.h @@ -25,6 +25,7 @@ #include "quiche/common/quiche_buffer_allocator.h" #include "quiche/common/quiche_callbacks.h" #include "quiche/common/quiche_circular_deque.h" +#include "quiche/common/quiche_mem_slice.h" #include "quiche/common/quiche_stream.h" #include "quiche/common/simple_buffer_allocator.h" #include "quiche/web_transport/web_transport.h" @@ -145,7 +146,7 @@ class QUICHE_EXPORT EncapsulatedSession bool SkipBytes(size_t bytes) override; // WriteStream implementation. - absl::Status Writev(absl::Span data, + absl::Status Writev(absl::Span data, const quiche::StreamWriteOptions& options) override; bool CanWrite() const override; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/web_transport/test_tools/in_memory_stream.h b/naiveproxy/src/net/third_party/quiche/src/quiche/web_transport/test_tools/in_memory_stream.h index 48da99a4a5..078ca948d3 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/web_transport/test_tools/in_memory_stream.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/web_transport/test_tools/in_memory_stream.h @@ -15,6 +15,7 @@ #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "quiche/common/platform/api/quiche_logging.h" +#include "quiche/common/quiche_mem_slice.h" #include "quiche/common/quiche_stream.h" #include "quiche/web_transport/web_transport.h" @@ -34,7 +35,7 @@ class QUICHE_NO_EXPORT InMemoryStream : public Stream { bool SkipBytes(size_t bytes) override; // quiche::WriteStream implementation. - absl::Status Writev(absl::Span data, + absl::Status Writev(absl::Span data, const quiche::StreamWriteOptions& options) override { QUICHE_NOTREACHED() << "Writev called on a read-only stream"; return absl::UnimplementedError("Writev called on a read-only stream"); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/web_transport/test_tools/mock_web_transport.h b/naiveproxy/src/net/third_party/quiche/src/quiche/web_transport/test_tools/mock_web_transport.h index 656c25c269..77b1595bd7 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/web_transport/test_tools/mock_web_transport.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/web_transport/test_tools/mock_web_transport.h @@ -20,6 +20,7 @@ #include "quiche/common/platform/api/quiche_export.h" #include "quiche/common/platform/api/quiche_test.h" #include "quiche/common/quiche_callbacks.h" +#include "quiche/common/quiche_mem_slice.h" #include "quiche/common/quiche_stream.h" #include "quiche/web_transport/web_transport.h" @@ -40,7 +41,7 @@ class QUICHE_NO_EXPORT MockStream : public Stream { MOCK_METHOD(ReadResult, Read, (absl::Span buffer), (override)); MOCK_METHOD(ReadResult, Read, (std::string * output), (override)); MOCK_METHOD(absl::Status, Writev, - (absl::Span data, + (absl::Span data, const quiche::StreamWriteOptions& options), (override)); MOCK_METHOD(PeekResult, PeekNextReadableRegion, (), (const, override)); diff --git a/naiveproxy/src/net/tools/dump_cache/dump_files.cc b/naiveproxy/src/net/tools/dump_cache/dump_files.cc index 290d01e262..047e150f4b 100644 --- a/naiveproxy/src/net/tools/dump_cache/dump_files.cc +++ b/naiveproxy/src/net/tools/dump_cache/dump_files.cc @@ -258,10 +258,20 @@ bool CacheDumper::GetEntry(disk_cache::EntryStore* entry, current_hash_++; } + auto hash_table_memory = + index_file_->as_span().subspan(offsetof(disk_cache::Index, table)); + // SAFETY: offsetof above ensures that hash_table_memory beginning is aligned + // properly to store CacheAddr[]; the overall bounds come from MappedFile + // returning what it actually mapped. + base::span index_table = + UNSAFE_BUFFERS(base::span( + reinterpret_cast(hash_table_memory.data()), + hash_table_memory.size() / sizeof(disk_cache::CacheAddr))); + for (int i = current_hash_; i < index_->header.table_len; i++) { - // Yes, we'll crash if the table is shorter than expected, but only after - // dumping every entry that we can find. - disk_cache::CacheAddr addr_i = UNSAFE_TODO(index_->table[i]); + // Yes, we'll CHECK-fail if the table is shorter than expected, but only + // after dumping every entry that we can find. + disk_cache::CacheAddr addr_i = index_table[i]; if (addr_i) { current_hash_ = i; *addr = addr_i; diff --git a/naiveproxy/src/net/tools/quic/synchronous_host_resolver.cc b/naiveproxy/src/net/tools/quic/synchronous_host_resolver.cc index dfb89e3c77..f594a8b3fa 100644 --- a/naiveproxy/src/net/tools/quic/synchronous_host_resolver.cc +++ b/naiveproxy/src/net/tools/quic/synchronous_host_resolver.cc @@ -83,7 +83,7 @@ void ResolverThread::Run() { } if (rv_ == OK) { - *addresses_ = *request->GetAddressResults(); + *addresses_ = request->GetAddressResults(); } } 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 242779b265..4187d4f052 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 @@ -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 #include @@ -19,6 +14,7 @@ #include "base/at_exit.h" #include "base/base_paths.h" #include "base/command_line.h" +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/files/file_path.h" #include "base/files/file_util.h" @@ -28,10 +24,11 @@ #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" +#include "base/strings/string_view_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" -#include "crypto/sha2.h" +#include "crypto/hash.h" #include "net/cert/root_store_proto_full/root_store.pb.h" #include "third_party/boringssl/src/include/openssl/bio.h" #include "third_party/boringssl/src/include/openssl/err.h" @@ -74,14 +71,15 @@ std::optional> DecodeCerts( bssl::UniquePtr scoped_name(name); bssl::UniquePtr scoped_header(header); bssl::UniquePtr scoped_data(data); - if (strcmp(name, "CERTIFICATE") != 0) { + if (UNSAFE_TODO(strcmp(name, "CERTIFICATE")) != 0) { LOG(ERROR) << "Found PEM block of type " << name << " instead of CERTIFICATE"; return std::nullopt; } - std::string sha256_hex = base::ToLowerASCII(base::HexEncode( - crypto::SHA256Hash(base::span(data, base::checked_cast(len))))); - certs[sha256_hex] = std::string(data, data + len); + std::string sha256_hex = + base::ToLowerASCII(base::HexEncode(crypto::hash::Sha256( + UNSAFE_TODO(base::span(data, base::checked_cast(len)))))); + certs[sha256_hex] = std::string(data, UNSAFE_TODO(data + len)); } return std::move(certs); } @@ -394,7 +392,8 @@ bool WriteEvCppFile(const RootStore& root_store, continue; } - std::string sha256_hash = crypto::SHA256HashString(anchor.der()); + std::string sha256_hash = + std::string(base::as_string_view(crypto::hash::Sha256(anchor.der()))); // Begin struct. Assumed type of EVMetadata: // diff --git a/naiveproxy/src/net/tools/testserver/BUILD.gn b/naiveproxy/src/net/tools/testserver/BUILD.gn deleted file mode 100644 index cf2aa79922..0000000000 --- a/naiveproxy/src/net/tools/testserver/BUILD.gn +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright 2016 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/python.gni") - -python_library("testserver_py") { - pydeps_file = "testserver.pydeps" -} diff --git a/naiveproxy/src/net/tools/testserver/backoff_server.py b/naiveproxy/src/net/tools/testserver/backoff_server.py deleted file mode 100755 index 0a236c124d..0000000000 --- a/naiveproxy/src/net/tools/testserver/backoff_server.py +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env python -# Copyright 2012 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 simple HTTP server for manually testing exponential -back-off functionality in Chrome. -""" - - -import BaseHTTPServer -import sys -import urlparse - - -AJAX_TEST_PAGE = ''' - - - - - -
- Response code to get: - -
- -''' - - -class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): - keep_running = True - local_ip = '' - port = 0 - - def do_GET(self): - if self.path == '/quitquitquit': - self.send_response(200) - self.send_header('Content-Type', 'text/plain') - self.end_headers() - self.wfile.write('QUITTING') - RequestHandler.keep_running = False - return - - if self.path.startswith('/ajax/'): - self.send_response(200) - self.send_header('Content-Type', 'text/html') - self.end_headers() - self.wfile.write(AJAX_TEST_PAGE % (self.local_ip, - self.port, - self.path[6:])) - return - - params = urlparse.parse_qs(urlparse.urlparse(self.path).query) - - if not params or not 'code' in params or params['code'][0] == '200': - self.send_response(200) - self.send_header('Content-Type', 'text/plain') - self.end_headers() - self.wfile.write('OK') - else: - status_code = int(params['code'][0]) - self.send_response(status_code) - self.end_headers() - self.wfile.write('Error %d' % int(status_code)) - - -def main(): - if len(sys.argv) != 3: - print "Usage: %s LOCAL_IP PORT" % sys.argv[0] - sys.exit(1) - RequestHandler.local_ip = sys.argv[1] - port = int(sys.argv[2]) - RequestHandler.port = port - print "To stop the server, go to http://localhost:%d/quitquitquit" % port - httpd = BaseHTTPServer.HTTPServer(('', port), RequestHandler) - while RequestHandler.keep_running: - httpd.handle_request() - - -if __name__ == '__main__': - main() diff --git a/naiveproxy/src/net/tools/testserver/dist/_socket.pyd b/naiveproxy/src/net/tools/testserver/dist/_socket.pyd deleted file mode 100644 index 5ae91b70ac..0000000000 Binary files a/naiveproxy/src/net/tools/testserver/dist/_socket.pyd and /dev/null differ diff --git a/naiveproxy/src/net/tools/testserver/dist/_ssl.pyd b/naiveproxy/src/net/tools/testserver/dist/_ssl.pyd deleted file mode 100644 index 6a9b73c517..0000000000 Binary files a/naiveproxy/src/net/tools/testserver/dist/_ssl.pyd and /dev/null differ diff --git a/naiveproxy/src/net/tools/testserver/run_testserver.cc b/naiveproxy/src/net/tools/testserver/run_testserver.cc index 774c8f0167..45508e657c 100644 --- a/naiveproxy/src/net/tools/testserver/run_testserver.cc +++ b/naiveproxy/src/net/tools/testserver/run_testserver.cc @@ -17,7 +17,7 @@ #include "base/task/single_thread_task_executor.h" #include "base/test/test_timeouts.h" #include "net/test/embedded_test_server/embedded_test_server.h" -#include "net/test/spawned_test_server/spawned_test_server.h" +#include "net/test/embedded_test_server/install_default_websocket_handlers.h" static void PrintUsage() { printf( @@ -51,51 +51,43 @@ int main(int argc, const char* argv[]) { return -1; } - // If populated, EmbeddedTestServer is used instead of the SpawnedTestServer. - std::optional embedded_test_server_type; + // Default to HTTP. + net::EmbeddedTestServer::Type embedded_test_server_type = + net::EmbeddedTestServer::TYPE_HTTP; + bool enable_websockets = false; - net::SpawnedTestServer::Type server_type; if (command_line->HasSwitch("http")) { embedded_test_server_type = net::EmbeddedTestServer::TYPE_HTTP; } else if (command_line->HasSwitch("https")) { embedded_test_server_type = net::EmbeddedTestServer::TYPE_HTTPS; } else if (command_line->HasSwitch("ws")) { - server_type = net::SpawnedTestServer::TYPE_WS; + embedded_test_server_type = net::EmbeddedTestServer::TYPE_HTTP; + enable_websockets = true; } else if (command_line->HasSwitch("wss")) { - server_type = net::SpawnedTestServer::TYPE_WSS; + embedded_test_server_type = net::EmbeddedTestServer::TYPE_HTTPS; + enable_websockets = true; } else { - // If no scheme switch is specified, select http or https scheme. + // If no scheme switch is specified, select https if "ssl-cert" is + // specified. // TODO(toyoshim): Remove this estimation. if (command_line->HasSwitch("ssl-cert")) { embedded_test_server_type = net::EmbeddedTestServer::TYPE_HTTPS; - } else { - embedded_test_server_type = net::EmbeddedTestServer::TYPE_HTTP; } } - net::SpawnedTestServer::SSLOptions ssl_options; net::EmbeddedTestServer::ServerCertificate server_certificate; if (command_line->HasSwitch("ssl-cert")) { - if ((embedded_test_server_type.has_value() && - *embedded_test_server_type != net::EmbeddedTestServer::TYPE_HTTPS) || - (!embedded_test_server_type.has_value() && - !net::SpawnedTestServer::UsingSSL(server_type))) { + if (embedded_test_server_type != net::EmbeddedTestServer::TYPE_HTTPS) { printf("Error: --ssl-cert is specified on non-secure scheme\n"); PrintUsage(); return -1; } std::string cert_option = command_line->GetSwitchValueASCII("ssl-cert"); if (cert_option == "ok") { - ssl_options.server_certificate = - net::SpawnedTestServer::SSLOptions::CERT_OK; server_certificate = net::EmbeddedTestServer::CERT_OK; } else if (cert_option == "mismatched-name") { - ssl_options.server_certificate = - net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME; server_certificate = net::EmbeddedTestServer::CERT_MISMATCHED_NAME; } else if (cert_option == "expired") { - ssl_options.server_certificate = - net::SpawnedTestServer::SSLOptions::CERT_EXPIRED; server_certificate = net::EmbeddedTestServer::CERT_EXPIRED; } else { printf("Error: --ssl-cert has invalid value %s\n", cert_option.c_str()); @@ -120,43 +112,24 @@ int main(int argc, const char* argv[]) { return -1; } - // Use EmbeddedTestServer, if it supports the provided configuration. - if (embedded_test_server_type.has_value()) { - net::EmbeddedTestServer embedded_test_server(*embedded_test_server_type); - if (*embedded_test_server_type == net::EmbeddedTestServer::TYPE_HTTPS) { - embedded_test_server.SetSSLConfig(server_certificate); - } - - embedded_test_server.AddDefaultHandlers(doc_root); - if (!embedded_test_server.Start()) { - printf("Error: failed to start embedded test server. Exiting.\n"); - return -1; - } - - printf("Embedded test server running at %s (type ctrl+c to exit)\n", - embedded_test_server.host_port_pair().ToString().c_str()); - - base::RunLoop().Run(); - return 0; + net::EmbeddedTestServer embedded_test_server(embedded_test_server_type); + if (embedded_test_server_type == net::EmbeddedTestServer::TYPE_HTTPS) { + embedded_test_server.SetSSLConfig(server_certificate); } - // Otherwise, use the SpawnedTestServer. - std::unique_ptr test_server; - if (net::SpawnedTestServer::UsingSSL(server_type)) { - test_server = std::make_unique( - server_type, ssl_options, doc_root); - } else { - test_server = - std::make_unique(server_type, doc_root); + embedded_test_server.AddDefaultHandlers(doc_root); + if (enable_websockets) { + net::test_server::InstallDefaultWebSocketHandlers(&embedded_test_server); } - if (!test_server->Start()) { - printf("Error: failed to start test server. Exiting.\n"); + if (!embedded_test_server.Start()) { + printf("Error: failed to start embedded test server. Exiting.\n"); return -1; } - printf("testserver running at %s (type ctrl+c to exit)\n", - test_server->host_port_pair().ToString().c_str()); + printf("Embedded test server running at %s (type ctrl+c to exit)\n", + embedded_test_server.host_port_pair().ToString().c_str()); base::RunLoop().Run(); + return 0; } diff --git a/naiveproxy/src/net/tools/testserver/testserver.py b/naiveproxy/src/net/tools/testserver/testserver.py deleted file mode 100755 index 98bdb6af75..0000000000 --- a/naiveproxy/src/net/tools/testserver/testserver.py +++ /dev/null @@ -1,412 +0,0 @@ -#!/usr/bin/env vpython3 -# 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. - -"""This is a simple HTTP/TCP/PROXY/BASIC_AUTH_PROXY/WEBSOCKET server used for -testing Chrome. - -It supports several test URLs, as specified by the handlers in TestPageHandler. -By default, it listens on an ephemeral port and sends the port number back to -the originating process over a pipe. The originating process can specify an -explicit port if necessary. -""" - -from __future__ import print_function - -import base64 -import logging -import os -import select -from six.moves import BaseHTTPServer, socketserver -import six.moves.urllib.parse as urlparse -import socket -import ssl -import sys - -BASE_DIR = os.path.dirname(os.path.abspath(__file__)) -ROOT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(BASE_DIR))) - -# Insert at the beginning of the path, we want to use our copies of the library -# unconditionally (since they contain modifications from anything that might be -# obtained from e.g. PyPi). -sys.path.insert(0, os.path.join(ROOT_DIR, 'third_party', 'pywebsocket3', 'src')) - -import mod_pywebsocket.standalone -from mod_pywebsocket.standalone import WebSocketServer -# import manually -mod_pywebsocket.standalone.ssl = ssl - -import testserver_base - -SERVER_UNSET = 0 -SERVER_BASIC_AUTH_PROXY = 1 -SERVER_WEBSOCKET = 2 -SERVER_PROXY = 3 - -# Default request queue size for WebSocketServer. -_DEFAULT_REQUEST_QUEUE_SIZE = 128 - -class WebSocketOptions: - """Holds options for WebSocketServer.""" - - def __init__(self, host, port, data_dir): - self.request_queue_size = _DEFAULT_REQUEST_QUEUE_SIZE - self.server_host = host - self.port = port - self.websock_handlers = data_dir - self.scan_dir = None - self.allow_handlers_outside_root_dir = False - self.websock_handlers_map_file = None - self.cgi_directories = [] - self.is_executable_method = None - - self.use_tls = False - self.private_key = None - self.certificate = None - self.tls_client_auth = False - self.tls_client_ca = None - self.use_basic_auth = False - self.basic_auth_credential = 'Basic ' + base64.b64encode( - b'test:test').decode() - - -class ThreadingHTTPServer(socketserver.ThreadingMixIn, - testserver_base.ClientRestrictingServerMixIn, - testserver_base.BrokenPipeHandlerMixIn, - testserver_base.StoppableHTTPServer): - """This is a specialization of StoppableHTTPServer that adds client - verification and creates a new thread for every connection. It - should only be used with handlers that are known to be threadsafe.""" - - pass - - -class TestPageHandler(testserver_base.BasePageHandler): - def __init__(self, request, client_address, socket_server): - connect_handlers = [self.DefaultConnectResponseHandler] - get_handlers = [self.DefaultResponseHandler] - post_handlers = get_handlers - put_handlers = get_handlers - head_handlers = [self.DefaultResponseHandler] - testserver_base.BasePageHandler.__init__(self, request, client_address, - socket_server, connect_handlers, - get_handlers, head_handlers, - post_handlers, put_handlers) - - def DefaultResponseHandler(self): - """This is the catch-all response handler for requests that aren't handled - by one of the special handlers above. - Note that we specify the content-length as without it the https connection - is not closed properly (and the browser keeps expecting data).""" - - contents = "Default response given for path: " + self.path - self.send_response(200) - self.send_header('Content-Type', 'text/html') - self.send_header('Content-Length', len(contents)) - self.end_headers() - if (self.command != 'HEAD'): - self.wfile.write(contents.encode('utf8')) - return True - - def DefaultConnectResponseHandler(self): - """This is the catch-all response handler for CONNECT requests that aren't - handled by one of the special handlers above. Real Web servers respond - with 400 to CONNECT requests.""" - - contents = "Your client has issued a malformed or illegal request." - self.send_response(400) # bad request - self.send_header('Content-Type', 'text/html') - self.send_header('Content-Length', len(contents)) - self.end_headers() - self.wfile.write(contents.encode('utf8')) - return True - - -class ProxyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): - """A request handler that behaves as a proxy server. Only CONNECT, GET and - HEAD methods are supported. - """ - - redirect_connect_to_localhost = False; - - def _start_read_write(self, sock): - sock.setblocking(0) - self.request.setblocking(0) - rlist = [self.request, sock] - while True: - ready_sockets, _unused, errors = select.select(rlist, [], []) - if errors: - self.send_response(500) - self.end_headers() - return - for s in ready_sockets: - received = s.recv(1024) - if len(received) == 0: - return - if s == self.request: - other = sock - else: - other = self.request - # This will lose data if the kernel write buffer fills up. - # TODO(ricea): Correctly use the return value to track how much was - # written and buffer the rest. Use select to determine when the socket - # becomes writable again. - other.send(received) - - def _do_common_method(self): - url = urlparse.urlparse(self.path) - port = url.port - if not port: - if url.scheme == 'http': - port = 80 - elif url.scheme == 'https': - port = 443 - if not url.hostname or not port: - self.send_response(400) - self.end_headers() - return - - if len(url.path) == 0: - path = '/' - else: - path = url.path - if len(url.query) > 0: - path = '%s?%s' % (url.path, url.query) - - sock = None - try: - sock = socket.create_connection((url.hostname, port)) - sock.send(('%s %s %s\r\n' % - (self.command, path, self.protocol_version)).encode('utf-8')) - for name, value in self.headers.items(): - if (name.lower().startswith('connection') - or name.lower().startswith('proxy')): - continue - # HTTP headers are encoded in Latin-1. - sock.send(b'%s: %s\r\n' % - (name.encode('latin-1'), value.encode('latin-1'))) - sock.send(b'\r\n') - # This is wrong: it will pass through connection-level headers and - # misbehave on connection reuse. The only reason it works at all is that - # our test servers have never supported connection reuse. - # TODO(ricea): Use a proper HTTP client library instead. - self._start_read_write(sock) - except Exception: - logging.exception('failure in common method: %s %s', self.command, path) - self.send_response(500) - self.end_headers() - finally: - if sock is not None: - sock.close() - - def do_CONNECT(self): - try: - pos = self.path.rfind(':') - host = self.path[:pos] - port = int(self.path[pos+1:]) - except Exception: - self.send_response(400) - self.end_headers() - - if ProxyRequestHandler.redirect_connect_to_localhost: - host = "127.0.0.1" - - sock = None - try: - sock = socket.create_connection((host, port)) - self.send_response(200, 'Connection established') - self.end_headers() - self._start_read_write(sock) - except Exception: - logging.exception('failure in CONNECT: %s', path) - self.send_response(500) - self.end_headers() - finally: - if sock is not None: - sock.close() - - def do_GET(self): - self._do_common_method() - - def do_HEAD(self): - self._do_common_method() - -class BasicAuthProxyRequestHandler(ProxyRequestHandler): - """A request handler that behaves as a proxy server which requires - basic authentication. - """ - - _AUTH_CREDENTIAL = 'Basic Zm9vOmJhcg==' # foo:bar - - def parse_request(self): - """Overrides parse_request to check credential.""" - - if not ProxyRequestHandler.parse_request(self): - return False - - auth = self.headers.get('Proxy-Authorization', None) - if auth != self._AUTH_CREDENTIAL: - self.send_response(407) - self.send_header('Proxy-Authenticate', 'Basic realm="MyRealm1"') - self.end_headers() - return False - - return True - - -class ServerRunner(testserver_base.TestServerRunner): - """TestServerRunner for the net test servers.""" - - def __init__(self): - super(ServerRunner, self).__init__() - - def __make_data_dir(self): - if self.options.data_dir: - if not os.path.isdir(self.options.data_dir): - raise testserver_base.OptionError('specified data dir not found: ' + - self.options.data_dir + ' exiting...') - my_data_dir = self.options.data_dir - else: - # Create the default path to our data dir, relative to the exe dir. - my_data_dir = os.path.join(BASE_DIR, "..", "..", "data") - - return my_data_dir - - def create_server(self, server_data): - port = self.options.port - host = self.options.host - - logging.basicConfig() - - # Work around a bug in Mac OS 10.6. Spawning a WebSockets server - # will result in a call to |getaddrinfo|, which fails with "nodename - # nor servname provided" for localhost:0 on 10.6. - # TODO(ricea): Remove this if no longer needed. - if self.options.server_type == SERVER_WEBSOCKET and \ - host == "localhost" and \ - port == 0: - host = "127.0.0.1" - - # Construct the subjectAltNames for any ad-hoc generated certificates. - # As host can be either a DNS name or IP address, attempt to determine - # which it is, so it can be placed in the appropriate SAN. - dns_sans = None - ip_sans = None - ip = None - try: - ip = socket.inet_aton(host) - ip_sans = [ip] - except socket.error: - pass - if ip is None: - dns_sans = [host] - - if self.options.server_type == SERVER_UNSET: - raise testserver_base.OptionError('no server type specified') - elif self.options.server_type == SERVER_WEBSOCKET: - # TODO(toyoshim): Remove following os.chdir. Currently this operation - # is required to work correctly. It should be fixed from pywebsocket side. - os.chdir(self.__make_data_dir()) - websocket_options = WebSocketOptions(host, port, '.') - scheme = "ws" - if self.options.cert_and_key_file: - scheme = "wss" - websocket_options.use_tls = True - key_path = os.path.join(ROOT_DIR, self.options.cert_and_key_file) - if not os.path.isfile(key_path): - raise testserver_base.OptionError( - 'specified server cert file not found: ' + - self.options.cert_and_key_file + ' exiting...') - websocket_options.private_key = key_path - websocket_options.certificate = key_path - - if self.options.ssl_client_auth: - websocket_options.tls_client_cert_optional = False - websocket_options.tls_client_auth = True - if len(self.options.ssl_client_ca) != 1: - raise testserver_base.OptionError( - 'one trusted client CA file should be specified') - if not os.path.isfile(self.options.ssl_client_ca[0]): - raise testserver_base.OptionError( - 'specified trusted client CA file not found: ' + - self.options.ssl_client_ca[0] + ' exiting...') - websocket_options.tls_client_ca = self.options.ssl_client_ca[0] - print('Trying to start websocket server on %s://%s:%d...' % - (scheme, websocket_options.server_host, websocket_options.port)) - server = WebSocketServer(websocket_options) - print('WebSocket server started on %s://%s:%d...' % - (scheme, host, server.server_port)) - server_data['port'] = server.server_port - websocket_options.use_basic_auth = self.options.ws_basic_auth - elif self.options.server_type == SERVER_PROXY: - ProxyRequestHandler.redirect_connect_to_localhost = \ - self.options.redirect_connect_to_localhost - server = ThreadingHTTPServer((host, port), ProxyRequestHandler) - print('Proxy server started on port %d...' % server.server_port) - server_data['port'] = server.server_port - elif self.options.server_type == SERVER_BASIC_AUTH_PROXY: - ProxyRequestHandler.redirect_connect_to_localhost = \ - self.options.redirect_connect_to_localhost - server = ThreadingHTTPServer((host, port), BasicAuthProxyRequestHandler) - print('BasicAuthProxy server started on port %d...' % server.server_port) - server_data['port'] = server.server_port - else: - raise testserver_base.OptionError('unknown server type' + - self.options.server_type) - - return server - - def add_options(self): - testserver_base.TestServerRunner.add_options(self) - self.option_parser.add_option('--proxy', - action='store_const', - const=SERVER_PROXY, - default=SERVER_UNSET, - dest='server_type', - help='start up a proxy server.') - self.option_parser.add_option('--basic-auth-proxy', - action='store_const', - const=SERVER_BASIC_AUTH_PROXY, - default=SERVER_UNSET, - dest='server_type', - help='start up a proxy server which requires ' - 'basic authentication.') - self.option_parser.add_option('--websocket', - action='store_const', - const=SERVER_WEBSOCKET, - default=SERVER_UNSET, - dest='server_type', - help='start up a WebSocket server.') - self.option_parser.add_option('--cert-and-key-file', - dest='cert_and_key_file', help='specify the ' - 'path to the file containing the certificate ' - 'and private key for the server in PEM ' - 'format') - self.option_parser.add_option('--ssl-client-auth', action='store_true', - help='Require SSL client auth on every ' - 'connection.') - self.option_parser.add_option('--ssl-client-ca', action='append', - default=[], help='Specify that the client ' - 'certificate request should include the CA ' - 'named in the subject of the DER-encoded ' - 'certificate contained in the specified ' - 'file. This option may appear multiple ' - 'times, indicating multiple CA names should ' - 'be sent in the request.') - self.option_parser.add_option('--file-root-url', default='/files/', - help='Specify a root URL for files served.') - # TODO(ricea): Generalize this to support basic auth for HTTP too. - self.option_parser.add_option('--ws-basic-auth', action='store_true', - dest='ws_basic_auth', - help='Enable basic-auth for WebSocket') - self.option_parser.add_option('--redirect-connect-to-localhost', - dest='redirect_connect_to_localhost', - default=False, action='store_true', - help='If set, the Proxy server will connect ' - 'to localhost instead of the requested URL ' - 'on CONNECT requests') - - -if __name__ == '__main__': - sys.exit(ServerRunner().main()) diff --git a/naiveproxy/src/net/tools/testserver/testserver.py.vpython3 b/naiveproxy/src/net/tools/testserver/testserver.py.vpython3 deleted file mode 100644 index 6bef4acae3..0000000000 --- a/naiveproxy/src/net/tools/testserver/testserver.py.vpython3 +++ /dev/null @@ -1,48 +0,0 @@ -# This is a vpython "spec" file. -# -# It describes patterns for python wheel dependencies of the python scripts in -# the chromium repo, particularly for dependencies that have compiled components -# (since pure-python dependencies can be easily vendored into third_party). -# -# When vpython is invoked, it finds this file and builds a python VirtualEnv, -# containing all of the dependencies described in this file, fetching them from -# CIPD (the "Chrome Infrastructure Package Deployer" service). Unlike `pip`, -# this never requires the end-user machine to have a working python extension -# compilation environment. All of these packages are built using: -# https://chromium.googlesource.com/infra/infra/+/main/infra/tools/dockerbuild/ -# -# All python scripts in the repo share this same spec, to avoid dependency -# fragmentation. -# -# If you have depot_tools installed in your $PATH, you can invoke python scripts -# in this repo by running them as you normally would run them, except -# substituting `vpython` instead of `python` on the command line, e.g.: -# vpython path/to/script.py some --arguments -# -# Read more about `vpython` and how to modify this file here: -# https://chromium.googlesource.com/infra/infra/+/main/doc/users/vpython.md - -# This Python file gets its own vpython spec since it doesn't actually need that -# many dependencies and trying to load all dependencies from the main .vpython3 -# spec on ChromeOS VMs runs into disk space issues. - -python_version: "3.11" - -# The default set of platforms vpython checks does not yet include mac-arm64. -# Setting `verify_pep425_tag` to the list of platforms we explicitly must support -# allows us to ensure that vpython specs stay mac-arm64-friendly -verify_pep425_tag: [ - {python: "cp38", abi: "cp311", platform: "manylinux1_x86_64"}, - {python: "cp38", abi: "cp311", platform: "linux_arm64"}, - - {python: "cp38", abi: "cp311", platform: "macosx_10_10_intel"}, - {python: "cp38", abi: "cp311", platform: "macosx_11_0_arm64"}, - - {python: "cp38", abi: "cp311", platform: "win32"}, - {python: "cp38", abi: "cp311", platform: "win_amd64"} -] - -wheel: < - name: "infra/python/wheels/six-py2_py3" - version: "version:1.15.0" -> diff --git a/naiveproxy/src/net/tools/testserver/testserver.pydeps b/naiveproxy/src/net/tools/testserver/testserver.pydeps deleted file mode 100644 index a4deed6804..0000000000 --- a/naiveproxy/src/net/tools/testserver/testserver.pydeps +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by running: -# build/print_python_deps.py --root net/tools/testserver --output net/tools/testserver/testserver.pydeps net/tools/testserver/testserver.py -../../../third_party/pywebsocket3/src/mod_pywebsocket/__init__.py -../../../third_party/pywebsocket3/src/mod_pywebsocket/_stream_exceptions.py -../../../third_party/pywebsocket3/src/mod_pywebsocket/common.py -../../../third_party/pywebsocket3/src/mod_pywebsocket/dispatch.py -../../../third_party/pywebsocket3/src/mod_pywebsocket/extensions.py -../../../third_party/pywebsocket3/src/mod_pywebsocket/handshake/__init__.py -../../../third_party/pywebsocket3/src/mod_pywebsocket/handshake/base.py -../../../third_party/pywebsocket3/src/mod_pywebsocket/handshake/hybi.py -../../../third_party/pywebsocket3/src/mod_pywebsocket/http_header_util.py -../../../third_party/pywebsocket3/src/mod_pywebsocket/memorizingfile.py -../../../third_party/pywebsocket3/src/mod_pywebsocket/msgutil.py -../../../third_party/pywebsocket3/src/mod_pywebsocket/request_handler.py -../../../third_party/pywebsocket3/src/mod_pywebsocket/server_util.py -../../../third_party/pywebsocket3/src/mod_pywebsocket/standalone.py -../../../third_party/pywebsocket3/src/mod_pywebsocket/stream.py -../../../third_party/pywebsocket3/src/mod_pywebsocket/util.py -../../../third_party/pywebsocket3/src/mod_pywebsocket/websocket_server.py -testserver.py -testserver_base.py diff --git a/naiveproxy/src/net/tools/testserver/testserver_base.py b/naiveproxy/src/net/tools/testserver/testserver_base.py deleted file mode 100644 index d52fc5d1fe..0000000000 --- a/naiveproxy/src/net/tools/testserver/testserver_base.py +++ /dev/null @@ -1,268 +0,0 @@ -# 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. - -from six.moves import BaseHTTPServer -import errno -import json -import optparse -import os -import re -import socket -from six.moves import socketserver as SocketServer -import struct -import sys -import warnings - -# Ignore deprecation warnings, they make our output more cluttered. -warnings.filterwarnings("ignore", category=DeprecationWarning) - -if sys.platform == 'win32': - import msvcrt - -# Using debug() seems to cause hangs on XP: see http://crbug.com/64515. -debug_output = sys.stderr -def debug(string): - debug_output.write(string + "\n") - debug_output.flush() - - -class Error(Exception): - """Error class for this module.""" - - -class OptionError(Error): - """Error for bad command line options.""" - - -class FileMultiplexer(object): - def __init__(self, fd1, fd2) : - self.__fd1 = fd1 - self.__fd2 = fd2 - - def __del__(self) : - if self.__fd1 != sys.stdout and self.__fd1 != sys.stderr: - self.__fd1.close() - if self.__fd2 != sys.stdout and self.__fd2 != sys.stderr: - self.__fd2.close() - - def write(self, text) : - self.__fd1.write(text) - self.__fd2.write(text) - - def flush(self) : - self.__fd1.flush() - self.__fd2.flush() - - -class ClientRestrictingServerMixIn: - """Implements verify_request to limit connections to our configured IP - address.""" - - def verify_request(self, _request, client_address): - return client_address[0] == self.server_address[0] - - -class BrokenPipeHandlerMixIn: - """Allows the server to deal with "broken pipe" errors (which happen if the - browser quits with outstanding requests, like for the favicon). This mix-in - requires the class to derive from SocketServer.BaseServer and not override its - handle_error() method. """ - - def handle_error(self, request, client_address): - value = sys.exc_info()[1] - if isinstance(value, socket.error): - err = value.args[0] - if sys.platform in ('win32', 'cygwin'): - # "An established connection was aborted by the software in your host." - pipe_err = 10053 - else: - pipe_err = errno.EPIPE - if err == pipe_err: - print("testserver.py: Broken pipe") - return - if err == errno.ECONNRESET: - print("testserver.py: Connection reset by peer") - return - SocketServer.BaseServer.handle_error(self, request, client_address) - - -class StoppableHTTPServer(BaseHTTPServer.HTTPServer): - """This is a specialization of BaseHTTPServer to allow it - to be exited cleanly (by setting its "stop" member to True).""" - - def serve_forever(self): - self.stop = False - self.nonce_time = None - while not self.stop: - self.handle_request() - self.socket.close() - - -def MultiplexerHack(std_fd, log_fd): - """Creates a FileMultiplexer that will write to both specified files. - - When running on Windows XP bots, stdout and stderr will be invalid file - handles, so log_fd will be returned directly. (This does not occur if you - run the test suite directly from a console, but only if the output of the - test executable is redirected.) - """ - if std_fd.fileno() <= 0: - return log_fd - return FileMultiplexer(std_fd, log_fd) - - -class BasePageHandler(BaseHTTPServer.BaseHTTPRequestHandler): - - def __init__(self, request, client_address, socket_server, - connect_handlers, get_handlers, head_handlers, post_handlers, - put_handlers): - self._connect_handlers = connect_handlers - self._get_handlers = get_handlers - self._head_handlers = head_handlers - self._post_handlers = post_handlers - self._put_handlers = put_handlers - BaseHTTPServer.BaseHTTPRequestHandler.__init__( - self, request, client_address, socket_server) - - def log_request(self, *args, **kwargs): - # Disable request logging to declutter test log output. - pass - - def _ShouldHandleRequest(self, handler_name): - """Determines if the path can be handled by the handler. - - We consider a handler valid if the path begins with the - handler name. It can optionally be followed by "?*", "/*". - """ - - pattern = re.compile('%s($|\?|/).*' % handler_name) - return pattern.match(self.path) - - def do_CONNECT(self): - for handler in self._connect_handlers: - if handler(): - return - - def do_GET(self): - for handler in self._get_handlers: - if handler(): - return - - def do_HEAD(self): - for handler in self._head_handlers: - if handler(): - return - - def do_POST(self): - for handler in self._post_handlers: - if handler(): - return - - def do_PUT(self): - for handler in self._put_handlers: - if handler(): - return - - -class TestServerRunner(object): - """Runs a test server and communicates with the controlling C++ test code. - - Subclasses should override the create_server method to create their server - object, and the add_options method to add their own options. - """ - - def __init__(self): - self.option_parser = optparse.OptionParser() - self.add_options() - - def main(self): - self.options, self.args = self.option_parser.parse_args() - - logfile = open(self.options.log_file, 'w') - - # http://crbug.com/248796 : Error logs streamed to normal sys.stderr will be - # written to HTTP response payload when remote test server is used. - # For this reason, some tests like ResourceFetcherTests.ResourceFetcher404 - # were failing on Android because remote test server is being used there. - # To fix them, we need to use sys.stdout as sys.stderr if remote test server - # is used. - if self.options.on_remote_server: - sys.stderr = sys.stdout - - sys.stderr = MultiplexerHack(sys.stderr, logfile) - if self.options.log_to_console: - sys.stdout = MultiplexerHack(sys.stdout, logfile) - else: - sys.stdout = logfile - - server_data = { - 'host': self.options.host, - } - self.server = self.create_server(server_data) - self._notify_startup_complete(server_data) - self.run_server() - - def create_server(self, server_data): - """Creates a server object and returns it. - - Must populate server_data['port'], and can set additional server_data - elements if desired.""" - raise NotImplementedError() - - def run_server(self): - try: - self.server.serve_forever() - except KeyboardInterrupt: - print('shutting down server') - self.server.stop = True - - def add_options(self): - self.option_parser.add_option('--startup-pipe', type='int', - dest='startup_pipe', - help='File handle of pipe to parent process') - self.option_parser.add_option('--log-to-console', action='store_const', - const=True, default=False, - dest='log_to_console', - help='Enables or disables sys.stdout logging ' - 'to the console.') - self.option_parser.add_option('--log-file', default='testserver.log', - dest='log_file', - help='The name of the server log file.') - self.option_parser.add_option('--port', default=0, type='int', - help='Port used by the server. If ' - 'unspecified, the server will listen on an ' - 'ephemeral port.') - self.option_parser.add_option('--host', default='127.0.0.1', - dest='host', - help='Hostname or IP upon which the server ' - 'will listen. Client connections will also ' - 'only be allowed from this address.') - self.option_parser.add_option('--data-dir', dest='data_dir', - help='Directory from which to read the ' - 'files.') - self.option_parser.add_option('--on-remote-server', action='store_const', - const=True, default=False, - dest='on_remote_server', - help='Whether remote server is being used or ' - 'not.') - - def _notify_startup_complete(self, server_data): - # Notify the parent that we've started. (BaseServer subclasses - # bind their sockets on construction.) - if self.options.startup_pipe is not None: - server_data_json = json.dumps(server_data).encode() - server_data_len = len(server_data_json) - print('sending server_data: %s (%d bytes)' % - (server_data_json, server_data_len)) - if sys.platform == 'win32': - fd = msvcrt.open_osfhandle(self.options.startup_pipe, 0) - else: - fd = self.options.startup_pipe - startup_pipe = os.fdopen(fd, "wb") - # First write the data length as an unsigned 4-byte value. This - # is _not_ using network byte ordering since the other end of the - # pipe is on the same machine. - startup_pipe.write(struct.pack('=L', server_data_len)) - startup_pipe.write(server_data_json) - startup_pipe.close() diff --git a/naiveproxy/src/net/tools/transport_security_state_generator/BUILD.gn b/naiveproxy/src/net/tools/transport_security_state_generator/BUILD.gn index 1bf81bbe91..5e4921447d 100644 --- a/naiveproxy/src/net/tools/transport_security_state_generator/BUILD.gn +++ b/naiveproxy/src/net/tools/transport_security_state_generator/BUILD.gn @@ -23,6 +23,7 @@ source_set("transport_security_state_generator_sources") { ] deps = [ "//base", + "//crypto", "//net/tools/huffman_trie:huffman_trie_generator_sources", "//third_party/boringssl", ] diff --git a/naiveproxy/src/net/tools/transport_security_state_generator/cert_util.cc b/naiveproxy/src/net/tools/transport_security_state_generator/cert_util.cc index 9771b42528..ac7e836fad 100644 --- a/naiveproxy/src/net/tools/transport_security_state_generator/cert_util.cc +++ b/naiveproxy/src/net/tools/transport_security_state_generator/cert_util.cc @@ -12,6 +12,7 @@ #include "base/numerics/clamped_math.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" +#include "crypto/evp.h" #include "net/tools/transport_security_state_generator/spki_hash.h" #include "third_party/boringssl/src/include/openssl/crypto.h" @@ -129,17 +130,8 @@ bool CalculateSPKIHashFromCertificate(X509* certificate, SPKIHash* out_hash) { return false; } - uint8_t* spki_der; - size_t spki_der_len; - bssl::ScopedCBB cbb; - if (!CBB_init(cbb.get(), 0) || - !EVP_marshal_public_key(cbb.get(), key.get()) || - !CBB_finish(cbb.get(), &spki_der, &spki_der_len)) { - return false; - } - - out_hash->CalculateFromBytes(spki_der, spki_der_len); - OPENSSL_free(spki_der); + std::vector spki_der = crypto::evp::PublicKeyToBytes(key.get()); + out_hash->CalculateFromBytes(spki_der); return true; } @@ -150,7 +142,6 @@ bool CalculateSPKIHashFromKey(std::string_view pem_key, SPKIHash* out_hash) { return false; } - out_hash->CalculateFromBytes(reinterpret_cast(der.data()), - der.size()); + out_hash->CalculateFromBytes(base::as_byte_span(der)); return true; } diff --git a/naiveproxy/src/net/tools/transport_security_state_generator/input_file_parsers.cc b/naiveproxy/src/net/tools/transport_security_state_generator/input_file_parsers.cc index bdada0cffe..5e6526e473 100644 --- a/naiveproxy/src/net/tools/transport_security_state_generator/input_file_parsers.cc +++ b/naiveproxy/src/net/tools/transport_security_state_generator/input_file_parsers.cc @@ -507,11 +507,7 @@ bool ParseJSON(std::string_view hsts_json, } std::string name = *maybe_name; - const std::string* maybe_report_uri = parsed->FindString("report_uri"); - std::string report_uri = - maybe_report_uri ? *maybe_report_uri : std::string(); - - auto pinset = std::make_unique(name, report_uri); + auto pinset = std::make_unique(name); const base::Value::List* pinset_static_hashes_list = parsed->FindList("static_spki_hashes"); diff --git a/naiveproxy/src/net/tools/transport_security_state_generator/pinset.cc b/naiveproxy/src/net/tools/transport_security_state_generator/pinset.cc index ba0ab5734e..a2c5a4b5b8 100644 --- a/naiveproxy/src/net/tools/transport_security_state_generator/pinset.cc +++ b/naiveproxy/src/net/tools/transport_security_state_generator/pinset.cc @@ -6,8 +6,7 @@ namespace net::transport_security_state { -Pinset::Pinset(std::string name, std::string report_uri) - : name_(name), report_uri_(report_uri) {} +Pinset::Pinset(std::string name) : name_(name) {} Pinset::~Pinset() = default; diff --git a/naiveproxy/src/net/tools/transport_security_state_generator/pinset.h b/naiveproxy/src/net/tools/transport_security_state_generator/pinset.h index b52ce5e040..d4dda4fcda 100644 --- a/naiveproxy/src/net/tools/transport_security_state_generator/pinset.h +++ b/naiveproxy/src/net/tools/transport_security_state_generator/pinset.h @@ -15,7 +15,7 @@ namespace net::transport_security_state { // the same pinset. class Pinset { public: - Pinset(std::string name, std::string report_uri); + explicit Pinset(std::string name); Pinset(const Pinset&) = delete; Pinset& operator=(const Pinset&) = delete; @@ -23,7 +23,6 @@ class Pinset { ~Pinset(); const std::string& name() const { return name_; } - const std::string& report_uri() const { return report_uri_; } const std::vector& static_spki_hashes() const { return static_spki_hashes_; @@ -42,7 +41,6 @@ class Pinset { private: std::string name_; - std::string report_uri_; // These vectors contain names rather than actual hashes. std::vector static_spki_hashes_; diff --git a/naiveproxy/src/net/tools/transport_security_state_generator/preloaded_state_generator.cc b/naiveproxy/src/net/tools/transport_security_state_generator/preloaded_state_generator.cc index b85de8d7a4..df93b8fbd8 100644 --- a/naiveproxy/src/net/tools/transport_security_state_generator/preloaded_state_generator.cc +++ b/naiveproxy/src/net/tools/transport_security_state_generator/preloaded_state_generator.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 "net/tools/transport_security_state_generator/preloaded_state_generator.h" #include @@ -37,10 +32,6 @@ std::string FormatRejectedKeyName(const std::string& name) { return "k" + name + "RejectedCerts"; } -std::string FormatReportURIName(const std::string& name) { - return "k" + name + "ReportURI"; -} - // Replaces the first occurrence of "[[" + name + "]]" in |*tpl| with // |value|. bool ReplaceTag(const std::string& name, @@ -90,21 +81,19 @@ std::string FormatVectorAsArray(const std::vector& bytes) { std::string WritePinsetList(const std::string& name, const std::vector& pins) { - std::string output = "static const char* const " + name + "[] = {"; + std::string output = + "static constexpr SHA256HashValue const * " + name + "[] = {"; output.append(kNewLine); for (const auto& pin_name : pins) { output.append(kIndent); output.append(kIndent); + output.append("&"); output.append(FormatSPKIName(pin_name)); output.append(","); output.append(kNewLine); } - output.append(kIndent); - output.append(kIndent); - output.append("nullptr,"); - output.append(kNewLine); output.append("};"); return output; @@ -135,7 +124,7 @@ std::string PreloadedStateGenerator::Generate( const std::string& preload_template, const TransportSecurityStateEntries& entries, const Pinsets& pinsets, - const base::Time& timestamp) { + base::Time timestamp) { std::string output = preload_template; ProcessSPKIHashes(pinsets, &output); @@ -198,25 +187,22 @@ void PreloadedStateGenerator::ProcessSPKIHashes(const Pinsets& pinset, const std::string& name = current.first; const SPKIHash& hash = current.second; - output.append("static const char " + FormatSPKIName(name) + "[] ="); + output.append("static constexpr SHA256HashValue " + FormatSPKIName(name) + + " = {"); output.append(kNewLine); for (size_t i = 0; i < hash.size() / 16; ++i) { output.append(kIndent); output.append(kIndent); - output.append("\""); for (size_t j = i * 16; j < ((i + 1) * 16); ++j) { - base::StringAppendF(&output, "\\x%02x", hash.data()[j]); + base::StringAppendF(&output, "0x%02x, ", hash.span()[j]); } - output.append("\""); - if (i + 1 == hash.size() / 16) { - output.append(";"); - } output.append(kNewLine); } + output.append("};"); output.append(kNewLine); } @@ -243,7 +229,9 @@ void PreloadedStateGenerator::ProcessPinsets(const Pinsets& pinset, WritePinsetList(accepted_pins_names, pinset_ptr->static_spki_hashes())); certs_output.append(kNewLine); - std::string rejected_pins_names = "kNoRejectedPublicKeys"; + // Initialized with a placeholder for when no public keys are rejected. + std::string rejected_pins_names = "{}"; + if (pinset_ptr->bad_static_spki_hashes().size()) { rejected_pins_names = FormatRejectedKeyName(uppercased_name); certs_output.append(WritePinsetList( @@ -251,21 +239,10 @@ void PreloadedStateGenerator::ProcessPinsets(const Pinsets& pinset, certs_output.append(kNewLine); } - std::string report_uri = "kNoReportURI"; - if (pinset_ptr->report_uri().size()) { - report_uri = FormatReportURIName(uppercased_name); - certs_output.append("static const char " + report_uri + "[] = "); - certs_output.append("\""); - certs_output.append(pinset_ptr->report_uri()); - certs_output.append("\";"); - certs_output.append(kNewLine); - } - certs_output.append(kNewLine); - pinsets_output.append(kIndent); pinsets_output.append(kIndent); pinsets_output.append("{" + accepted_pins_names + ", " + - rejected_pins_names + ", " + report_uri + "},"); + rejected_pins_names + "},"); pinsets_output.append(kNewLine); pinset_map->insert(NameIDPair(pinset_ptr->name(), diff --git a/naiveproxy/src/net/tools/transport_security_state_generator/preloaded_state_generator.h b/naiveproxy/src/net/tools/transport_security_state_generator/preloaded_state_generator.h index d6b6bde270..b1d27bdc4c 100644 --- a/naiveproxy/src/net/tools/transport_security_state_generator/preloaded_state_generator.h +++ b/naiveproxy/src/net/tools/transport_security_state_generator/preloaded_state_generator.h @@ -31,7 +31,7 @@ class PreloadedStateGenerator { std::string Generate(const std::string& preload_template, const TransportSecurityStateEntries& entries, const Pinsets& pinsets, - const base::Time& timestamp); + base::Time timestamp); private: void ProcessSPKIHashes(const Pinsets& pinset, std::string* tpl); diff --git a/naiveproxy/src/net/tools/transport_security_state_generator/spki_hash.cc b/naiveproxy/src/net/tools/transport_security_state_generator/spki_hash.cc index 618e812eaf..b098da769e 100644 --- a/naiveproxy/src/net/tools/transport_security_state_generator/spki_hash.cc +++ b/naiveproxy/src/net/tools/transport_security_state_generator/spki_hash.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/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "net/tools/transport_security_state_generator/spki_hash.h" #include @@ -40,12 +35,12 @@ bool SPKIHash::FromString(std::string_view hash_string) { return false; } - memcpy(data_, decoded.data(), decoded.size()); + base::span(data_).copy_from(base::as_byte_span(decoded)); return true; } -void SPKIHash::CalculateFromBytes(const uint8_t* input, size_t input_length) { - SHA256(input, input_length, data_); +void SPKIHash::CalculateFromBytes(base::span bytes) { + data_ = crypto::hash::Sha256(bytes); } } // namespace net::transport_security_state diff --git a/naiveproxy/src/net/tools/transport_security_state_generator/spki_hash.h b/naiveproxy/src/net/tools/transport_security_state_generator/spki_hash.h index 935d94b1ef..1cbc4077dd 100644 --- a/naiveproxy/src/net/tools/transport_security_state_generator/spki_hash.h +++ b/naiveproxy/src/net/tools/transport_security_state_generator/spki_hash.h @@ -10,12 +10,12 @@ #include +#include "crypto/hash.h" + namespace net::transport_security_state { class SPKIHash { public: - enum : size_t { kLength = 32 }; - SPKIHash(); ~SPKIHash(); @@ -27,18 +27,16 @@ class SPKIHash { // Calculates the SHA256 digest over |*input| and copies the result to // |data_|. - void CalculateFromBytes(const uint8_t* input, size_t input_length); + void CalculateFromBytes(base::span bytes); - // Returns the size of the hash in bytes. Harcoded to 32 which is the length - // of a SHA256 hash. - size_t size() const { return kLength; } + // Returns the size of the hash in bytes. + size_t size() const { return data_.size(); } - uint8_t* data() { return data_; } - const uint8_t* data() const { return data_; } + base::span span() { return data_; } + base::span span() const { return data_; } private: - // The bytes of the hash. Current hashes are SHA256 and thus 32 bytes long. - uint8_t data_[kLength]; + std::array data_; }; } // namespace net::transport_security_state 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 4360cb8b9e..536bde8879 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 @@ -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 #include #include @@ -15,9 +10,11 @@ #include "base/at_exit.h" #include "base/command_line.h" +#include "base/compiler_specific.h" #include "base/files/file_util.h" #include "base/logging.h" #include "base/path_service.h" +#include "base/strings/string_view_util.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "build/build_config.h" @@ -51,8 +48,8 @@ bool CheckForDuplicatePins(const Pinsets& pinsets) { } seen_names.insert(pin.first); - std::string hash = - std::string(pin.second.data(), pin.second.data() + pin.second.size()); + const std::string hash = + std::string(base::as_string_view(pin.second.span())); auto it = seen_hashes.find(hash); if (it != seen_hashes.cend()) { LOG(ERROR) << "Duplicate pin hash for " << pin.first diff --git a/naiveproxy/src/net/url_request/redirect_info.cc b/naiveproxy/src/net/url_request/redirect_info.cc index becf2a4155..037df288c5 100644 --- a/naiveproxy/src/net/url_request/redirect_info.cc +++ b/naiveproxy/src/net/url_request/redirect_info.cc @@ -65,6 +65,7 @@ RedirectInfo RedirectInfo::ComputeRedirectInfo( RedirectInfo::FirstPartyURLPolicy original_first_party_url_policy, ReferrerPolicy original_referrer_policy, const std::string& original_referrer, + const std::optional& original_initiator, int http_status_code, const GURL& new_location, const std::optional& referrer_policy_header, @@ -73,6 +74,7 @@ RedirectInfo RedirectInfo::ComputeRedirectInfo( bool is_signed_exchange_fallback_redirect) { RedirectInfo redirect_info; + redirect_info.original_initiator = original_initiator; redirect_info.status_code = http_status_code; // The request method may change, depending on the status code. diff --git a/naiveproxy/src/net/url_request/redirect_info.h b/naiveproxy/src/net/url_request/redirect_info.h index 810eaf97d9..49fe7a94dc 100644 --- a/naiveproxy/src/net/url_request/redirect_info.h +++ b/naiveproxy/src/net/url_request/redirect_info.h @@ -13,6 +13,7 @@ #include "net/cookies/site_for_cookies.h" #include "net/url_request/referrer_policy.h" #include "url/gurl.h" +#include "url/origin.h" namespace net { @@ -42,6 +43,7 @@ struct NET_EXPORT RedirectInfo { FirstPartyURLPolicy original_first_party_url_policy, ReferrerPolicy original_referrer_policy, const std::string& original_referrer, + const std::optional& original_initiator, // The HTTP status code of the redirect response. int http_status_code, // The new location URL of the redirect response. @@ -58,6 +60,10 @@ struct NET_EXPORT RedirectInfo { // Whether the redirect is caused by a failure of signed exchange loading. bool is_signed_exchange_fallback_redirect = false); + // The original request's initiator. This is used for some checks if a + // redirect is safe. + std::optional original_initiator; + // The status code for the redirect response. This is almost redundant with // the response headers, but some URLRequestJobs emit redirects without // headers. diff --git a/naiveproxy/src/net/url_request/redirect_util.cc b/naiveproxy/src/net/url_request/redirect_util.cc index 08f6db50bf..383c331864 100644 --- a/naiveproxy/src/net/url_request/redirect_util.cc +++ b/naiveproxy/src/net/url_request/redirect_util.cc @@ -19,7 +19,7 @@ namespace net { // static void RedirectUtil::UpdateHttpRequest( const GURL& original_url, - const std::string& original_method, + std::string_view original_method, const RedirectInfo& redirect_info, const std::optional>& removed_headers, const std::optional& modified_headers, diff --git a/naiveproxy/src/net/url_request/redirect_util.h b/naiveproxy/src/net/url_request/redirect_util.h index 4d538d809b..cf493026c2 100644 --- a/naiveproxy/src/net/url_request/redirect_util.h +++ b/naiveproxy/src/net/url_request/redirect_util.h @@ -7,6 +7,7 @@ #include #include +#include #include #include "base/memory/scoped_refptr.h" @@ -38,7 +39,7 @@ class RedirectUtil { // cleared during the redirect. NET_EXPORT static void UpdateHttpRequest( const GURL& original_url, - const std::string& original_method, + std::string_view original_method, const RedirectInfo& redirect_info, const std::optional>& removed_headers, const std::optional& modified_headers, diff --git a/naiveproxy/src/net/url_request/url_request.h b/naiveproxy/src/net/url_request/url_request.h index 35416bf46f..ca68860c36 100644 --- a/naiveproxy/src/net/url_request/url_request.h +++ b/naiveproxy/src/net/url_request/url_request.h @@ -30,7 +30,6 @@ #include "net/base/load_states.h" #include "net/base/load_timing_info.h" #include "net/base/load_timing_internal_info.h" -#include "net/base/net_error_details.h" #include "net/base/net_errors.h" #include "net/base/net_export.h" #include "net/base/network_delegate.h" @@ -73,6 +72,7 @@ class CookieOptions; class CookieInclusionStatus; class IOBuffer; struct LoadTimingInfo; +struct NetErrorDetails; struct RedirectInfo; class SSLCertRequestInfo; class SSLInfo; @@ -524,16 +524,14 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { // The time at which the returned response was requested. For cached // responses, this is the last time the cache entry was validated. - const base::Time& request_time() const { return response_info_.request_time; } + base::Time request_time() const { return response_info_.request_time; } // The time at which the returned response was generated. For cached // responses, this is the last time the cache entry was validated. - const base::Time& response_time() const { - return response_info_.response_time; - } + base::Time response_time() const { return response_info_.response_time; } // Like response_time, but ignoring revalidations. - const base::Time& original_response_time() const { + base::Time original_response_time() const { return response_info_.original_response_time; } diff --git a/naiveproxy/src/net/url_request/url_request_context.cc b/naiveproxy/src/net/url_request/url_request_context.cc index d7a3e72d2e..5f459fd27e 100644 --- a/naiveproxy/src/net/url_request/url_request_context.cc +++ b/naiveproxy/src/net/url_request/url_request_context.cc @@ -95,6 +95,14 @@ URLRequestContext::~URLRequestContext() { DCHECK(host_resolver()); host_resolver()->OnShutdown(); +#if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) + if (device_bound_session_service_) { + // The SessionService may have pending URLRequests that use this + // context. + device_bound_session_service_.reset(); + } +#endif // BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) + AssertNoURLRequests(); } 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 4ac56ba267..8600847ba8 100644 --- a/naiveproxy/src/net/url_request/url_request_context_builder.cc +++ b/naiveproxy/src/net/url_request/url_request_context_builder.cc @@ -20,6 +20,7 @@ #include "base/task/thread_pool.h" #include "base/types/pass_key.h" #include "build/build_config.h" +#include "build/buildflag.h" #include "net/base/cache_type.h" #include "net/base/features.h" #include "net/base/net_errors.h" @@ -30,6 +31,7 @@ #include "net/cert/multi_log_ct_verifier.h" #include "net/cert/sct_auditing_delegate.h" #include "net/cookies/cookie_monster.h" +#include "net/disk_cache/buildflags.h" #include "net/dns/context_host_resolver.h" #include "net/dns/host_resolver.h" #include "net/dns/host_resolver_manager.h" @@ -580,14 +582,21 @@ std::unique_ptr URLRequestContextBuilder::Build() { break; case HttpCacheParams::IN_MEMORY: NOTREACHED(); +#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND) + case HttpCacheParams::DISK_EXPERIMENTAL_SQL: + backend_type = CACHE_BACKEND_EXPERIMENTAL_SQL; +#endif // ENABLE_DISK_CACHE_SQL_BACKEND } http_cache_backend = std::make_unique( DISK_CACHE, backend_type, http_cache_params_.file_operations_factory, http_cache_params_.path, http_cache_params_.max_size, http_cache_params_.reset_cache); - if (base::FeatureList::IsEnabled(features::kHttpCacheNoVarySearch)) { + if (base::FeatureList::IsEnabled(features::kHttpCacheNoVarySearch) && + features::kHttpCacheNoVarySearchPersistenceEnabled.Get() && + !http_cache_params_.no_vary_search_path.empty()) { + CHECK(!http_cache_params_.path.empty()); file_operations = NoVarySearchCacheStorageFileOperations::Create( - http_cache_params_.path); + http_cache_params_.no_vary_search_path, http_cache_params_.path); } } else { http_cache_backend = 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 7a9022b3d7..b9a77dcaa3 100644 --- a/naiveproxy/src/net/url_request/url_request_context_builder.h +++ b/naiveproxy/src/net/url_request/url_request_context_builder.h @@ -36,6 +36,7 @@ #include "net/base/network_delegate.h" #include "net/base/network_handle.h" #include "net/base/proxy_delegate.h" +#include "net/disk_cache/buildflags.h" #include "net/disk_cache/disk_cache.h" #include "net/dns/host_resolver.h" #include "net/dns/stale_host_resolver.h" @@ -109,6 +110,11 @@ class NET_EXPORT URLRequestContextBuilder { DISK_BLOCKFILE, // Disk cache using "simple" backend (SimpleBackendImpl). DISK_SIMPLE, +#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND) + // Disk cache using "sql" backend (SqlBackendImpl). + // This is still under experiment. + DISK_EXPERIMENTAL_SQL, +#endif // ENABLE_DISK_CACHE_SQL_BACKEND }; HttpCacheParams(); @@ -127,6 +133,9 @@ class NET_EXPORT URLRequestContextBuilder { // The cache path (when type is DISK). base::FilePath path; + // The path for persisting the NoVarySearchCache. + base::FilePath no_vary_search_path; + // A factory to broker file operations. This is needed for network process // sandboxing in some platforms. scoped_refptr diff --git a/naiveproxy/src/net/url_request/url_request_error_job.cc b/naiveproxy/src/net/url_request/url_request_error_job.cc index d22bd5d903..6d9a7d4394 100644 --- a/naiveproxy/src/net/url_request/url_request_error_job.cc +++ b/naiveproxy/src/net/url_request/url_request_error_job.cc @@ -8,19 +8,32 @@ #include "base/functional/bind.h" #include "base/location.h" #include "base/task/single_thread_task_runner.h" +#include "net/base/features.h" #include "net/base/net_errors.h" +#include "net/base/task/task_runner.h" namespace net { +namespace { +const scoped_refptr& TaskRunner( + net::RequestPriority priority) { + if (features::kNetTaskSchedulerURLRequestErrorJob.Get()) { + return net::GetTaskRunner(priority); + } + return base::SingleThreadTaskRunner::GetCurrentDefault(); +} + +} // namespace + URLRequestErrorJob::URLRequestErrorJob(URLRequest* request, int error) : URLRequestJob(request), error_(error) {} URLRequestErrorJob::~URLRequestErrorJob() = default; void URLRequestErrorJob::Start() { - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::BindOnce(&URLRequestErrorJob::StartAsync, - weak_factory_.GetWeakPtr())); + TaskRunner(request_->priority()) + ->PostTask(FROM_HERE, base::BindOnce(&URLRequestErrorJob::StartAsync, + weak_factory_.GetWeakPtr())); } void URLRequestErrorJob::Kill() { 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 4126605576..f25e19b68c 100644 --- a/naiveproxy/src/net/url_request/url_request_http_job.cc +++ b/naiveproxy/src/net/url_request/url_request_http_job.cc @@ -33,10 +33,12 @@ #include "base/strings/stringprintf.h" #include "base/task/single_thread_task_runner.h" #include "base/time/time.h" +#include "base/trace_event/trace_event.h" #include "base/types/optional_util.h" #include "base/values.h" #include "build/build_config.h" #include "net/base/features.h" +#include "net/base/hash_value.h" #include "net/base/host_port_pair.h" #include "net/base/http_user_agent_settings.h" #include "net/base/load_flags.h" @@ -47,8 +49,8 @@ #include "net/base/privacy_mode.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "net/base/schemeful_site.h" +#include "net/base/task/task_runner.h" #include "net/base/trace_constants.h" -#include "net/base/tracing.h" #include "net/base/url_util.h" #include "net/cert/cert_status_flags.h" #include "net/cert/ct_policy_status.h" @@ -189,7 +191,7 @@ base::Value::Dict CookieInclusionStatusNetLogParams( // which is expected to be ordered with the leaf cert first and the root cert // last. This complements the per-verification histogram // Net.Certificate.TrustAnchor.Verify -void LogTrustAnchor(const HashValueVector& spki_hashes) { +void LogTrustAnchor(const std::vector& spki_hashes) { // Don't record metrics if there are no hashes; this is true if the HTTP // load did not come from an active network connection, such as the disk // cache or a synthesized response. @@ -355,6 +357,14 @@ bool ClearSiteDataHeaderContainsCookiesOrWildcard( return false; } +const scoped_refptr& TaskRunner( + net::RequestPriority priority) { + if (features::kNetTaskSchedulerURLRequestHttpJob.Get()) { + return net::GetTaskRunner(priority); + } + return base::SingleThreadTaskRunner::GetCurrentDefault(); +} + } // namespace std::unique_ptr URLRequestHttpJob::Create(URLRequest* request) { @@ -699,7 +709,7 @@ void URLRequestHttpJob::MaybeStartTransactionInternal(int result) { request_->net_log().AddEventWithStringParams(NetLogEventType::CANCELLED, "source", "delegate"); // Don't call back synchronously to the delegate. - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + TaskRunner(priority_)->PostTask( FROM_HERE, base::BindOnce(&URLRequestHttpJob::NotifyStartError, weak_factory_.GetWeakPtr(), result)); } @@ -776,7 +786,7 @@ void URLRequestHttpJob::StartTransactionInternal() { // The transaction started synchronously, but we need to notify the // URLRequest delegate via the message loop. - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + TaskRunner(priority_)->PostTask( FROM_HERE, base::BindOnce(&URLRequestHttpJob::OnStartCompleted, weak_factory_.GetWeakPtr(), rv)); } @@ -1702,7 +1712,7 @@ void URLRequestHttpJob::CancelAuth() { // // Have to do this via PostTask to avoid re-entrantly calling into the // consumer. - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + TaskRunner(priority_)->PostTask( FROM_HERE, base::BindOnce(&URLRequestHttpJob::NotifyFinalHeadersReceived, weak_factory_.GetWeakPtr())); } @@ -1727,7 +1737,7 @@ void URLRequestHttpJob::ContinueWithCertificate( // The transaction started synchronously, but we need to notify the // URLRequest delegate via the message loop. - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + TaskRunner(priority_)->PostTask( FROM_HERE, base::BindOnce(&URLRequestHttpJob::OnStartCompleted, weak_factory_.GetWeakPtr(), rv)); } @@ -1750,7 +1760,7 @@ void URLRequestHttpJob::ContinueDespiteLastError() { // The transaction started synchronously, but we need to notify the // URLRequest delegate via the message loop. - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + TaskRunner(priority_)->PostTask( FROM_HERE, base::BindOnce(&URLRequestHttpJob::OnStartCompleted, weak_factory_.GetWeakPtr(), rv)); } diff --git a/naiveproxy/src/net/url_request/url_request_job.cc b/naiveproxy/src/net/url_request/url_request_job.cc index 8bdef06e92..ff36f3719d 100644 --- a/naiveproxy/src/net/url_request/url_request_job.cc +++ b/naiveproxy/src/net/url_request/url_request_job.cc @@ -24,6 +24,7 @@ #include "net/base/network_delegate.h" #include "net/base/proxy_chain.h" #include "net/base/schemeful_site.h" +#include "net/base/task/task_runner.h" #include "net/cert/x509_certificate.h" #include "net/cookies/cookie_setting_override.h" #include "net/cookies/cookie_util.h" @@ -50,6 +51,14 @@ base::Value::Dict SourceStreamSetParams(SourceStream* source_stream) { return event_params; } +const scoped_refptr& TaskRunner( + net::RequestPriority priority) { + if (features::kNetTaskSchedulerURLRequestJob.Get()) { + return net::GetTaskRunner(priority); + } + return base::SingleThreadTaskRunner::GetCurrentDefault(); +} + } // namespace // Each SourceStreams own the previous SourceStream in the chain, but the @@ -468,7 +477,8 @@ void URLRequestJob::NotifyHeadersComplete() { RedirectInfo redirect_info = RedirectInfo::ComputeRedirectInfo( request_->method(), request_->url(), request_->site_for_cookies(), request_->first_party_url_policy(), request_->referrer_policy(), - request_->referrer(), http_status_code, new_location, + request_->referrer(), request_->initiator(), http_status_code, + new_location, net::RedirectUtil::GetReferrerPolicyHeader( request_->response_headers()), insecure_scheme_was_upgraded, CopyFragmentOnRedirect(new_location)); @@ -591,9 +601,9 @@ void URLRequestJob::OnDone(int net_error, bool notify_done) { if (notify_done) { // Complete this notification later. This prevents us from re-entering the // delegate if we're done because of a synchronous call. - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, - base::BindOnce(&URLRequestJob::NotifyDone, weak_factory_.GetWeakPtr())); + TaskRunner(request_->priority()) + ->PostTask(FROM_HERE, base::BindOnce(&URLRequestJob::NotifyDone, + weak_factory_.GetWeakPtr())); } } diff --git a/naiveproxy/src/net/url_request/url_request_redirect_job.cc b/naiveproxy/src/net/url_request/url_request_redirect_job.cc index 666aed4861..270cbfcf40 100644 --- a/naiveproxy/src/net/url_request/url_request_redirect_job.cc +++ b/naiveproxy/src/net/url_request/url_request_redirect_job.cc @@ -13,8 +13,10 @@ #include "base/strings/stringprintf.h" #include "base/task/single_thread_task_runner.h" #include "base/values.h" +#include "net/base/features.h" #include "net/base/load_timing_info.h" #include "net/base/net_errors.h" +#include "net/base/task/task_runner.h" #include "net/http/http_log_util.h" #include "net/http/http_raw_request_headers.h" #include "net/http/http_response_headers.h" @@ -27,6 +29,16 @@ namespace net { +namespace { +const scoped_refptr& TaskRunner( + net::RequestPriority priority) { + if (features::kNetTaskSchedulerURLRequestRedirectJob.Get()) { + return net::GetTaskRunner(priority); + } + return base::SingleThreadTaskRunner::GetCurrentDefault(); +} +} // namespace + URLRequestRedirectJob::URLRequestRedirectJob( URLRequest* request, const GURL& redirect_destination, @@ -66,9 +78,9 @@ void URLRequestRedirectJob::GetLoadTimingInfo( void URLRequestRedirectJob::Start() { request()->net_log().AddEventWithStringParams( NetLogEventType::URL_REQUEST_REDIRECT_JOB, "reason", redirect_reason_); - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::BindOnce(&URLRequestRedirectJob::StartAsync, - weak_factory_.GetWeakPtr())); + TaskRunner(request_->priority()) + ->PostTask(FROM_HERE, base::BindOnce(&URLRequestRedirectJob::StartAsync, + weak_factory_.GetWeakPtr())); } void URLRequestRedirectJob::Kill() { diff --git a/naiveproxy/src/net/url_request/url_request_test_job.cc b/naiveproxy/src/net/url_request/url_request_test_job.cc index 8c3918e6c0..52c0547d50 100644 --- a/naiveproxy/src/net/url_request/url_request_test_job.cc +++ b/naiveproxy/src/net/url_request/url_request_test_job.cc @@ -10,8 +10,8 @@ #include "base/compiler_specific.h" #include "base/functional/bind.h" -#include "base/lazy_instance.h" #include "base/location.h" +#include "base/no_destructor.h" #include "base/numerics/safe_conversions.h" #include "base/strings/string_util.h" #include "base/task/single_thread_task_runner.h" @@ -26,8 +26,11 @@ namespace net { namespace { typedef std::list URLRequestJobList; -base::LazyInstance::Leaky - g_pending_jobs = LAZY_INSTANCE_INITIALIZER; + +URLRequestJobList& GetPendingJobs() { + static base::NoDestructor pending_jobs; + return *pending_jobs; +} } // namespace @@ -143,7 +146,7 @@ URLRequestTestJob::URLRequestTestJob(URLRequest* request, response_headers_length_(response_headers.size()) {} URLRequestTestJob::~URLRequestTestJob() { - std::erase(g_pending_jobs.Get(), this); + std::erase(GetPendingJobs(), this); } bool URLRequestTestJob::GetMimeType(std::string* mime_type) const { @@ -278,7 +281,7 @@ void URLRequestTestJob::Kill() { stage_ = DONE; URLRequestJob::Kill(); weak_factory_.InvalidateWeakPtrs(); - std::erase(g_pending_jobs.Get(), this); + std::erase(GetPendingJobs(), this); } void URLRequestTestJob::ProcessNextOperation() { @@ -327,16 +330,17 @@ void URLRequestTestJob::AdvanceJob() { weak_factory_.GetWeakPtr())); return; } - g_pending_jobs.Get().push_back(this); + GetPendingJobs().push_back(this); } // static bool URLRequestTestJob::ProcessOnePendingMessage() { - if (g_pending_jobs.Get().empty()) + if (GetPendingJobs().empty()) { return false; + } - URLRequestTestJob* next_job(g_pending_jobs.Get().front()); - g_pending_jobs.Get().pop_front(); + URLRequestTestJob* next_job(GetPendingJobs().front()); + GetPendingJobs().pop_front(); DCHECK(!next_job->auto_advance()); // auto_advance jobs should be in this q next_job->ProcessNextOperation(); diff --git a/naiveproxy/src/net/websockets/DIR_METADATA b/naiveproxy/src/net/websockets/DIR_METADATA index 8f6200917d..1138724cb4 100644 --- a/naiveproxy/src/net/websockets/DIR_METADATA +++ b/naiveproxy/src/net/websockets/DIR_METADATA @@ -1,7 +1,7 @@ monorail: { component: "Blink>Network>WebSockets" } -team_email: "blink-network-dev@chromium.org" +team_email: "net-dev@chromium.org" buganizer_public: { component_id: 1456696 } diff --git a/naiveproxy/src/net/websockets/websocket_basic_stream_adapters.cc b/naiveproxy/src/net/websockets/websocket_basic_stream_adapters.cc index 847b0c04a8..649c25d5e2 100644 --- a/naiveproxy/src/net/websockets/websocket_basic_stream_adapters.cc +++ b/naiveproxy/src/net/websockets/websocket_basic_stream_adapters.cc @@ -224,7 +224,7 @@ NetLogSource WebSocketSpdyStreamAdapter::source_dependency() const { int WebSocketSpdyStreamAdapter::CopySavedReadDataIntoBuffer() { DCHECK(read_buffer_); DCHECK(read_length_); - int rv = read_data_.Dequeue(read_buffer_->data(), read_length_); + int rv = read_data_.Dequeue(read_buffer_->first(read_length_)); read_buffer_ = nullptr; read_length_ = 0u; diff --git a/naiveproxy/src/net/websockets/websocket_channel.cc b/naiveproxy/src/net/websockets/websocket_channel.cc index defb320b2b..4386152625 100644 --- a/naiveproxy/src/net/websockets/websocket_channel.cc +++ b/naiveproxy/src/net/websockets/websocket_channel.cc @@ -427,13 +427,8 @@ void WebSocketChannel::SendAddChannelRequestWithSuppliedCallback( NetworkTrafficAnnotationTag traffic_annotation, WebSocketStreamRequestCreationCallback callback) { DCHECK_EQ(FRESHLY_CONSTRUCTED, state_); - if (!socket_url.SchemeIsWSOrWSS()) { - // TODO(ricea): Kill the renderer (this error should have been caught by - // Javascript). - event_interface_->OnFailChannel("Invalid scheme", ERR_FAILED, std::nullopt); - // |this| is deleted here. - return; - } + CHECK(socket_url.SchemeIsWSOrWSS()); + socket_url_ = socket_url; auto connect_delegate = std::make_unique(this); stream_request_ = std::move(callback).Run( diff --git a/naiveproxy/src/net/websockets/websocket_test_util.cc b/naiveproxy/src/net/websockets/websocket_test_util.cc index 0b0d159081..7156400392 100644 --- a/naiveproxy/src/net/websockets/websocket_test_util.cc +++ b/naiveproxy/src/net/websockets/websocket_test_util.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 "net/websockets/websocket_test_util.h" #include @@ -212,22 +207,19 @@ void WebSocketMockClientSocketFactoryMaker::SetExpectations( detail_->expect_written = expect_written; detail_->return_to_read = return_to_read; int sequence = 0; - detail_->write = MockWrite(SYNCHRONOUS, - detail_->expect_written.data(), - detail_->expect_written.size(), - sequence++); + detail_->write = MockWrite(SYNCHRONOUS, sequence++, detail_->expect_written); // HttpStreamParser reads 4KB at a time. We need to take this implementation // detail into account if |return_to_read| is big enough. - for (size_t place = 0; place < detail_->return_to_read.size(); + std::string_view to_read(detail_->return_to_read); + for (size_t place = 0; place < to_read.size(); place += kHttpStreamParserBufferSize) { - detail_->reads.emplace_back(SYNCHRONOUS, - detail_->return_to_read.data() + place, - std::min(detail_->return_to_read.size() - place, - kHttpStreamParserBufferSize), - sequence++); + detail_->reads.emplace_back( + SYNCHRONOUS, sequence++, + to_read.substr(place, std::min(to_read.size() - place, + kHttpStreamParserBufferSize))); } auto socket_data = std::make_unique( - detail_->reads, base::span(&detail_->write, 1u)); + detail_->reads, base::span_from_ref(detail_->write)); socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); AddRawExpectations(std::move(socket_data)); } diff --git a/naiveproxy/src/third_party/abseil-cpp/BUILD.gn b/naiveproxy/src/third_party/abseil-cpp/BUILD.gn index 896b9dea0e..f227c8344d 100644 --- a/naiveproxy/src/third_party/abseil-cpp/BUILD.gn +++ b/naiveproxy/src/third_party/abseil-cpp/BUILD.gn @@ -7,7 +7,6 @@ # without these options will be part of the same program. import("//build/config/c++/c++.gni") -import("//build/config/nacl/config.gni") import("//build/config/sanitizers/sanitizers.gni") import("//build/toolchain/toolchain.gni") import("//build_overrides/build.gni") @@ -17,9 +16,6 @@ config("absl_component_build") { defines = [ "ABSL_CONSUME_DLL" ] } -assert(!is_nacl || is_nacl_saigo, - "base must not be built in most nacl toolchains") - component("absl") { public_deps = [ ":absl_component_deps" ] if (is_component_build) { @@ -132,13 +128,6 @@ group("absl_component_deps") { public_deps += [ ":absl_full_deps" ] } - # The following dependencies currently don't build with NaCl. - # TODO(https://crbug.com/1114625): Fix build errors and remove this section. - if (is_nacl) { - public_deps -= - [ "//third_party/abseil-cpp/absl/debugging:failure_signal_handler" ] - } - visibility = [ ":absl" ] } @@ -229,27 +218,7 @@ config("absl_default_cflags_cc") { "-Wnull-conversion", "-Wobjc-literal-conversion", "-Wstring-conversion", - ] - if (!is_nacl) { - cflags_cc += [ "-Wbitfield-enum-conversion" ] - } - } -} - -config("absl_test_cflags_cc") { - cflags_cc = [] - if (is_clang || !is_win) { - cflags_cc += [ - "-Wno-conversion-null", - "-Wno-missing-declarations", - "-Wno-unused-function", - "-Wno-unused-parameter", - "-Wno-unused-private-field", - ] - } - if (is_win) { - cflags_cc += [ - "/wd4101", # unreferenced local variable + "-Wbitfield-enum-conversion", ] } } diff --git a/naiveproxy/src/third_party/abseil-cpp/CMake/AbseilDll.cmake b/naiveproxy/src/third_party/abseil-cpp/CMake/AbseilDll.cmake index 6a237cc31d..be5aaa9c63 100644 --- a/naiveproxy/src/third_party/abseil-cpp/CMake/AbseilDll.cmake +++ b/naiveproxy/src/third_party/abseil-cpp/CMake/AbseilDll.cmake @@ -214,10 +214,14 @@ set(ABSL_INTERNAL_DLL_FILES "numeric/int128.h" "numeric/internal/bits.h" "numeric/internal/representation.h" + "profiling/hashtable.cc" + "profiling/hashtable.h" "profiling/internal/exponential_biased.cc" "profiling/internal/exponential_biased.h" "profiling/internal/periodic_sampler.cc" "profiling/internal/periodic_sampler.h" + "profiling/internal/profile_builder.cc" + "profiling/internal/profile_builder.h" "profiling/internal/sample_recorder.h" "random/bernoulli_distribution.h" "random/beta_distribution.h" @@ -715,8 +719,10 @@ int main() { return 0; } if(ABSL_INTERNAL_AT_LEAST_CXX20) set(ABSL_INTERNAL_CXX_STD_FEATURE cxx_std_20) -else() +elseif(ABSL_INTERNAL_AT_LEAST_CXX17) set(ABSL_INTERNAL_CXX_STD_FEATURE cxx_std_17) +else() + message(FATAL_ERROR "The compiler defaults to or is configured for C++ < 17. C++ >= 17 is required and Abseil and all libraries that use Abseil must use the same C++ language standard") endif() function(absl_internal_dll_contains) diff --git a/naiveproxy/src/third_party/abseil-cpp/OWNERS b/naiveproxy/src/third_party/abseil-cpp/OWNERS index 78260873a4..c93c059797 100644 --- a/naiveproxy/src/third_party/abseil-cpp/OWNERS +++ b/naiveproxy/src/third_party/abseil-cpp/OWNERS @@ -2,4 +2,4 @@ danilchap@chromium.org mbonadei@chromium.org # For .def files updates: -hans@chromium.org +per-file *.def=file://tools/clang/scripts/OWNERS diff --git a/naiveproxy/src/third_party/abseil-cpp/README.chromium b/naiveproxy/src/third_party/abseil-cpp/README.chromium index 89ecbc9280..e3aa983b7c 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: 23d40c5dbdef4ffb8d53860ff9e6d81c57476eab +Revision: 56945519b5d17dcec0982ac6cdf4b6420f03c9c3 Update Mechanism: Manual 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 0ec8b921e7..0446a0cea3 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/algorithm/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/algorithm/BUILD.bazel @@ -14,6 +14,8 @@ # limitations under the License. # +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", 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 4e73701fbf..9f4a8a48b1 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/base/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/base/BUILD.bazel @@ -14,6 +14,9 @@ # limitations under the License. # +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc b/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc index 158b60982f..a5bd71da6d 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc @@ -19,6 +19,9 @@ #include "absl/base/internal/low_level_alloc.h" +#include + +#include #include #include "absl/base/call_once.h" @@ -219,6 +222,32 @@ struct LowLevelAlloc::Arena { uint32_t random ABSL_GUARDED_BY(mu); }; +// --------------------------------------------------------------- +// An async-signal-safe arena for LowLevelAlloc +static std::atomic g_sig_safe_arena; + +base_internal::LowLevelAlloc::Arena *SigSafeArena() { + return g_sig_safe_arena.load(std::memory_order_acquire); +} + +void InitSigSafeArena() { + if (SigSafeArena() == nullptr) { + uint32_t flags = 0; +#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING + flags |= base_internal::LowLevelAlloc::kAsyncSignalSafe; +#endif + base_internal::LowLevelAlloc::Arena *new_arena = + base_internal::LowLevelAlloc::NewArena(flags); + base_internal::LowLevelAlloc::Arena *old_value = nullptr; + if (!g_sig_safe_arena.compare_exchange_strong(old_value, new_arena, + std::memory_order_release, + std::memory_order_relaxed)) { + // We lost a race to allocate an arena; deallocate. + base_internal::LowLevelAlloc::DeleteArena(new_arena); + } + } +} + namespace { // Static storage space for the lazily-constructed, default global arena // instances. We require this space because the whole point of LowLevelAlloc @@ -289,11 +318,11 @@ class ABSL_SCOPED_LOCKABLE ArenaLock { mask_valid_ = pthread_sigmask(SIG_BLOCK, &all, &mask_) == 0; } #endif - arena_->mu.Lock(); + arena_->mu.lock(); } ~ArenaLock() { ABSL_RAW_CHECK(left_, "haven't left Arena region"); } void Leave() ABSL_UNLOCK_FUNCTION() { - arena_->mu.Unlock(); + arena_->mu.unlock(); #ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING if (mask_valid_) { const int err = pthread_sigmask(SIG_SETMASK, &mask_, nullptr); @@ -544,7 +573,7 @@ static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) { } // we unlock before mmap() both because mmap() may call a callback hook, // and because it may be slow. - arena->mu.Unlock(); + arena->mu.unlock(); // mmap generous 64K chunks to decrease // the chances/impact of fragmentation: size_t new_pages_size = RoundUp(req_rnd, arena->pagesize * 16); @@ -583,7 +612,7 @@ static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) { #endif #endif // __linux__ #endif // _WIN32 - arena->mu.Lock(); + arena->mu.lock(); s = reinterpret_cast(new_pages); s->header.size = new_pages_size; // Pretend the block is allocated; call AddToFreelist() to free it. diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/low_level_alloc.h b/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/low_level_alloc.h index c2f1f25d8e..23218dd5a6 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/low_level_alloc.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/low_level_alloc.h @@ -120,6 +120,12 @@ class LowLevelAlloc { LowLevelAlloc(); // no instances }; +// Returns a global async-signal-safe arena for LowLevelAlloc. +LowLevelAlloc::Arena *SigSafeArena(); + +// Ensures the global async-signal-safe arena for LowLevelAlloc is initialized. +void InitSigSafeArena(); + } // namespace base_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/spinlock.cc b/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/spinlock.cc index 430f775bdf..4168b8b728 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/spinlock.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/spinlock.cc @@ -16,15 +16,18 @@ #include #include +#include #include #include "absl/base/attributes.h" +#include "absl/base/call_once.h" #include "absl/base/config.h" #include "absl/base/internal/atomic_hook.h" #include "absl/base/internal/cycleclock.h" +#include "absl/base/internal/scheduling_mode.h" #include "absl/base/internal/spinlock_wait.h" #include "absl/base/internal/sysinfo.h" /* For NumCPUs() */ -#include "absl/base/call_once.h" +#include "absl/base/internal/tsan_mutex_interface.h" // Description of lock-word: // 31..00: [............................3][2][1][0] @@ -58,7 +61,7 @@ namespace absl { ABSL_NAMESPACE_BEGIN namespace base_internal { -ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static base_internal::AtomicHook submit_profile_data; @@ -67,12 +70,6 @@ void RegisterSpinLockProfiler(void (*fn)(const void *contendedlock, submit_profile_data.Store(fn); } -// Uncommon constructors. -SpinLock::SpinLock(base_internal::SchedulingMode mode) - : lockword_(IsCooperative(mode) ? kSpinLockCooperative : 0) { - ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static); -} - // Monitor the lock to see if its value changes within some time period // (adaptive_spin_count loop iterations). The last value read from the lock // is returned from the method. @@ -81,9 +78,8 @@ uint32_t SpinLock::SpinLoop() { // adaptive_spin_count here. ABSL_CONST_INIT static absl::once_flag init_adaptive_spin_count; ABSL_CONST_INIT static int adaptive_spin_count = 0; - base_internal::LowLevelCallOnce(&init_adaptive_spin_count, []() { - adaptive_spin_count = base_internal::NumCPUs() > 1 ? 1000 : 1; - }); + LowLevelCallOnce(&init_adaptive_spin_count, + []() { adaptive_spin_count = NumCPUs() > 1 ? 1000 : 1; }); int c = adaptive_spin_count; uint32_t lock_value; @@ -100,11 +96,11 @@ void SpinLock::SlowLock() { return; } - base_internal::SchedulingMode scheduling_mode; + SchedulingMode scheduling_mode; if ((lock_value & kSpinLockCooperative) != 0) { - scheduling_mode = base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL; + scheduling_mode = SCHEDULE_COOPERATIVE_AND_KERNEL; } else { - scheduling_mode = base_internal::SCHEDULE_KERNEL_ONLY; + scheduling_mode = SCHEDULE_KERNEL_ONLY; } // The lock was not obtained initially, so this thread needs to wait for @@ -134,7 +130,7 @@ void SpinLock::SlowLock() { // new lock state will be the number of cycles this thread waited if // this thread obtains the lock. lock_value = TryLockInternal(lock_value, wait_cycles); - continue; // Skip the delay at the end of the loop. + continue; // Skip the delay at the end of the loop. } else if ((lock_value & kWaitTimeMask) == 0) { // The lock is still held, without a waiter being marked, but something // else about the lock word changed, causing our CAS to fail. For @@ -150,8 +146,8 @@ void SpinLock::SlowLock() { // synchronization there to avoid false positives. ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0); // Wait for an OS specific delay. - base_internal::SpinLockDelay(&lockword_, lock_value, ++lock_wait_call_count, - scheduling_mode); + SpinLockDelay(&lockword_, lock_value, ++lock_wait_call_count, + scheduling_mode); ABSL_TSAN_MUTEX_POST_DIVERT(this, 0); // Spin again after returning from the wait routine to give this thread // some chance of obtaining the lock. @@ -162,8 +158,8 @@ void SpinLock::SlowLock() { } void SpinLock::SlowUnlock(uint32_t lock_value) { - base_internal::SpinLockWake(&lockword_, - false); // wake waiter if necessary + SpinLockWake(&lockword_, + false); // wake waiter if necessary // If our acquisition was contended, collect contentionz profile info. We // reserve a unitary wait time to represent that a waiter exists without our diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/spinlock.h b/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/spinlock.h index 2a10896976..16fe93e54c 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/spinlock.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/spinlock.h @@ -19,7 +19,7 @@ // - for use by Abseil internal code that Mutex itself depends on // - for async signal safety (see below) -// SpinLock with a base_internal::SchedulingMode::SCHEDULE_KERNEL_ONLY is async +// SpinLock with a SchedulingMode::SCHEDULE_KERNEL_ONLY is async // signal safe. If a spinlock is used within a signal handler, all code that // acquires the lock must ensure that the signal cannot arrive while they are // holding the lock. Typically, this is done by blocking the signal. @@ -31,14 +31,16 @@ #include #include +#include #include "absl/base/attributes.h" +#include "absl/base/config.h" #include "absl/base/const_init.h" -#include "absl/base/dynamic_annotations.h" #include "absl/base/internal/low_level_scheduling.h" #include "absl/base/internal/raw_logging.h" #include "absl/base/internal/scheduling_mode.h" #include "absl/base/internal/tsan_mutex_interface.h" +#include "absl/base/macros.h" #include "absl/base/thread_annotations.h" namespace tcmalloc { @@ -55,17 +57,31 @@ namespace base_internal { class ABSL_LOCKABLE ABSL_ATTRIBUTE_WARN_UNUSED SpinLock { public: - SpinLock() : lockword_(kSpinLockCooperative) { - ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static); - } + constexpr SpinLock() : lockword_(kSpinLockCooperative) { RegisterWithTsan(); } // Constructors that allow non-cooperative spinlocks to be created for use // inside thread schedulers. Normal clients should not use these. - explicit SpinLock(base_internal::SchedulingMode mode); + constexpr explicit SpinLock(SchedulingMode mode) + : lockword_(IsCooperative(mode) ? kSpinLockCooperative : 0) { + RegisterWithTsan(); + } + +#if ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(_WIN32) + // Constructor to inline users of the default scheduling mode. + // + // This only needs to exists for inliner runs, but doesn't work correctly in + // clang+windows builds, likely due to mangling differences. + ABSL_DEPRECATE_AND_INLINE() + constexpr explicit SpinLock(SchedulingMode mode) + __attribute__((enable_if(mode == SCHEDULE_COOPERATIVE_AND_KERNEL, + "Cooperative use default constructor"))) + : SpinLock() {} +#endif // Constructor for global SpinLock instances. See absl/base/const_init.h. - constexpr SpinLock(absl::ConstInitType, base_internal::SchedulingMode mode) - : lockword_(IsCooperative(mode) ? kSpinLockCooperative : 0) {} + ABSL_DEPRECATE_AND_INLINE() + constexpr SpinLock(absl::ConstInitType, SchedulingMode mode) + : SpinLock(mode) {} // For global SpinLock instances prefer trivial destructor when possible. // Default but non-trivial destructor in some build configurations causes an @@ -77,7 +93,7 @@ class ABSL_LOCKABLE ABSL_ATTRIBUTE_WARN_UNUSED SpinLock { #endif // Acquire this SpinLock. - inline void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() { + inline void lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() { ABSL_TSAN_MUTEX_PRE_LOCK(this, 0); if (!TryLockImpl()) { SlowLock(); @@ -85,11 +101,13 @@ class ABSL_LOCKABLE ABSL_ATTRIBUTE_WARN_UNUSED SpinLock { ABSL_TSAN_MUTEX_POST_LOCK(this, 0, 0); } + inline void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() { return lock(); } + // Try to acquire this SpinLock without blocking and return true if the // acquisition was successful. If the lock was not acquired, false is - // returned. If this SpinLock is free at the time of the call, TryLock - // will return true with high probability. - [[nodiscard]] inline bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) { + // returned. If this SpinLock is free at the time of the call, try_lock will + // return true with high probability. + [[nodiscard]] inline bool try_lock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) { ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_try_lock); bool res = TryLockImpl(); ABSL_TSAN_MUTEX_POST_LOCK( @@ -98,15 +116,19 @@ class ABSL_LOCKABLE ABSL_ATTRIBUTE_WARN_UNUSED SpinLock { return res; } + [[nodiscard]] inline bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) { + return try_lock(); + } + // Release this SpinLock, which must be held by the calling thread. - inline void Unlock() ABSL_UNLOCK_FUNCTION() { + inline void unlock() ABSL_UNLOCK_FUNCTION() { ABSL_TSAN_MUTEX_PRE_UNLOCK(this, 0); uint32_t lock_value = lockword_.load(std::memory_order_relaxed); lock_value = lockword_.exchange(lock_value & kSpinLockCooperative, std::memory_order_release); if ((lock_value & kSpinLockDisabledScheduling) != 0) { - base_internal::SchedulingGuard::EnableRescheduling(true); + SchedulingGuard::EnableRescheduling(true); } if ((lock_value & kWaitTimeMask) != 0) { // Collect contentionz profile info, and speed the wakeup of any waiter. @@ -117,6 +139,8 @@ class ABSL_LOCKABLE ABSL_ATTRIBUTE_WARN_UNUSED SpinLock { ABSL_TSAN_MUTEX_POST_UNLOCK(this, 0); } + inline void Unlock() ABSL_UNLOCK_FUNCTION() { unlock(); } + // Determine if the lock is held. When the lock is held by the invoking // thread, true will always be returned. Intended to be used as // CHECK(lock.IsHeld()). @@ -175,9 +199,16 @@ class ABSL_LOCKABLE ABSL_ATTRIBUTE_WARN_UNUSED SpinLock { ~(kSpinLockHeld | kSpinLockCooperative | kSpinLockDisabledScheduling); // Returns true if the provided scheduling mode is cooperative. - static constexpr bool IsCooperative( - base_internal::SchedulingMode scheduling_mode) { - return scheduling_mode == base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL; + static constexpr bool IsCooperative(SchedulingMode scheduling_mode) { + return scheduling_mode == SCHEDULE_COOPERATIVE_AND_KERNEL; + } + + constexpr void RegisterWithTsan() { +#if ABSL_HAVE_BUILTIN(__builtin_is_constant_evaluated) + if (!__builtin_is_constant_evaluated()) { + ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static); + } +#endif } bool IsCooperative() const { @@ -206,9 +237,9 @@ class ABSL_SCOPED_LOCKABLE [[nodiscard]] SpinLockHolder { public: inline explicit SpinLockHolder(SpinLock* l) ABSL_EXCLUSIVE_LOCK_FUNCTION(l) : lock_(l) { - l->Lock(); + l->lock(); } - inline ~SpinLockHolder() ABSL_UNLOCK_FUNCTION() { lock_->Unlock(); } + inline ~SpinLockHolder() ABSL_UNLOCK_FUNCTION() { lock_->unlock(); } SpinLockHolder(const SpinLockHolder&) = delete; SpinLockHolder& operator=(const SpinLockHolder&) = delete; @@ -243,7 +274,7 @@ inline uint32_t SpinLock::TryLockInternal(uint32_t lock_value, if ((lock_value & kSpinLockCooperative) == 0) { // For non-cooperative locks we must make sure we mark ourselves as // non-reschedulable before we attempt to CompareAndSwap. - if (base_internal::SchedulingGuard::DisableRescheduling()) { + if (SchedulingGuard::DisableRescheduling()) { sched_disabled_bit = kSpinLockDisabledScheduling; } } @@ -252,7 +283,7 @@ inline uint32_t SpinLock::TryLockInternal(uint32_t lock_value, lock_value, kSpinLockHeld | lock_value | wait_cycles | sched_disabled_bit, std::memory_order_acquire, std::memory_order_relaxed)) { - base_internal::SchedulingGuard::EnableRescheduling(sched_disabled_bit != 0); + SchedulingGuard::EnableRescheduling(sched_disabled_bit != 0); } return lock_value; diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/spinlock_benchmark.cc b/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/spinlock_benchmark.cc index 1790d9678e..993cab6ff4 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/spinlock_benchmark.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/spinlock_benchmark.cc @@ -35,7 +35,7 @@ static void BM_TryLock(benchmark::State& state) { static absl::NoDestructor spinlock( scheduling_mode); for (auto _ : state) { - if (spinlock->TryLock()) spinlock->Unlock(); + if (spinlock->try_lock()) spinlock->unlock(); } } diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/base/spinlock_test_common.cc b/naiveproxy/src/third_party/abseil-cpp/absl/base/spinlock_test_common.cc index e9047158cb..56b09ec26d 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/base/spinlock_test_common.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/base/spinlock_test_common.cc @@ -18,6 +18,7 @@ #include #include +#include // NOLINT(build/c++11) #include #include // NOLINT(build/c++11) #include @@ -60,24 +61,41 @@ namespace { static constexpr size_t kArrayLength = 10; static uint32_t values[kArrayLength]; -ABSL_CONST_INIT static SpinLock static_cooperative_spinlock( - absl::kConstInit, base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL); +ABSL_CONST_INIT static SpinLock static_cooperative_spinlock; ABSL_CONST_INIT static SpinLock static_noncooperative_spinlock( - absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY); + base_internal::SCHEDULE_KERNEL_ONLY); // Simple integer hash function based on the public domain lookup2 hash. // http://burtleburtle.net/bob/c/lookup2.c static uint32_t Hash32(uint32_t a, uint32_t c) { uint32_t b = 0x9e3779b9UL; // The golden ratio; an arbitrary value. - a -= b; a -= c; a ^= (c >> 13); - b -= c; b -= a; b ^= (a << 8); - c -= a; c -= b; c ^= (b >> 13); - a -= b; a -= c; a ^= (c >> 12); - b -= c; b -= a; b ^= (a << 16); - c -= a; c -= b; c ^= (b >> 5); - a -= b; a -= c; a ^= (c >> 3); - b -= c; b -= a; b ^= (a << 10); - c -= a; c -= b; c ^= (b >> 15); + a -= b; + a -= c; + a ^= (c >> 13); + b -= c; + b -= a; + b ^= (a << 8); + c -= a; + c -= b; + c ^= (b >> 13); + a -= b; + a -= c; + a ^= (c >> 12); + b -= c; + b -= a; + b ^= (a << 16); + c -= a; + c -= b; + c ^= (b >> 5); + a -= b; + a -= c; + a ^= (c >> 3); + b -= c; + b -= a; + b ^= (a << 10); + c -= a; + c -= b; + c ^= (b >> 15); return c; } @@ -114,15 +132,13 @@ static_assert(std::is_trivially_destructible(), ""); TEST(SpinLock, StackNonCooperativeDisablesScheduling) { SpinLock spinlock(base_internal::SCHEDULE_KERNEL_ONLY); - spinlock.Lock(); + SpinLockHolder l(&spinlock); EXPECT_FALSE(base_internal::SchedulingGuard::ReschedulingIsAllowed()); - spinlock.Unlock(); } TEST(SpinLock, StaticNonCooperativeDisablesScheduling) { - static_noncooperative_spinlock.Lock(); + SpinLockHolder l(&static_noncooperative_spinlock); EXPECT_FALSE(base_internal::SchedulingGuard::ReschedulingIsAllowed()); - static_noncooperative_spinlock.Unlock(); } TEST(SpinLock, WaitCyclesEncoding) { @@ -134,7 +150,7 @@ TEST(SpinLock, WaitCyclesEncoding) { // We should be able to encode up to (1^kMaxCycleBits - 1) without clamping // but the lower kProfileTimestampShift will be dropped. const int kMaxCyclesShift = - 32 - kLockwordReservedShift + kProfileTimestampShift; + 32 - kLockwordReservedShift + kProfileTimestampShift; const int64_t kMaxCycles = (int64_t{1} << kMaxCyclesShift) - 1; // These bits should be zero after encoding. @@ -171,22 +187,22 @@ TEST(SpinLock, WaitCyclesEncoding) { SpinLockTest::DecodeWaitCycles(~kLockwordReservedMask)); // Check that we cannot produce kSpinLockSleeper during encoding. - int64_t sleeper_cycles = - kSpinLockSleeper << (kProfileTimestampShift - kLockwordReservedShift); + int64_t sleeper_cycles = kSpinLockSleeper + << (kProfileTimestampShift - kLockwordReservedShift); uint32_t sleeper_value = SpinLockTest::EncodeWaitCycles(start_time, start_time + sleeper_cycles); EXPECT_NE(sleeper_value, kSpinLockSleeper); // Test clamping uint32_t max_value = - SpinLockTest::EncodeWaitCycles(start_time, start_time + kMaxCycles); + SpinLockTest::EncodeWaitCycles(start_time, start_time + kMaxCycles); int64_t max_value_decoded = SpinLockTest::DecodeWaitCycles(max_value); int64_t expected_max_value_decoded = kMaxCycles & ~kProfileTimestampMask; EXPECT_EQ(expected_max_value_decoded, max_value_decoded); const int64_t step = (1 << kProfileTimestampShift); - uint32_t after_max_value = - SpinLockTest::EncodeWaitCycles(start_time, start_time + kMaxCycles + step); + uint32_t after_max_value = SpinLockTest::EncodeWaitCycles( + start_time, start_time + kMaxCycles + step); int64_t after_max_value_decoded = SpinLockTest::DecodeWaitCycles(after_max_value); EXPECT_EQ(expected_max_value_decoded, after_max_value_decoded); @@ -204,7 +220,7 @@ TEST(SpinLockWithThreads, StackSpinLock) { } TEST(SpinLockWithThreads, StackCooperativeSpinLock) { - SpinLock spinlock(base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL); + SpinLock spinlock; ThreadedTest(&spinlock); } @@ -255,8 +271,7 @@ TEST(SpinLockWithThreads, DoesNotDeadlock) { } }; - SpinLock stack_cooperative_spinlock( - base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL); + SpinLock stack_cooperative_spinlock; SpinLock stack_noncooperative_spinlock(base_internal::SCHEDULE_KERNEL_ONLY); Helper::DeadlockTest(&stack_cooperative_spinlock, base_internal::NumCPUs() * 2); @@ -272,13 +287,18 @@ TEST(SpinLockTest, IsCooperative) { SpinLock default_constructor; EXPECT_TRUE(SpinLockTest::IsCooperative(default_constructor)); - SpinLock cooperative(base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL); + SpinLock cooperative; EXPECT_TRUE(SpinLockTest::IsCooperative(cooperative)); SpinLock kernel_only(base_internal::SCHEDULE_KERNEL_ONLY); EXPECT_FALSE(SpinLockTest::IsCooperative(kernel_only)); } +TEST(SpinLockTest, ScopedLock) { + SpinLock s; + std::scoped_lock l(s); +} + } // namespace } // namespace base_internal ABSL_NAMESPACE_END diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/cleanup/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/cleanup/BUILD.bazel index d5797816fd..5475439250 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/cleanup/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/cleanup/BUILD.bazel @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", 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 66587729b5..68a9008791 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/container/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/container/BUILD.bazel @@ -14,6 +14,9 @@ # limitations under the License. # +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/hashtable_control_bytes.h b/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/hashtable_control_bytes.h index b6068504b2..0501e48d32 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/hashtable_control_bytes.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/hashtable_control_bytes.h @@ -91,11 +91,6 @@ class NonIterableBitMask { return container_internal::TrailingZeros(mask_) >> Shift; } - // Returns the index of the highest *abstract* bit set in `self`. - uint32_t HighestBitSet() const { - return static_cast((bit_width(mask_) - 1) >> Shift); - } - // Returns the number of trailing zero *abstract* bits. uint32_t TrailingZeros() const { return container_internal::TrailingZeros(mask_) >> Shift; @@ -333,13 +328,6 @@ struct GroupSse2Impl { _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(ctrl, special)))); } - // Returns the number of trailing empty or deleted elements in the group. - uint32_t CountLeadingEmptyOrDeleted() const { - auto special = _mm_set1_epi8(static_cast(ctrl_t::kSentinel)); - return TrailingZeros(static_cast( - _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl)) + 1)); - } - void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const { auto msbs = _mm_set1_epi8(static_cast(-128)); auto x126 = _mm_set1_epi8(126); @@ -424,19 +412,6 @@ struct GroupAArch64Impl { return NonIterableBitMaskType(mask); } - uint32_t CountLeadingEmptyOrDeleted() const { - uint64_t mask = - vget_lane_u64(vreinterpret_u64_u8(vcle_s8( - vdup_n_s8(static_cast(ctrl_t::kSentinel)), - vreinterpret_s8_u8(ctrl))), - 0); - // Similar to MaskEmptyorDeleted() but we invert the logic to invert the - // produced bitfield. We then count number of trailing zeros. - // Clang and GCC optimize countr_zero to rbit+clz without any check for 0, - // so we should be fine. - return static_cast(countr_zero(mask)) >> 3; - } - void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const { uint64_t mask = vget_lane_u64(vreinterpret_u64_u8(ctrl), 0); constexpr uint64_t slsbs = 0x0202020202020202ULL; @@ -503,14 +478,6 @@ struct GroupPortableImpl { return NonIterableBitMaskType((~ctrl | (ctrl << 7)) & kMsbs8Bytes); } - uint32_t CountLeadingEmptyOrDeleted() const { - // ctrl | ~(ctrl >> 7) will have the lowest bit set to zero for kEmpty and - // kDeleted. We lower all other bits and count number of trailing zeros. - constexpr uint64_t bits = 0x0101010101010101ULL; - return static_cast(countr_zero((ctrl | ~(ctrl >> 7)) & bits) >> - 3); - } - void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const { constexpr uint64_t lsbs = 0x0101010101010101ULL; auto x = ctrl & kMsbs8Bytes; diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.cc b/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.cc index c0fce8794d..965476a09a 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.cc @@ -94,8 +94,9 @@ void HashtablezInfo::PrepareForSampling(int64_t stride, // The inliner makes hardcoded skip_count difficult (especially when combined // with LTO). We use the ability to exclude stacks by regex when encoding // instead. - depth = absl::GetStackTrace(stack, HashtablezInfo::kMaxStackDepth, - /* skip_count= */ 0); + depth = static_cast( + absl::GetStackTrace(stack, HashtablezInfo::kMaxStackDepth, + /* skip_count= */ 0)); inline_element_size = inline_element_size_value; key_size = key_size_value; value_size = value_size_value; diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h b/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h index 305dc855b8..55ce7ed86b 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h @@ -97,7 +97,7 @@ struct HashtablezInfo : public profiling_internal::Sample { // the lock. static constexpr int kMaxStackDepth = 64; absl::Time create_time; - int32_t depth; + uint32_t depth; // The SOO capacity for this table in elements (not bytes). Note that sampled // tables are never SOO because we need to store the infoz handle on the heap. // Tables that would be SOO if not sampled should have: soo_capacity > 0 && diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/raw_hash_set.cc b/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/raw_hash_set.cc index 640c5a5be4..9f4cefff6d 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/raw_hash_set.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/raw_hash_set.cc @@ -45,15 +45,9 @@ constexpr ctrl_t ZeroCtrlT() { return static_cast(0); } // uninitialized because reading this memory is a bug. ABSL_DLL ctrl_t kDefaultIterControl; -// We need one full byte followed by a sentinel byte for iterator::operator++ to -// work. We have a full group after kSentinel to be safe (in case operator++ is -// changed to read a full group). -ABSL_CONST_INIT ABSL_DLL const ctrl_t kSooControl[17] = { - ZeroCtrlT(), ctrl_t::kSentinel, ZeroCtrlT(), ctrl_t::kEmpty, - ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty, - ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty, - ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty, - ctrl_t::kEmpty}; +// We need one full byte followed by a sentinel byte for iterator::operator++. +ABSL_CONST_INIT ABSL_DLL const ctrl_t kSooControl[2] = {ZeroCtrlT(), + ctrl_t::kSentinel}; namespace { @@ -170,6 +164,18 @@ FindInfo find_first_non_full_from_h1(const ctrl_t* ctrl, size_t h1, } } +// Probes an array of control bits using a probe sequence derived from `hash`, +// and returns the offset corresponding to the first deleted or empty slot. +// +// Behavior when the entire table is full is undefined. +// +// NOTE: this function must work with tables having both empty and deleted +// slots in the same group. Such tables appear during `erase()`. +FindInfo find_first_non_full(const CommonFields& common, size_t hash) { + return find_first_non_full_from_h1(common.control(), H1(hash), + common.capacity()); +} + // Whether a table fits in half a group. A half-group table fits entirely into a // probing group, i.e., has a capacity < `Group::kWidth`. // @@ -246,11 +252,6 @@ void ConvertDeletedToEmptyAndFullToDeleted(ctrl_t* ctrl, size_t capacity) { ctrl[capacity] = ctrl_t::kSentinel; } -FindInfo find_first_non_full(const CommonFields& common, size_t hash) { - return find_first_non_full_from_h1(common.control(), H1(hash), - common.capacity()); -} - void IterateOverFullSlots(const CommonFields& c, size_t slot_size, absl::FunctionRef cb) { IterateOverFullSlotsImpl(c, slot_size, cb); @@ -514,16 +515,23 @@ ABSL_ATTRIBUTE_ALWAYS_INLINE inline void InitializeThreeElementsControlBytes( } // namespace -void EraseMetaOnly(CommonFields& c, const ctrl_t* ctrl, size_t slot_size) { +void EraseMetaOnlySmall(CommonFields& c, bool soo_enabled, size_t slot_size) { + ABSL_SWISSTABLE_ASSERT(c.is_small()); + if (soo_enabled) { + c.set_empty_soo(); + return; + } + c.decrement_size(); + c.infoz().RecordErase(); + SanitizerPoisonMemoryRegion(c.slot_array(), slot_size); +} + +void EraseMetaOnlyLarge(CommonFields& c, const ctrl_t* ctrl, size_t slot_size) { + ABSL_SWISSTABLE_ASSERT(!c.is_small()); ABSL_SWISSTABLE_ASSERT(IsFull(*ctrl) && "erasing a dangling iterator"); c.decrement_size(); c.infoz().RecordErase(); - if (c.is_small()) { - SanitizerPoisonMemoryRegion(c.slot_array(), slot_size); - return; - } - size_t index = static_cast(ctrl - c.control()); if (WasNeverFull(c, index)) { 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 08c5d57aba..679d68c423 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 @@ -368,17 +368,6 @@ struct IsDecomposable< std::declval()...))>, Policy, Hash, Eq, Ts...> : std::true_type {}; -// TODO(alkis): Switch to std::is_nothrow_swappable when gcc/clang supports it. -template -constexpr bool IsNoThrowSwappable(std::true_type = {} /* is_swappable */) { - using std::swap; - return noexcept(swap(std::declval(), std::declval())); -} -template -constexpr bool IsNoThrowSwappable(std::false_type /* is_swappable */) { - return false; -} - ABSL_DLL extern ctrl_t kDefaultIterControl; // We use these sentinel capacity values in debug mode to indicate different @@ -400,7 +389,7 @@ inline ctrl_t* DefaultIterControl() { return &kDefaultIterControl; } // For use in SOO iterators. // TODO(b/289225379): we could potentially get rid of this by adding an is_soo // bit in iterators. This would add branches but reduce cache misses. -ABSL_DLL extern const ctrl_t kSooControl[17]; +ABSL_DLL extern const ctrl_t kSooControl[2]; // Returns a pointer to a full byte followed by a sentinel byte. inline ctrl_t* SooControl() { @@ -964,7 +953,14 @@ class CommonFields : public CommonFieldsGenerationInfo { ctrl_t* control() const { ABSL_SWISSTABLE_ASSERT(capacity() > 0); - ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(heap_or_soo_.control().get()); + // Assume that the control bytes don't alias `this`. + ctrl_t* ctrl = heap_or_soo_.control().get(); + [[maybe_unused]] size_t num_control_bytes = NumControlBytes(capacity()); + ABSL_ASSUME(reinterpret_cast(ctrl + num_control_bytes) <= + reinterpret_cast(this) || + reinterpret_cast(this + 1) <= + reinterpret_cast(ctrl)); + ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(ctrl); } void set_control(ctrl_t* c) { heap_or_soo_.control().set(c); } @@ -1370,13 +1366,6 @@ inline void AssertSameContainer(const ctrl_t* ctrl_a, const ctrl_t* ctrl_b, if (SwisstableGenerationsEnabled()) { if (ABSL_PREDICT_TRUE(generation_ptr_a == generation_ptr_b)) return; - // Users don't need to know whether the tables are SOO so don't mention SOO - // in the debug message. - const bool a_is_soo = IsSooControl(ctrl_a); - const bool b_is_soo = IsSooControl(ctrl_b); - fail_if(a_is_soo != b_is_soo || (a_is_soo && b_is_soo), - "Comparing iterators from different hashtables."); - const bool a_is_empty = IsEmptyGeneration(generation_ptr_a); const bool b_is_empty = IsEmptyGeneration(generation_ptr_b); fail_if(a_is_empty != b_is_empty, @@ -1422,15 +1411,6 @@ inline probe_seq probe(const CommonFields& common, size_t hash) { return probe(common.capacity(), hash); } -// Probes an array of control bits using a probe sequence derived from `hash`, -// and returns the offset corresponding to the first deleted or empty slot. -// -// Behavior when the entire table is full is undefined. -// -// NOTE: this function must work with tables having both empty and deleted -// slots in the same group. Such tables appear during `erase()`. -FindInfo find_first_non_full(const CommonFields& common, size_t hash); - constexpr size_t kProbedElementIndexSentinel = ~size_t{}; // Implementation detail of transfer_unprobed_elements_to_next_capacity_fn. @@ -1803,8 +1783,9 @@ void ResizeAllocatedTableWithSeedChange(CommonFields& common, void ClearBackingArray(CommonFields& c, const PolicyFunctions& policy, void* alloc, bool reuse, bool soo_enabled); -// Type-erased version of raw_hash_set::erase_meta_only. -void EraseMetaOnly(CommonFields& c, const ctrl_t* ctrl, size_t slot_size); +// Type-erased versions of raw_hash_set::erase_meta_only_{small,large}. +void EraseMetaOnlySmall(CommonFields& c, bool soo_enabled, size_t slot_size); +void EraseMetaOnlyLarge(CommonFields& c, const ctrl_t* ctrl, size_t slot_size); // For trivially relocatable types we use memcpy directly. This allows us to // share the same function body for raw_hash_set instantiations that have the @@ -1934,6 +1915,13 @@ class raw_hash_set { auto KeyTypeCanBeHashed(const Hash& h, const key_type& k) -> decltype(h(k)); auto KeyTypeCanBeEq(const Eq& eq, const key_type& k) -> decltype(eq(k, k)); + // Try to be helpful when the hasher returns an unreasonable type. + using key_hash_result = + absl::remove_cvref_t()( + std::declval()))>; + static_assert(sizeof(key_hash_result) >= sizeof(size_t), + "`Hash::operator()` should return a `size_t`"); + using AllocTraits = absl::allocator_traits; using SlotAlloc = typename absl::allocator_traits< allocator_type>::template rebind_alloc; @@ -2000,19 +1988,19 @@ class raw_hash_set { // PRECONDITION: not an end() iterator. reference operator*() const { - AssertIsFull(ctrl_, generation(), generation_ptr(), "operator*()"); + assert_is_full("operator*()"); return unchecked_deref(); } // PRECONDITION: not an end() iterator. pointer operator->() const { - AssertIsFull(ctrl_, generation(), generation_ptr(), "operator->"); + assert_is_full("operator->"); return &operator*(); } // PRECONDITION: not an end() iterator. iterator& operator++() { - AssertIsFull(ctrl_, generation(), generation_ptr(), "operator++"); + assert_is_full("operator++"); ++ctrl_; ++slot_; skip_empty_or_deleted(); @@ -2063,27 +2051,31 @@ class raw_hash_set { explicit iterator(const GenerationType* generation_ptr) : HashSetIteratorGenerationInfo(generation_ptr), ctrl_(nullptr) {} + void assert_is_full(const char* operation) const { + AssertIsFull(ctrl_, generation(), generation_ptr(), operation); + } + // Fixes up `ctrl_` to point to a full or sentinel by advancing `ctrl_` and // `slot_` until they reach one. void skip_empty_or_deleted() { while (IsEmptyOrDeleted(*ctrl_)) { - auto mask = GroupFullEmptyOrDeleted{ctrl_}.MaskFullOrSentinel(); - // Generally it is possible to compute `shift` branchless. - // This branch is useful to: - // 1. Avoid checking `IsEmptyOrDeleted` after the shift for the most - // common dense table case. - // 2. Avoid the cost of `LowestBitSet` for extremely sparse tables. - if (ABSL_PREDICT_TRUE(mask)) { - auto shift = mask.LowestBitSet(); - ctrl_ += shift; - slot_ += shift; - return; - } - ctrl_ += Group::kWidth; - slot_ += Group::kWidth; + ++ctrl_; + ++slot_; } } + // An equality check which skips ABSL Hardening iterator invalidation + // checks. + // Should be used when the lifetimes of the iterators are well-enough + // understood to prove that they cannot be invalid. + bool unchecked_equals(const iterator& b) const { + return ctrl_ == b.control(); + } + + // Dereferences the iterator without ABSL Hardening iterator invalidation + // checks. + reference unchecked_deref() const { return PolicyTraits::element(slot_); } + ctrl_t* control() const { return ctrl_; } slot_type* slot() const { return slot_; } @@ -2095,16 +2087,6 @@ class raw_hash_set { union { slot_type* slot_; }; - - // An equality check which skips ABSL Hardening iterator invalidation - // checks. - // Should be used when the lifetimes of the iterators are well-enough - // understood to prove that they cannot be invalid. - bool unchecked_equals(const iterator& b) { return ctrl_ == b.control(); } - - // Dereferences the iterator without ABSL Hardening iterator invalidation - // checks. - reference unchecked_deref() const { return PolicyTraits::element(slot_); } }; class const_iterator { @@ -2145,14 +2127,13 @@ class raw_hash_set { const GenerationType* gen) : inner_(const_cast(ctrl), const_cast(slot), gen) { } + bool unchecked_equals(const const_iterator& b) const { + return inner_.unchecked_equals(b.inner_); + } ctrl_t* control() const { return inner_.control(); } slot_type* slot() const { return inner_.slot(); } iterator inner_; - - bool unchecked_equals(const const_iterator& b) { - return inner_.unchecked_equals(b.inner_); - } }; using node_type = node_handle, Alloc>; @@ -2337,7 +2318,7 @@ class raw_hash_set { } raw_hash_set& operator=(raw_hash_set&& that) noexcept( - absl::allocator_traits::is_always_equal::value && + AllocTraits::is_always_equal::value && std::is_nothrow_move_assignable::value && std::is_nothrow_move_assignable::value) { // TODO(sbenza): We should only use the operations from the noexcept clause @@ -2388,7 +2369,7 @@ class raw_hash_set { size_t capacity() const { const size_t cap = common().capacity(); // Compiler complains when using functions in ASSUME so use local variable. - ABSL_ATTRIBUTE_UNUSED static constexpr size_t kDefaultCapacity = + [[maybe_unused]] static constexpr size_t kDefaultCapacity = DefaultCapacity(); ABSL_ASSUME(cap >= kDefaultCapacity); return cap; @@ -2693,7 +2674,7 @@ class raw_hash_set { void erase(iterator it) { ABSL_SWISSTABLE_ASSERT(capacity() > 0); AssertNotDebugCapacity(); - AssertIsFull(it.control(), it.generation(), it.generation_ptr(), "erase()"); + it.assert_is_full("erase()"); destroy(it.slot()); erase_meta_only(it); } @@ -2707,7 +2688,7 @@ class raw_hash_set { if (first == last) return last.inner_; if (is_small()) { destroy(single_slot()); - erase_meta_only(single_iterator()); + erase_meta_only_small(); return end(); } if (first == begin() && last == end()) { @@ -2742,12 +2723,12 @@ class raw_hash_set { if (src.is_small()) { if (src.empty()) return; if (insert_slot(src.single_slot())) - src.erase_meta_only(src.single_iterator()); + src.erase_meta_only_small(); return; } for (auto it = src.begin(), e = src.end(); it != e;) { auto next = std::next(it); - if (insert_slot(it.slot())) src.erase_meta_only(it); + if (insert_slot(it.slot())) src.erase_meta_only_large(it); it = next; } } @@ -2759,8 +2740,7 @@ class raw_hash_set { node_type extract(const_iterator position) { AssertNotDebugCapacity(); - AssertIsFull(position.control(), position.inner_.generation(), - position.inner_.generation_ptr(), "extract()"); + position.inner_.assert_is_full("extract()"); allocator_type alloc(char_alloc_ref()); auto node = CommonAccess::Transfer(alloc, position.slot()); erase_meta_only(position); @@ -2775,9 +2755,9 @@ class raw_hash_set { } void swap(raw_hash_set& that) noexcept( - IsNoThrowSwappable() && IsNoThrowSwappable() && - IsNoThrowSwappable( - typename AllocTraits::propagate_on_container_swap{})) { + AllocTraits::is_always_equal::value && + std::is_nothrow_swappable::value && + std::is_nothrow_swappable::value) { AssertNotDebugCapacity(); that.AssertNotDebugCapacity(); using std::swap; @@ -3090,11 +3070,17 @@ class raw_hash_set { // This merely updates the pertinent control byte. This can be used in // conjunction with Policy::transfer to move the object to another place. void erase_meta_only(const_iterator it) { - if (is_soo()) { - common().set_empty_soo(); + if (is_small()) { + erase_meta_only_small(); return; } - EraseMetaOnly(common(), it.control(), sizeof(slot_type)); + erase_meta_only_large(it); + } + void erase_meta_only_small() { + EraseMetaOnlySmall(common(), SooEnabled(), sizeof(slot_type)); + } + void erase_meta_only_large(const_iterator it) { + EraseMetaOnlyLarge(common(), it.control(), sizeof(slot_type)); } template @@ -3154,8 +3140,7 @@ class raw_hash_set { std::move(tmp)); } - void annotate_for_bug_detection_on_move( - ABSL_ATTRIBUTE_UNUSED raw_hash_set& that) { + void annotate_for_bug_detection_on_move([[maybe_unused]] raw_hash_set& that) { // We only enable moved-from validation when generations are enabled (rather // than using NDEBUG) to avoid issues in which NDEBUG is enabled in some // translation units but not in others. @@ -3305,7 +3290,7 @@ class raw_hash_set { protected: // Asserts for correctness that we run on find/find_or_prepare_insert. template - void AssertOnFind(ABSL_ATTRIBUTE_UNUSED const K& key) { + void AssertOnFind([[maybe_unused]] const K& key) { AssertHashEqConsistent(key); AssertNotDebugCapacity(); } @@ -3364,7 +3349,7 @@ class raw_hash_set { const bool is_key_equal = equal_to(key, to_slot(slot)); if (!is_key_equal) return; - ABSL_ATTRIBUTE_UNUSED const bool is_hash_equal = + [[maybe_unused]] const bool is_hash_equal = hash_of_arg == hash_of(to_slot(slot)); assert((!is_key_equal || is_hash_equal) && "eq(k1, k2) must imply that hash(k1) == hash(k2). " @@ -3642,10 +3627,10 @@ struct HashtableFreeFunctionsAccess { return 0; } c->destroy(it.slot()); - c->erase_meta_only(it); + c->erase_meta_only_small(); return 1; } - ABSL_ATTRIBUTE_UNUSED const size_t original_size_for_assert = c->size(); + [[maybe_unused]] const size_t original_size_for_assert = c->size(); size_t num_deleted = 0; using SlotType = typename Set::slot_type; IterateOverFullSlots( @@ -3654,7 +3639,7 @@ struct HashtableFreeFunctionsAccess { auto* slot = static_cast(slot_void); if (pred(Set::PolicyTraits::element(slot))) { c->destroy(slot); - EraseMetaOnly(c->common(), ctrl, sizeof(*slot)); + EraseMetaOnlyLarge(c->common(), ctrl, sizeof(*slot)); ++num_deleted; } }); @@ -3713,7 +3698,7 @@ struct HashtableDebugAccess> { static size_t GetNumProbes(const Set& set, const typename Set::key_type& key) { - if (set.is_soo()) return 0; + if (set.is_small()) return 0; size_t num_probes = 0; const size_t hash = set.hash_of(key); auto seq = probe(set.common(), hash); diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/raw_hash_set_benchmark.cc b/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/raw_hash_set_benchmark.cc index 07a5b90f5a..f3e32fd2ee 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/raw_hash_set_benchmark.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/raw_hash_set_benchmark.cc @@ -519,17 +519,6 @@ void BM_Group_MaskNonFull(benchmark::State& state) { } BENCHMARK(BM_Group_MaskNonFull); -void BM_Group_CountLeadingEmptyOrDeleted(benchmark::State& state) { - std::array group; - Iota(group.begin(), group.end(), -2); - Group g{group.data()}; - for (auto _ : state) { - ::benchmark::DoNotOptimize(g); - ::benchmark::DoNotOptimize(g.CountLeadingEmptyOrDeleted()); - } -} -BENCHMARK(BM_Group_CountLeadingEmptyOrDeleted); - void BM_Group_MatchFirstEmptyOrDeleted(benchmark::State& state) { std::array group; Iota(group.begin(), group.end(), -2); diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/raw_hash_set_resize_impl.h b/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/raw_hash_set_resize_impl.h index 149d9e825e..ed48d96bc6 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/raw_hash_set_resize_impl.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/raw_hash_set_resize_impl.h @@ -52,7 +52,6 @@ struct ProbedItemImpl { static constexpr IntType kMaxNewBits = kMaxOldBits + 1; static constexpr IntType kMaxNewCapacity = (IntType{1} << kMaxNewBits) - 1; - static constexpr IntType kH2Shift = (kTotalBits - kH2Bits); static_assert(kMaxNewBits + kMaxOldBits + kH2Bits == kTotalBits); ProbedItemImpl() = default; diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/crc/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/crc/BUILD.bazel index b659a7e24e..22c3cbf0fc 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/crc/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/crc/BUILD.bazel @@ -12,6 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/crc/internal/crc_memcpy_x86_arm_combined.cc b/naiveproxy/src/third_party/abseil-cpp/absl/crc/internal/crc_memcpy_x86_arm_combined.cc index 38f61e9b1f..247b3aa9d1 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/crc/internal/crc_memcpy_x86_arm_combined.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/crc/internal/crc_memcpy_x86_arm_combined.cc @@ -422,6 +422,11 @@ CrcMemcpy::ArchSpecificEngines CrcMemcpy::GetArchSpecificEngines() { }; // INTEL_SANDYBRIDGE performs better with SSE than AVX. case CpuType::kIntelSandybridge: + // Use SIMD memcpy on ARM cores. + case CpuType::kArmNeoverseN1: + case CpuType::kArmNeoverseN2: + case CpuType::kArmNeoverseV1: + case CpuType::kArmNeoverseV2: return { /*.temporal=*/new AcceleratedCrcMemcpyEngine<3, 0>(), /*.non_temporal=*/new CrcNonTemporalMemcpyEngine(), diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/crc/internal/crc_x86_arm_combined.cc b/naiveproxy/src/third_party/abseil-cpp/absl/crc/internal/crc_x86_arm_combined.cc index 3194bec468..03cf348ff9 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/crc/internal/crc_x86_arm_combined.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/crc/internal/crc_x86_arm_combined.cc @@ -100,47 +100,67 @@ constexpr size_t kMediumCutoff = 2048; namespace { -uint32_t multiply(uint32_t a, uint32_t b) { - V128 power = V128_From64WithZeroFill(a); - V128 crc = V128_From64WithZeroFill(b); - V128 res = V128_PMulLow(power, crc); +// Does polynomial multiplication a * b * x^33 mod G. +// +// One of the multiplicands needs to have an extra factor of x^-33 to cancel out +// the extra factor of x^33. The extra factor of x^33 comes from: +// +// - x^1 from the carry-less multiplication, due to the +// "least-significant-bit-first" convention of CRC-32C. +// +// - x^32 from using CRC32_u64() to reduce the carry-less product to 32 bits. +// +// Both could be avoided, but at the cost of extra instructions. It's more +// efficient to just drop a factor of x^33 from one of the multiplicands. +uint32_t MultiplyWithExtraX33(uint32_t a, uint32_t b) { + V128 a_vec = V128_From64WithZeroFill(a); + V128 b_vec = V128_From64WithZeroFill(b); + V128 res = V128_PMulLow(a_vec, b_vec); - // Combine crc values. - // - // Adding res to itself is equivalent to multiplying by 2, - // or shifting left by 1. Addition is used as not all compilers - // are able to generate optimal code without this hint. - // https://godbolt.org/z/rr3fMnf39 - res = V128_Add64(res, res); - return static_cast(V128_Extract32<1>(res)) ^ - CRC32_u32(0, static_cast(V128_Low64(res))); + return CRC32_u64(0, static_cast(V128_Low64(res))); } -// Powers of crc32c polynomial, for faster ExtendByZeros. -// Verified against folly: -// folly/hash/detail/Crc32CombineDetail.cpp +// The number of low-order bits that ComputeZeroConstant() drops from the +// length, i.e. treats as zeroes +constexpr int kNumDroppedBits = 4; + +// Precomputed constants for faster ExtendByZeroes(). This was generated by +// gen_crc32c_consts.py. The entry at index i is x^(2^(i + 3 + kNumDroppedBits) +// - 33) mod G. That is x^-33 times the polynomial by which the CRC value needs +// to be multiplied to extend it by 2^(i + 3 + kNumDroppedBits) zero bits, or +// equivalently 2^(i + kNumDroppedBits) zero bytes. The extra factor of x^-33 +// cancels out the extra factor of x^33 that MultiplyWithExtraX33() introduces. constexpr uint32_t kCRC32CPowers[] = { - 0x82f63b78, 0x6ea2d55c, 0x18b8ea18, 0x510ac59a, 0xb82be955, 0xb8fdb1e7, - 0x88e56f72, 0x74c360a4, 0xe4172b16, 0x0d65762a, 0x35d73a62, 0x28461564, - 0xbf455269, 0xe2ea32dc, 0xfe7740e6, 0xf946610b, 0x3c204f8f, 0x538586e3, - 0x59726915, 0x734d5309, 0xbc1ac763, 0x7d0722cc, 0xd289cabe, 0xe94ca9bc, - 0x05b74f3f, 0xa51e1f42, 0x40000000, 0x20000000, 0x08000000, 0x00800000, - 0x00008000, 0x82f63b78, 0x6ea2d55c, 0x18b8ea18, 0x510ac59a, 0xb82be955, - 0xb8fdb1e7, 0x88e56f72, 0x74c360a4, 0xe4172b16, 0x0d65762a, 0x35d73a62, - 0x28461564, 0xbf455269, 0xe2ea32dc, 0xfe7740e6, 0xf946610b, 0x3c204f8f, - 0x538586e3, 0x59726915, 0x734d5309, 0xbc1ac763, 0x7d0722cc, 0xd289cabe, - 0xe94ca9bc, 0x05b74f3f, 0xa51e1f42, 0x40000000, 0x20000000, 0x08000000, - 0x00800000, 0x00008000, + 0x493c7d27, 0xba4fc28e, 0x9e4addf8, 0x0d3b6092, 0xb9e02b86, 0xdd7e3b0c, + 0x170076fa, 0xa51b6135, 0x82f89c77, 0x54a86326, 0x1dc403cc, 0x5ae703ab, + 0xc5013a36, 0xac2ac6dd, 0x9b4615a9, 0x688d1c61, 0xf6af14e6, 0xb6ffe386, + 0xb717425b, 0x478b0d30, 0x54cc62e5, 0x7b2102ee, 0x8a99adef, 0xa7568c8f, + 0xd610d67e, 0x6b086b3f, 0xd94f3c0b, 0xbf818109, 0x780d5a4d, 0x05ec76f1, + 0x00000001, 0x493c7d27, 0xba4fc28e, 0x9e4addf8, 0x0d3b6092, 0xb9e02b86, + 0xdd7e3b0c, 0x170076fa, 0xa51b6135, 0x82f89c77, 0x54a86326, 0x1dc403cc, + 0x5ae703ab, 0xc5013a36, 0xac2ac6dd, 0x9b4615a9, 0x688d1c61, 0xf6af14e6, + 0xb6ffe386, 0xb717425b, 0x478b0d30, 0x54cc62e5, 0x7b2102ee, 0x8a99adef, + 0xa7568c8f, 0xd610d67e, 0x6b086b3f, 0xd94f3c0b, 0xbf818109, 0x780d5a4d, }; +// There must be an entry for each non-dropped bit in the size_t length. +static_assert(std::size(kCRC32CPowers) >= sizeof(size_t) * 8 - kNumDroppedBits); } // namespace -// Compute a magic constant, so that multiplying by it is the same as -// extending crc by length zeros. +// Compute a magic constant, so that multiplying by it is the same as extending +// crc by length zeros. The lowest kNumDroppedBits of the length are ignored and +// treated as zeroes; the caller is assumed to handle any nonzero bits there. +#if defined(NDEBUG) && ABSL_HAVE_CPP_ATTRIBUTE(clang::no_sanitize) +// The array accesses in this are safe: `length >= size_t{1} << +// kNumDroppedBits`, so `countr_zero(length >> kNumDroppedBits) < sizeof(size_t) +// * 8 - kNumDroppedBits`, and `length & (length - 1)` cannot introduce bits +// `>= sizeof(size_t) * 8 - kNumDroppedBits`. The compiler cannot prove this, so +// manually disable bounds checking. +[[clang::no_sanitize("array-bounds")]] +#endif uint32_t CRC32AcceleratedX86ARMCombined::ComputeZeroConstant( size_t length) const { - // Lowest 2 bits are handled separately in ExtendByZeroes - length >>= 2; + length >>= kNumDroppedBits; int index = absl::countr_zero(length); uint32_t prev = kCRC32CPowers[index]; @@ -149,7 +169,7 @@ uint32_t CRC32AcceleratedX86ARMCombined::ComputeZeroConstant( while (length) { // For each bit of length, extend by 2**n zeros. index = absl::countr_zero(length); - prev = multiply(prev, kCRC32CPowers[index]); + prev = MultiplyWithExtraX33(prev, kCRC32CPowers[index]); length &= length - 1; } return prev; @@ -159,22 +179,13 @@ void CRC32AcceleratedX86ARMCombined::ExtendByZeroes(uint32_t* crc, size_t length) const { uint32_t val = *crc; // Don't bother with multiplication for small length. - switch (length & 3) { - case 0: - break; - case 1: - val = CRC32_u8(val, 0); - break; - case 2: - val = CRC32_u16(val, 0); - break; - case 3: - val = CRC32_u8(val, 0); - val = CRC32_u16(val, 0); - break; - } - if (length > 3) { - val = multiply(val, ComputeZeroConstant(length)); + if (length & 1) val = CRC32_u8(val, 0); + if (length & 2) val = CRC32_u16(val, 0); + if (length & 4) val = CRC32_u32(val, 0); + if (length & 8) val = CRC32_u64(val, 0); + static_assert(kNumDroppedBits == 4); + if (length >= size_t{1} << kNumDroppedBits) { + val = MultiplyWithExtraX33(val, ComputeZeroConstant(length)); } *crc = val; } @@ -542,14 +553,15 @@ class CRC32AcceleratedX86ARMCombinedMultipleStreams } // Combine all streams into single result. + static_assert(64 % (1 << kNumDroppedBits) == 0); uint32_t magic = ComputeZeroConstant(bs * 64); l64 = l64_crc[0]; for (size_t i = 1; i < num_crc_streams; i++) { - l64 = multiply(static_cast(l64), magic); + l64 = MultiplyWithExtraX33(static_cast(l64), magic); l64 ^= l64_crc[i]; } for (size_t i = 0; i < num_pclmul_streams; i++) { - l64 = multiply(static_cast(l64), magic); + l64 = MultiplyWithExtraX33(static_cast(l64), magic); l64 ^= l64_pclmul[i]; } diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/crc/internal/gen_crc32c_consts.py b/naiveproxy/src/third_party/abseil-cpp/absl/crc/internal/gen_crc32c_consts.py new file mode 100755 index 0000000000..f78ae302d5 --- /dev/null +++ b/naiveproxy/src/third_party/abseil-cpp/absl/crc/internal/gen_crc32c_consts.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +# +# Copyright 2025 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. + +"""This script generates kCRC32CPowers[].""" + + +def poly_mul(a, b): + """Polynomial multiplication: a * b.""" + product = 0 + for i in range(b.bit_length()): + if (b & (1 << i)) != 0: + product ^= a << i + return product + + +def poly_div(a, b): + """Polynomial division: floor(a / b).""" + q = 0 + while a.bit_length() >= b.bit_length(): + q ^= 1 << (a.bit_length() - b.bit_length()) + a ^= b << (a.bit_length() - b.bit_length()) + return q + + +def poly_reduce(a, b): + """Polynomial reduction: a mod b.""" + return a ^ poly_mul(poly_div(a, b), b) + + +def poly_exp(a, b, g): + """Polynomial exponentiation: a^b mod g.""" + if b == 1: + return poly_reduce(a, g) + c = poly_exp(a, b // 2, g) + c = poly_mul(c, c) + if b % 2 != 0: + c = poly_mul(c, a) + return poly_reduce(c, g) + + +def bitreflect(a, num_bits): + """Reflects the bits of the given integer.""" + if a.bit_length() > num_bits: + raise ValueError(f'Integer has more than {num_bits} bits') + return sum(((a >> i) & 1) << (num_bits - 1 - i) for i in range(num_bits)) + + +G = 0x11EDC6F41 # The CRC-32C reducing polynomial, in the "natural" bit order +CRC_BITS = 32 # The degree of G, i.e. the 32 in "CRC-32C" +LSB_FIRST = True # CRC-32C is a least-significant-bit-first CRC +NUM_SIZE_BITS = 64 # The maximum number of bits in the length (size_t) +NUM_DROPPED_BITS = 4 # The number of bits dropped from the length +LOG2_BITS_PER_BYTE = 3 # log2 of the number of bits in a byte, i.e. log2(8) +X = 2 # The polynomial 'x', in the "natural" bit order + + +def print_crc32c_powers(): + """Generates kCRC32CPowers[]. + + kCRC32CPowers[] is an array of length NUM_SIZE_BITS - NUM_DROPPED_BITS, + whose i'th entry is x^(2^(i + LOG2_BITS_PER_BYTE + NUM_DROPPED_BITS) - + CRC_BITS - 1) mod G. See kCRC32CPowers[] in the C++ source for more info. + """ + for i in range(NUM_SIZE_BITS - NUM_DROPPED_BITS): + poly = poly_exp( + X, + 2 ** (i + LOG2_BITS_PER_BYTE + NUM_DROPPED_BITS) + - CRC_BITS + - (1 if LSB_FIRST else 0), + G, + ) + poly = bitreflect(poly, CRC_BITS) + print(f'0x{poly:0{2*CRC_BITS//8}x}, ', end='') + + +if __name__ == '__main__': + print_crc32c_powers() diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h index 88949fe974..c82d4a3694 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h @@ -43,11 +43,12 @@ "absl/debugging/internal/stacktrace_emscripten-inl.inc" #elif defined(__ANDROID__) && __ANDROID_API__ >= 33 - +#ifdef ABSL_HAVE_THREAD_LOCAL // Use the generic implementation for Android 33+ (Android T+). This is the // first version of Android for which implements backtrace(). #define ABSL_STACKTRACE_INL_HEADER \ "absl/debugging/internal/stacktrace_generic-inl.inc" +#endif // defined(ABSL_HAVE_THREAD_LOCAL) #elif defined(__linux__) && !defined(__ANDROID__) @@ -59,11 +60,11 @@ "absl/debugging/internal/stacktrace_libunwind-inl.inc" #define STACKTRACE_USES_LIBUNWIND 1 #elif defined(NO_FRAME_POINTER) && defined(__has_include) -#if __has_include() +#if __has_include() && defined(ABSL_HAVE_THREAD_LOCAL) // Note: When using glibc this may require -funwind-tables to function properly. #define ABSL_STACKTRACE_INL_HEADER \ "absl/debugging/internal/stacktrace_generic-inl.inc" -#endif // __has_include() +#endif // __has_include() && defined(ABSL_HAVE_THREAD_LOCAL) #elif defined(__i386__) || defined(__x86_64__) #define ABSL_STACKTRACE_INL_HEADER \ "absl/debugging/internal/stacktrace_x86-inl.inc" @@ -77,11 +78,11 @@ #define ABSL_STACKTRACE_INL_HEADER \ "absl/debugging/internal/stacktrace_riscv-inl.inc" #elif defined(__has_include) -#if __has_include() +#if __has_include() && defined(ABSL_HAVE_THREAD_LOCAL) // Note: When using glibc this may require -funwind-tables to function properly. #define ABSL_STACKTRACE_INL_HEADER \ "absl/debugging/internal/stacktrace_generic-inl.inc" -#endif // __has_include() +#endif // __has_include() && defined(ABSL_HAVE_THREAD_LOCAL) #endif // defined(__has_include) #endif // defined(__linux__) && !defined(__ANDROID__) diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/stacktrace.cc b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/stacktrace.cc index f71e80cfef..ccecff766e 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/stacktrace.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/stacktrace.cc @@ -97,25 +97,51 @@ std::atomic custom; template ABSL_ATTRIBUTE_ALWAYS_INLINE inline int Unwind(void** result, uintptr_t* frames, - int* sizes, int max_depth, + int* sizes, size_t max_depth, int skip_count, const void* uc, int* min_dropped_frames) { + bool unwind_with_fixup = internal_stacktrace::ShouldFixUpStack(); + if (unwind_with_fixup) { + if constexpr (kHaveAlloca) { + // Some implementations of FixUpStack may need to be passed frame + // information from Unwind, even if the caller doesn't need that + // information. We allocate the necessary buffers for such implementations + // here. + if (frames == nullptr) { + frames = static_cast(alloca(max_depth * sizeof(*frames))); + } + if (sizes == nullptr) { + sizes = static_cast(alloca(max_depth * sizeof(*sizes))); + } + } + } + Unwinder g = custom.load(std::memory_order_acquire); - int size; + size_t size; // Add 1 to skip count for the unwinder function itself ++skip_count; if (g != nullptr) { - size = (*g)(result, sizes, max_depth, skip_count, uc, min_dropped_frames); + size = static_cast((*g)(result, sizes, static_cast(max_depth), + skip_count, uc, min_dropped_frames)); // Frame pointers aren't returned by existing hooks, so clear them. if (frames != nullptr) { std::fill(frames, frames + size, uintptr_t()); } } else { - size = UnwindImpl( - result, frames, sizes, max_depth, skip_count, uc, min_dropped_frames); + size = static_cast( + unwind_with_fixup + ? UnwindImpl( + result, frames, sizes, static_cast(max_depth), + skip_count, uc, min_dropped_frames) + : UnwindImpl( + result, frames, sizes, static_cast(max_depth), + skip_count, uc, min_dropped_frames)); + } + if (unwind_with_fixup) { + internal_stacktrace::FixUpStack(result, frames, sizes, max_depth, size); } ABSL_BLOCK_TAIL_CALL_OPTIMIZATION(); - return size; + return static_cast(size); } } // anonymous namespace @@ -123,15 +149,8 @@ ABSL_ATTRIBUTE_ALWAYS_INLINE inline int Unwind(void** result, uintptr_t* frames, ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int internal_stacktrace::GetStackFrames(void** result, uintptr_t* frames, int* sizes, int max_depth, int skip_count) { - if (internal_stacktrace::ShouldFixUpStack()) { - size_t depth = static_cast(Unwind( - result, frames, sizes, max_depth, skip_count, nullptr, nullptr)); - internal_stacktrace::FixUpStack(result, frames, sizes, - static_cast(max_depth), depth); - return static_cast(depth); - } - - return Unwind(result, frames, sizes, max_depth, skip_count, + return Unwind(result, frames, sizes, + static_cast(max_depth), skip_count, nullptr, nullptr); } @@ -140,56 +159,24 @@ internal_stacktrace::GetStackFramesWithContext(void** result, uintptr_t* frames, int* sizes, int max_depth, int skip_count, const void* uc, int* min_dropped_frames) { - if (internal_stacktrace::ShouldFixUpStack()) { - size_t depth = static_cast(Unwind( - result, frames, sizes, max_depth, skip_count, uc, min_dropped_frames)); - internal_stacktrace::FixUpStack(result, frames, sizes, - static_cast(max_depth), depth); - return static_cast(depth); - } - - return Unwind(result, frames, sizes, max_depth, skip_count, uc, + return Unwind(result, frames, sizes, + static_cast(max_depth), skip_count, uc, min_dropped_frames); } ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackTrace( void** result, int max_depth, int skip_count) { - if (internal_stacktrace::ShouldFixUpStack()) { - if constexpr (kHaveAlloca) { - const size_t nmax = static_cast(max_depth); - uintptr_t* frames = - static_cast(alloca(nmax * sizeof(*frames))); - int* sizes = static_cast(alloca(nmax * sizeof(*sizes))); - size_t depth = static_cast(Unwind( - result, frames, sizes, max_depth, skip_count, nullptr, nullptr)); - internal_stacktrace::FixUpStack(result, frames, sizes, nmax, depth); - return static_cast(depth); - } - } - - return Unwind(result, nullptr, nullptr, max_depth, skip_count, + return Unwind(result, nullptr, nullptr, + static_cast(max_depth), skip_count, nullptr, nullptr); } ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackTraceWithContext(void** result, int max_depth, int skip_count, const void* uc, int* min_dropped_frames) { - if (internal_stacktrace::ShouldFixUpStack()) { - if constexpr (kHaveAlloca) { - const size_t nmax = static_cast(max_depth); - uintptr_t* frames = - static_cast(alloca(nmax * sizeof(*frames))); - int* sizes = static_cast(alloca(nmax * sizeof(*sizes))); - size_t depth = static_cast( - Unwind(result, frames, sizes, max_depth, skip_count, uc, - min_dropped_frames)); - internal_stacktrace::FixUpStack(result, frames, sizes, nmax, depth); - return static_cast(depth); - } - } - - return Unwind(result, nullptr, nullptr, max_depth, skip_count, - uc, min_dropped_frames); + return Unwind(result, nullptr, nullptr, + static_cast(max_depth), skip_count, uc, + min_dropped_frames); } void SetStackUnwinder(Unwinder w) { diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/symbolize_elf.inc b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/symbolize_elf.inc index 9836c93295..0317bbc316 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/symbolize_elf.inc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/symbolize_elf.inc @@ -167,22 +167,22 @@ struct FileMappingHint { // We are using SpinLock and not a Mutex here, because we may be called // from inside Mutex::Lock itself, and it prohibits recursive calls. // This happens in e.g. base/stacktrace_syscall_unittest. -// Moreover, we are using only TryLock(), if the decorator list +// Moreover, we are using only try_lock(), if the decorator list // is being modified (is busy), we skip all decorators, and possibly // loose some info. Sorry, that's the best we could do. ABSL_CONST_INIT absl::base_internal::SpinLock g_decorators_mu( - absl::kConstInit, absl::base_internal::SCHEDULE_KERNEL_ONLY); + absl::base_internal::SCHEDULE_KERNEL_ONLY); const int kMaxFileMappingHints = 8; int g_num_file_mapping_hints; FileMappingHint g_file_mapping_hints[kMaxFileMappingHints]; // Protects g_file_mapping_hints. ABSL_CONST_INIT absl::base_internal::SpinLock g_file_mapping_mu( - absl::kConstInit, absl::base_internal::SCHEDULE_KERNEL_ONLY); + absl::base_internal::SCHEDULE_KERNEL_ONLY); // Async-signal-safe function to zero a buffer. // memset() is not guaranteed to be async-signal-safe. -static void SafeMemZero(void* p, size_t size) { +static void SafeMemZero(void *p, size_t size) { unsigned char *c = static_cast(p); while (size--) { *c++ = 0; @@ -232,29 +232,6 @@ struct SymbolCacheLine { uint32_t age[ASSOCIATIVITY]; }; -// --------------------------------------------------------------- -// An async-signal-safe arena for LowLevelAlloc -static std::atomic g_sig_safe_arena; - -static base_internal::LowLevelAlloc::Arena *SigSafeArena() { - return g_sig_safe_arena.load(std::memory_order_acquire); -} - -static void InitSigSafeArena() { - if (SigSafeArena() == nullptr) { - base_internal::LowLevelAlloc::Arena *new_arena = - base_internal::LowLevelAlloc::NewArena( - base_internal::LowLevelAlloc::kAsyncSignalSafe); - base_internal::LowLevelAlloc::Arena *old_value = nullptr; - if (!g_sig_safe_arena.compare_exchange_strong(old_value, new_arena, - std::memory_order_release, - std::memory_order_relaxed)) { - // We lost a race to allocate an arena; deallocate. - base_internal::LowLevelAlloc::DeleteArena(new_arena); - } - } -} - // --------------------------------------------------------------- // An AddrMap is a vector of ObjFile, using SigSafeArena() for allocation. @@ -287,7 +264,7 @@ ObjFile *AddrMap::Add() { size_t new_allocated = allocated_ * 2 + 50; ObjFile *new_obj_ = static_cast(base_internal::LowLevelAlloc::AllocWithArena( - new_allocated * sizeof(*new_obj_), SigSafeArena())); + new_allocated * sizeof(*new_obj_), base_internal::SigSafeArena())); if (obj_) { memcpy(new_obj_, obj_, allocated_ * sizeof(*new_obj_)); base_internal::LowLevelAlloc::Free(obj_); @@ -335,8 +312,9 @@ class Symbolizer { private: char *CopyString(const char *s) { size_t len = strlen(s); - char *dst = static_cast( - base_internal::LowLevelAlloc::AllocWithArena(len + 1, SigSafeArena())); + char *dst = + static_cast(base_internal::LowLevelAlloc::AllocWithArena( + len + 1, base_internal::SigSafeArena())); ABSL_RAW_CHECK(dst != nullptr, "out of memory"); memcpy(dst, s, len + 1); return dst; @@ -441,14 +419,14 @@ static size_t SymbolizerSize() { // Return (and set null) g_cached_symbolized_state if it is not null. // Otherwise return a new symbolizer. static Symbolizer *AllocateSymbolizer() { - InitSigSafeArena(); + base_internal::InitSigSafeArena(); Symbolizer *symbolizer = g_cached_symbolizer.exchange(nullptr, std::memory_order_acquire); if (symbolizer != nullptr) { return symbolizer; } return new (base_internal::LowLevelAlloc::AllocWithArena( - SymbolizerSize(), SigSafeArena())) Symbolizer(); + SymbolizerSize(), base_internal::SigSafeArena())) Symbolizer(); } // Set g_cached_symbolize_state to s if it is null, otherwise @@ -1469,14 +1447,15 @@ static bool MaybeInitializeObjFile(ObjFile *obj) { constexpr int interesting = PF_X | PF_R; #endif - if (phdr.p_type != PT_LOAD - || (phdr.p_flags & interesting) != interesting) { + if (phdr.p_type != PT_LOAD || + (phdr.p_flags & interesting) != interesting) { // Not a LOAD segment, not executable code, and not a function // descriptor. continue; } if (num_interesting_load_segments < obj->phdr.size()) { - memcpy(&obj->phdr[num_interesting_load_segments++], &phdr, sizeof(phdr)); + memcpy(&obj->phdr[num_interesting_load_segments++], &phdr, + sizeof(phdr)); } else { ABSL_RAW_LOG( WARNING, "%s: too many interesting LOAD segments: %zu >= %zu", @@ -1525,7 +1504,8 @@ const char *Symbolizer::GetUncachedSymbol(const void *pc) { ABSL_RAW_CHECK(p.p_type == PT_NULL, "unexpected p_type"); break; } - if (pc < reinterpret_cast(start_addr + p.p_vaddr + p.p_memsz)) { + if (pc < + reinterpret_cast(start_addr + p.p_vaddr + p.p_memsz)) { phdr = &p; break; } @@ -1569,7 +1549,7 @@ const char *Symbolizer::GetUncachedSymbol(const void *pc) { #endif } - if (g_decorators_mu.TryLock()) { + if (g_decorators_mu.try_lock()) { if (g_num_decorators > 0) { SymbolDecoratorArgs decorator_args = { pc, relocation, fd, symbol_buf_, sizeof(symbol_buf_), @@ -1579,7 +1559,7 @@ const char *Symbolizer::GetUncachedSymbol(const void *pc) { g_decorators[i].fn(&decorator_args); } } - g_decorators_mu.Unlock(); + g_decorators_mu.unlock(); } if (symbol_buf_[0] == '\0') { return nullptr; @@ -1625,17 +1605,17 @@ const char *Symbolizer::GetSymbol(const void *pc) { } bool RemoveAllSymbolDecorators(void) { - if (!g_decorators_mu.TryLock()) { + if (!g_decorators_mu.try_lock()) { // Someone else is using decorators. Get out. return false; } g_num_decorators = 0; - g_decorators_mu.Unlock(); + g_decorators_mu.unlock(); return true; } bool RemoveSymbolDecorator(int ticket) { - if (!g_decorators_mu.TryLock()) { + if (!g_decorators_mu.try_lock()) { // Someone else is using decorators. Get out. return false; } @@ -1649,14 +1629,14 @@ bool RemoveSymbolDecorator(int ticket) { break; } } - g_decorators_mu.Unlock(); + g_decorators_mu.unlock(); return true; // Decorator is known to be removed. } int InstallSymbolDecorator(SymbolDecorator decorator, void *arg) { static int ticket = 0; - if (!g_decorators_mu.TryLock()) { + if (!g_decorators_mu.try_lock()) { // Someone else is using decorators. Get out. return -2; } @@ -1667,18 +1647,18 @@ int InstallSymbolDecorator(SymbolDecorator decorator, void *arg) { g_decorators[g_num_decorators] = {decorator, arg, ticket++}; ++g_num_decorators; } - g_decorators_mu.Unlock(); + g_decorators_mu.unlock(); return ret; } -bool RegisterFileMappingHint(const void *start, const void *end, uint64_t offset, - const char *filename) { +bool RegisterFileMappingHint(const void *start, const void *end, + uint64_t offset, const char *filename) { SAFE_ASSERT(start <= end); SAFE_ASSERT(filename != nullptr); - InitSigSafeArena(); + base_internal::InitSigSafeArena(); - if (!g_file_mapping_mu.TryLock()) { + if (!g_file_mapping_mu.try_lock()) { return false; } @@ -1688,8 +1668,9 @@ bool RegisterFileMappingHint(const void *start, const void *end, uint64_t offset } else { // TODO(ckennelly): Move this into a string copy routine. size_t len = strlen(filename); - char *dst = static_cast( - base_internal::LowLevelAlloc::AllocWithArena(len + 1, SigSafeArena())); + char *dst = + static_cast(base_internal::LowLevelAlloc::AllocWithArena( + len + 1, base_internal::SigSafeArena())); ABSL_RAW_CHECK(dst != nullptr, "out of memory"); memcpy(dst, filename, len + 1); @@ -1700,13 +1681,13 @@ bool RegisterFileMappingHint(const void *start, const void *end, uint64_t offset hint.filename = dst; } - g_file_mapping_mu.Unlock(); + g_file_mapping_mu.unlock(); return ret; } bool GetFileMappingHint(const void **start, const void **end, uint64_t *offset, const char **filename) { - if (!g_file_mapping_mu.TryLock()) { + if (!g_file_mapping_mu.try_lock()) { return false; } bool found = false; @@ -1729,7 +1710,7 @@ bool GetFileMappingHint(const void **start, const void **end, uint64_t *offset, break; } } - g_file_mapping_mu.Unlock(); + g_file_mapping_mu.unlock(); return found; } @@ -1765,7 +1746,8 @@ ABSL_NAMESPACE_END } // namespace absl extern "C" bool AbslInternalGetFileMappingHint(const void **start, - const void **end, uint64_t *offset, + const void **end, + uint64_t *offset, const char **filename) { return absl::debugging_internal::GetFileMappingHint(start, end, offset, filename); 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 620af2b5aa..532721d23f 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/flags/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/flags/BUILD.bazel @@ -14,6 +14,9 @@ # limitations under the License. # +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/functional/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/functional/BUILD.bazel index aeed3b668e..c2bb96d7d1 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/functional/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/functional/BUILD.bazel @@ -14,6 +14,9 @@ # limitations under the License. # +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/functional/any_invocable.h b/naiveproxy/src/third_party/abseil-cpp/absl/functional/any_invocable.h index 43ea9af882..524345d5c0 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/functional/any_invocable.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/functional/any_invocable.h @@ -295,22 +295,22 @@ class AnyInvocable : private internal_any_invocable::Impl { // Equality operators - // Returns `true` if `*this` is empty. + // Returns `true` if `f` is empty. friend bool operator==(const AnyInvocable& f, std::nullptr_t) noexcept { return !f.HasValue(); } - // Returns `true` if `*this` is empty. + // Returns `true` if `f` is empty. friend bool operator==(std::nullptr_t, const AnyInvocable& f) noexcept { return !f.HasValue(); } - // Returns `false` if `*this` is empty. + // Returns `false` if `f` is empty. friend bool operator!=(const AnyInvocable& f, std::nullptr_t) noexcept { return f.HasValue(); } - // Returns `false` if `*this` is empty. + // Returns `false` if `f` is empty. friend bool operator!=(std::nullptr_t, const AnyInvocable& f) noexcept { return f.HasValue(); } diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/hash/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/hash/BUILD.bazel index 0488227160..187689f880 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/hash/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/hash/BUILD.bazel @@ -14,6 +14,9 @@ # limitations under the License. # +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", @@ -76,14 +79,13 @@ cc_library( cc_test( name = "hash_test", + size = "large", srcs = [ "hash_test.cc", "internal/hash_test.h", ], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, - # TODO(b/417700722): Fix HashValueTest.PointerAlignment reporting more collisions under ubsan. - tags = ["noubsan"], deps = [ ":hash", ":hash_testing", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/hash/internal/hash.cc b/naiveproxy/src/third_party/abseil-cpp/absl/hash/internal/hash.cc index 87d2061c6a..a693d5c1f7 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/hash/internal/hash.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/hash/internal/hash.cc @@ -100,10 +100,10 @@ uint64_t Mix32Bytes(const uint8_t* ptr, uint64_t current_state) { ABSL_ATTRIBUTE_ALWAYS_INLINE inline uint64_t HashBlockOn32Bit( const unsigned char* data, size_t len, uint64_t state) { // TODO(b/417141985): expose and use CityHash32WithSeed. - return Mix( - PrecombineLengthMix(state, len) ^ - hash_internal::CityHash32(reinterpret_cast(data), len), - kMul); + // Note: we can't use PrecombineLengthMix here because len can be up to 1024. + return CombineRawImpl( + state + len, + hash_internal::CityHash32(reinterpret_cast(data), len)); } ABSL_ATTRIBUTE_NOINLINE uint64_t diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/hash/internal/hash.h b/naiveproxy/src/third_party/abseil-cpp/absl/hash/internal/hash.h index 0ec5e368ba..8c584b207a 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/hash/internal/hash.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/hash/internal/hash.h @@ -409,8 +409,10 @@ H hash_weakly_mixed_integer(H hash_state, WeaklyMixedInteger value) { template typename std::enable_if::value, H>::type AbslHashValue( H hash_state, B value) { + // We use ~size_t{} instead of 1 so that all bits are different between + // true/false instead of only 1. return H::combine(std::move(hash_state), - static_cast(value ? 1 : 0)); + static_cast(value ? ~size_t{} : 0)); } // AbslHashValue() for hashing enum values @@ -490,8 +492,9 @@ std::enable_if_t::value, H> AbslHashValue(H hash_state, auto v = reinterpret_cast(ptr); // Due to alignment, pointers tend to have low bits as zero, and the next few // bits follow a pattern since they are also multiples of some base value. - // Mix pointers twice to ensure we have good entropy in low bits. - return H::combine(std::move(hash_state), v, v); + // The PointerAlignment test verifies that our mixing is good enough to handle + // these cases. + return H::combine(std::move(hash_state), v); } // AbslHashValue() for hashing nullptr_t @@ -933,22 +936,7 @@ hash_range_or_bytes(H hash_state, const T* data, size_t size) { hash_internal::WeaklyMixedInteger{size}); } -// Extremely weak mixture of length that is added to the state before combining -// the data. It is used only for small strings. -inline uint64_t PrecombineLengthMix(uint64_t state, size_t len) { - // The length is always one byte here. We place it to 4th byte for the - // following reasons: - // 1. 4th byte is unused for very short strings 0-3 bytes. - // 2. 4th byte is duplicated for 4 bytes string. - // 3. 4th byte is in the middle and mixed well for 5-8 bytes strings. - // - // There were experiments with adding just `len` here. - // Also seems have slightly better performance overall, that gives collisions - // for small strings. - return state + (uint64_t{len} << 24); -} - - inline constexpr uint64_t kMul = uint64_t{0xdcb22ca68cb134ed}; +inline constexpr uint64_t kMul = uint64_t{0x79d5f9e0de1e8cf5}; // Random data taken from the hexadecimal digits of Pi's fractional component. // https://en.wikipedia.org/wiki/Nothing-up-my-sleeve_number @@ -957,25 +945,20 @@ ABSL_CACHELINE_ALIGNED inline constexpr uint64_t kStaticRandomData[] = { 0x082e'fa98'ec4e'6c89, 0x4528'21e6'38d0'1377, }; +// Extremely weak mixture of length that is mixed into the state before +// combining the data. It is used only for small strings. This also ensures that +// we have high entropy in all bits of the state. +inline uint64_t PrecombineLengthMix(uint64_t state, size_t len) { + ABSL_ASSUME(len + sizeof(uint64_t) <= sizeof(kStaticRandomData)); + uint64_t data = absl::base_internal::UnalignedLoad64( + reinterpret_cast(&kStaticRandomData[0]) + len); + return state ^ data; +} + ABSL_ATTRIBUTE_ALWAYS_INLINE inline uint64_t Mix(uint64_t lhs, uint64_t rhs) { - // For 32 bit platforms we are trying to use all 64 lower bits. - if constexpr (sizeof(size_t) < 8) { - uint64_t m = lhs * rhs; - return m ^ (m >> 32); - } - // absl::uint128 is not an alias or a thin wrapper around the intrinsic. - // We use the intrinsic when available to improve performance. - // TODO(b/399425325): Try to remove MulType since compiler seem to generate - // the same code with just absl::uint128. - // See https://gcc.godbolt.org/z/s3hGarraG for details. -#ifdef ABSL_HAVE_INTRINSIC_INT128 - using MulType = __uint128_t; -#else // ABSL_HAVE_INTRINSIC_INT128 - using MulType = absl::uint128; -#endif // ABSL_HAVE_INTRINSIC_INT128 - // Though the 128-bit product on AArch64 needs two instructions, it is - // still a good balance between speed and hash quality. - MulType m = lhs; + // Though the 128-bit product needs multiple instructions on non-x86-64 + // platforms, it is still a good balance between speed and hash quality. + absl::uint128 m = lhs; m *= rhs; return Uint128High64(m) ^ Uint128Low64(m); } @@ -1037,6 +1020,11 @@ inline uint32_t Read1To3(const unsigned char* p, size_t len) { return mem0 | mem1; } +ABSL_ATTRIBUTE_ALWAYS_INLINE inline uint64_t CombineRawImpl(uint64_t state, + uint64_t value) { + return Mix(state ^ value, kMul); +} + // Slow dispatch path for calls to CombineContiguousImpl with a size argument // larger than inlined size. Has the same effect as calling // CombineContiguousImpl() repeatedly with the chunk stride size. @@ -1058,7 +1046,7 @@ ABSL_ATTRIBUTE_ALWAYS_INLINE inline uint64_t CombineSmallContiguousImpl( // Empty string must modify the state. v = 0x57; } - return Mix(state ^ v, kMul); + return CombineRawImpl(state, v); } ABSL_ATTRIBUTE_ALWAYS_INLINE inline uint64_t CombineContiguousImpl9to16( @@ -1266,7 +1254,7 @@ class ABSL_DLL MixingHashState : public HashStateBase { template ::value, int> = 0> static size_t hash_with_seed(T value, size_t seed) { return static_cast( - Mix(seed ^ static_cast>(value), kMul)); + CombineRawImpl(seed, static_cast>(value))); } template ::value, int> = 0> @@ -1304,7 +1292,7 @@ class ABSL_DLL MixingHashState : public HashStateBase { // optimize Read1To3 and Read4To8 differently for the string case. static MixingHashState combine_raw(MixingHashState hash_state, uint64_t value) { - return MixingHashState(Mix(hash_state.state_ ^ value, kMul)); + return MixingHashState(CombineRawImpl(hash_state.state_, value)); } static MixingHashState combine_weakly_mixed_integer( diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/log/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/log/BUILD.bazel index 62ece45129..d4b37307de 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/log/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/log/BUILD.bazel @@ -14,6 +14,8 @@ # limitations under the License. # +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/log/check_test_impl.inc b/naiveproxy/src/third_party/abseil-cpp/absl/log/check_test_impl.inc index 37226a364f..5a7caf47d0 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/log/check_test_impl.inc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/log/check_test_impl.inc @@ -265,6 +265,26 @@ TEST(CHECKTest, TestBinaryChecksWithNullptr) { ABSL_TEST_CHECK_NE(nullptr, p_not_null); } +struct ExampleTypeThatHasNoStreamOperator { + bool x; + + bool operator==(const ExampleTypeThatHasNoStreamOperator& other) const { + return x == other.x; + } + bool operator==(const bool& other) const { return x == other; } +}; + +TEST(CHECKDeathTest, TestBinaryChecksWithUnprintable) { + ExampleTypeThatHasNoStreamOperator a{true}; + ExampleTypeThatHasNoStreamOperator b{false}; + ABSL_TEST_CHECK_EQ(a, a); + EXPECT_DEATH(ABSL_TEST_CHECK_EQ(a, b), + "Check failed: a == b \\(UNPRINTABLE vs. UNPRINTABLE\\)"); + ABSL_TEST_CHECK_EQ(a, true); + EXPECT_DEATH(ABSL_TEST_CHECK_EQ(a, false), + "Check failed: a == false \\(UNPRINTABLE vs. 0\\)"); +} + #if GTEST_HAS_DEATH_TEST // Test logging of various char-typed values by failing CHECK*(). diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/BUILD.bazel index 953b690e98..1ba9d7662a 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/BUILD.bazel @@ -14,6 +14,9 @@ # limitations under the License. # +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/check_op.cc b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/check_op.cc index 23db63bf10..5db98dd9cd 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/check_op.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/check_op.cc @@ -101,6 +101,8 @@ void MakeCheckOpValueString(std::ostream& os, const void* p) { } } +void MakeCheckOpUnprintableString(std::ostream& os) { os << "UNPRINTABLE"; } + // Helper functions for string comparisons. #define DEFINE_CHECK_STROP_IMPL(name, func, expected) \ const char* absl_nullable Check##func##expected##Impl( \ diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/check_op.h b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/check_op.h index d7b55f6f1a..4554475dad 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/check_op.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/check_op.h @@ -224,6 +224,19 @@ void MakeCheckOpValueString(std::ostream& os, signed char v); void MakeCheckOpValueString(std::ostream& os, unsigned char v); void MakeCheckOpValueString(std::ostream& os, const void* absl_nullable p); +void MakeCheckOpUnprintableString(std::ostream& os); + +// A wrapper for types that have no operator<<. +struct UnprintableWrapper { + template + explicit UnprintableWrapper(const T&) {} + + friend std::ostream& operator<<(std::ostream& os, const UnprintableWrapper&) { + MakeCheckOpUnprintableString(os); + return os; + } +}; + namespace detect_specialization { // MakeCheckOpString is being specialized for every T and U pair that is being @@ -353,6 +366,15 @@ struct is_streamable() << std::declval())>> : std::true_type {}; +// This overload triggers when T is neither possible to print nor an enum. +template +std::enable_if_t, std::is_enum, + std::is_pointer, std::is_same, + is_streamable, HasAbslStringify>>, + UnprintableWrapper> +Detect(...); + // This overload triggers when T is a scoped enum that has not defined an output // stream operator (operator<<) or AbslStringify. It causes the enum value to be // converted to a type that can be streamed. For consistency with other enums, a diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/vlog_config.cc b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/vlog_config.cc index f7c61bed52..0a460d937d 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/vlog_config.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/vlog_config.cc @@ -90,7 +90,7 @@ struct VModuleInfo final { // To avoid problems with the heap checker which calls into `VLOG`, `mutex` must // be a `SpinLock` that prevents fiber scheduling instead of a `Mutex`. ABSL_CONST_INIT absl::base_internal::SpinLock mutex( - absl::kConstInit, absl::base_internal::SCHEDULE_KERNEL_ONLY); + absl::base_internal::SCHEDULE_KERNEL_ONLY); // `GetUpdateSitesMutex()` serializes updates to all of the sites (i.e. those in // `site_list_head`) themselves. @@ -267,7 +267,7 @@ void UpdateVLogSites() ABSL_UNLOCK_FUNCTION(mutex) // have to wait on all updates in order to acquire `mutex` and initialize // themselves. absl::MutexLock ul(GetUpdateSitesMutex()); - mutex.Unlock(); + mutex.unlock(); VLogSite* n = site_list_head.load(std::memory_order_seq_cst); // Because sites are added to the list in the order they are executed, there // tend to be clusters of entries with the same file. @@ -299,7 +299,7 @@ void UpdateVModule(absl::string_view vmodule) if (!absl::SimpleAtoi(glob_level.substr(eq + 1), &level)) continue; glob_levels.emplace_back(glob, level); } - mutex.Lock(); // Unlocked by UpdateVLogSites(). + mutex.lock(); // unlocked by UpdateVLogSites(). get_vmodule_info().clear(); for (const auto& it : glob_levels) { const absl::string_view glob = it.first; @@ -311,10 +311,10 @@ void UpdateVModule(absl::string_view vmodule) int UpdateGlobalVLogLevel(int v) ABSL_LOCKS_EXCLUDED(mutex, GetUpdateSitesMutex()) { - mutex.Lock(); // Unlocked by UpdateVLogSites(). + mutex.lock(); // unlocked by UpdateVLogSites(). const int old_global_v = global_v; if (v == global_v) { - mutex.Unlock(); + mutex.unlock(); return old_global_v; } global_v = v; @@ -324,7 +324,7 @@ int UpdateGlobalVLogLevel(int v) int PrependVModule(absl::string_view module_pattern, int log_level) ABSL_LOCKS_EXCLUDED(mutex, GetUpdateSitesMutex()) { - mutex.Lock(); // Unlocked by UpdateVLogSites(). + mutex.lock(); // unlocked by UpdateVLogSites(). int old_v = PrependVModuleLocked(module_pattern, log_level); UpdateVLogSites(); return old_v; diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/memory/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/memory/BUILD.bazel index d50a502e70..81e12facae 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/memory/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/memory/BUILD.bazel @@ -14,6 +14,8 @@ # limitations under the License. # +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/meta/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/meta/BUILD.bazel index d01cb8a217..f6efa42be3 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/meta/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/meta/BUILD.bazel @@ -14,6 +14,8 @@ # limitations under the License. # +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/numeric/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/numeric/BUILD.bazel index f455d1e917..edfe6b6fce 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/numeric/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/numeric/BUILD.bazel @@ -12,6 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/profiling/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/profiling/BUILD.bazel index 4a3c64430e..5afdb96beb 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/profiling/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/profiling/BUILD.bazel @@ -12,6 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", @@ -141,3 +144,44 @@ cc_binary( "@google_benchmark//:benchmark_main", ], ) + +cc_library( + name = "profile_builder", + srcs = ["internal/profile_builder.cc"], + hdrs = ["internal/profile_builder.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//absl:__subpackages__", + ], + deps = [ + "//absl/base", + "//absl/base:config", + "//absl/base:raw_logging_internal", + "//absl/container:btree", + "//absl/container:flat_hash_map", + "//absl/strings", + "//absl/types:span", + ], +) + +cc_library( + name = "hashtable", + srcs = ["hashtable.cc"], + hdrs = ["hashtable.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//absl:__subpackages__", + ], + deps = [ + ":profile_builder", + "//absl/base:config", + "//absl/container:hashtablez_sampler", + "//absl/status:statusor", + "//absl/strings", + "//absl/strings:string_view", + "//absl/time", + "//absl/types:span", + ], +) diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/profiling/BUILD.gn b/naiveproxy/src/third_party/abseil-cpp/absl/profiling/BUILD.gn index 16b37de58a..23764a27f5 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/profiling/BUILD.gn +++ b/naiveproxy/src/third_party/abseil-cpp/absl/profiling/BUILD.gn @@ -63,3 +63,32 @@ absl_test("periodic_sampler_test") { "//third_party/abseil-cpp/absl/base:core_headers", ] } + +absl_source_set("profile_builder") { + sources = [ "internal/profile_builder.cc" ] + public = [ "internal/profile_builder.h" ] + deps = [ + "//third_party/abseil-cpp/absl/base", + "//third_party/abseil-cpp/absl/base:config", + "//third_party/abseil-cpp/absl/base:raw_logging_internal", + "//third_party/abseil-cpp/absl/container:btree", + "//third_party/abseil-cpp/absl/container:flat_hash_map", + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:span", + ] +} + +absl_source_set("hashtable") { + sources = [ "hashtable.cc" ] + public = [ "hashtable.h" ] + deps = [ + ":profile_builder", + "//third_party/abseil-cpp/absl/base:config", + "//third_party/abseil-cpp/absl/container:hashtablez_sampler", + "//third_party/abseil-cpp/absl/status:statusor", + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/strings:string_view", + "//third_party/abseil-cpp/absl/time", + "//third_party/abseil-cpp/absl/types:span", + ] +} diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/profiling/CMakeLists.txt b/naiveproxy/src/third_party/abseil-cpp/absl/profiling/CMakeLists.txt index 84b8b3b894..4807f0dde6 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/profiling/CMakeLists.txt +++ b/naiveproxy/src/third_party/abseil-cpp/absl/profiling/CMakeLists.txt @@ -92,3 +92,40 @@ absl_cc_test( GTest::gmock_main ) +# Internal-only target, do not depend on directly +absl_cc_library( + NAME + profile_builder + HDRS + "internal/profile_builder.h" + SRCS + "internal/profile_builder.cc" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::config + absl::core_headers + absl::raw_logging_internal + absl::flat_hash_map + absl::btree + absl::strings + absl::span +) + +absl_cc_library( + NAME + hashtable_profiler + HDRS + "hashtable.h" + SRCS + "hashtable.cc" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::profile_builder + absl::config + absl::core_headers + absl::strings + absl::span + absl::hashtablez_sampler +) diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/profiling/hashtable.cc b/naiveproxy/src/third_party/abseil-cpp/absl/profiling/hashtable.cc new file mode 100644 index 0000000000..bfec0d56c3 --- /dev/null +++ b/naiveproxy/src/third_party/abseil-cpp/absl/profiling/hashtable.cc @@ -0,0 +1,124 @@ +// Copyright 2025 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/profiling/hashtable.h" + +#include +#include +#include +#include +#include +#include + +#include "absl/base/config.h" +#include "absl/container/internal/hashtablez_sampler.h" +#include "absl/profiling/internal/profile_builder.h" +#include "absl/status/statusor.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" +#include "absl/time/clock.h" +#include "absl/time/time.h" +#include "absl/types/span.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN + +StatusOr MarshalHashtableProfile() { + return debugging_internal::MarshalHashtableProfile( + container_internal::GlobalHashtablezSampler(), Now()); +} + +namespace debugging_internal { + +StatusOr MarshalHashtableProfile( + container_internal::HashtablezSampler& sampler, Time now) { + static constexpr absl::string_view kDropFrames = + "(::)?absl::container_internal::.*|" + "(::)?absl::(flat|node)_hash_(map|set).*"; + + ProfileBuilder builder; + StringId drop_frames_id = builder.InternString(kDropFrames); + builder.set_drop_frames_id(drop_frames_id); + builder.AddSampleType(builder.InternString("capacity"), + builder.InternString("count")); + builder.set_default_sample_type_id(builder.InternString("capacity")); + + const auto capacity_id = builder.InternString("capacity"); + const auto size_id = builder.InternString("size"); + const auto num_erases_id = builder.InternString("num_erases"); + const auto num_rehashes_id = builder.InternString("num_rehashes"); + const auto max_probe_length_id = builder.InternString("max_probe_length"); + const auto total_probe_length_id = builder.InternString("total_probe_length"); + const auto stuck_bits_id = builder.InternString("stuck_bits"); + const auto inline_element_size_id = + builder.InternString("inline_element_size"); + const auto key_size_id = builder.InternString("key_size"); + const auto value_size_id = builder.InternString("value_size"); + const auto soo_capacity_id = builder.InternString("soo_capacity"); + const auto checksum_id = builder.InternString("checksum"); + const auto table_age_id = builder.InternString("table_age"); + const auto max_reserve_id = builder.InternString("max_reserve"); + + size_t dropped = + sampler.Iterate([&](const container_internal::HashtablezInfo& info) { + const size_t capacity = info.capacity.load(std::memory_order_relaxed); + std::vector> labels; + + auto add_label = [&](StringId tag, uint64_t value) { + if (value == 0) { + return; + } + labels.emplace_back(tag, static_cast(value)); + }; + + add_label(capacity_id, capacity); + add_label(size_id, info.size.load(std::memory_order_relaxed)); + add_label(num_erases_id, + info.num_erases.load(std::memory_order_relaxed)); + add_label(num_rehashes_id, + info.num_rehashes.load(std::memory_order_relaxed)); + add_label(max_probe_length_id, + info.max_probe_length.load(std::memory_order_relaxed)); + add_label(total_probe_length_id, + info.total_probe_length.load(std::memory_order_relaxed)); + add_label(stuck_bits_id, + (info.hashes_bitwise_and.load(std::memory_order_relaxed) | + ~info.hashes_bitwise_or.load(std::memory_order_relaxed))); + add_label(inline_element_size_id, info.inline_element_size); + add_label(key_size_id, info.key_size); + add_label(value_size_id, info.value_size); + add_label(soo_capacity_id, info.soo_capacity); + add_label(checksum_id, + info.hashes_bitwise_xor.load(std::memory_order_relaxed)); + add_label( + table_age_id, + static_cast(ToInt64Microseconds(now - info.create_time))); + add_label(max_reserve_id, + info.max_reserve.load(std::memory_order_relaxed)); + builder.AddSample(static_cast(capacity) * info.weight, + MakeSpan(info.stack, info.depth), labels); + }); + + // TODO(b/262310142): Make this more structured data. + StringId comment_id = + builder.InternString(StrCat("dropped_samples: ", dropped)); + builder.set_comment_id(comment_id); + builder.AddCurrentMappings(); + return std::move(builder).Emit(); +} + +} // namespace debugging_internal +ABSL_NAMESPACE_END +} // namespace absl diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/profiling/hashtable.h b/naiveproxy/src/third_party/abseil-cpp/absl/profiling/hashtable.h new file mode 100644 index 0000000000..9e490dcdb8 --- /dev/null +++ b/naiveproxy/src/third_party/abseil-cpp/absl/profiling/hashtable.h @@ -0,0 +1,40 @@ +// Copyright 2025 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_PROFILING_HASHTABLE_H_ +#define ABSL_PROFILING_HASHTABLE_H_ + +#include +#include + +#include "absl/container/internal/hashtablez_sampler.h" +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" +#include "absl/time/time.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN + +absl::StatusOr MarshalHashtableProfile(); + +namespace debugging_internal { + +absl::StatusOr MarshalHashtableProfile( + container_internal::HashtablezSampler& sampler, absl::Time now); + +} // namespace debugging_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_PROFILING_HASHTABLE_H_ diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/profiling/internal/profile_builder.cc b/naiveproxy/src/third_party/abseil-cpp/absl/profiling/internal/profile_builder.cc new file mode 100644 index 0000000000..f0bb40b732 --- /dev/null +++ b/naiveproxy/src/third_party/abseil-cpp/absl/profiling/internal/profile_builder.cc @@ -0,0 +1,462 @@ +// Copyright 2025 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/profiling/internal/profile_builder.h" + +#ifdef __linux__ +#include +#include +#endif // __linux__ + +#include +#include +#include +#include +#include +#include + +#include "absl/base/casts.h" +#include "absl/base/config.h" +#include "absl/base/internal/raw_logging.h" +#include "absl/strings/escaping.h" +#include "absl/strings/str_cat.h" +#include "absl/types/span.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace debugging_internal { + +namespace { + +// This file contains a simplified implementation of the pprof profile builder, +// which avoids a dependency on protobuf. +// +// The canonical profile proto definition is at +// https://github.com/google/pprof/blob/master/proto/profile.proto +// +// Wire-format encoding is a simple sequence of (tag, value) pairs. The tag +// is a varint-encoded integer, where the low 3 bits are the wire type, and the +// high bits are the field number. +// +// For the fields we care about, we'll be using the following wire types: +// +// Wire Type 0: Varint-encoded integer. +// Wire Type 2: Length-delimited. Used for strings and sub-messages. +enum class WireType { + kVarint = 0, + kLengthDelimited = 2, +}; + +#ifdef __linux__ +// Returns the Phdr of the first segment of the given type. +const ElfW(Phdr) * GetFirstSegment(const dl_phdr_info* const info, + const ElfW(Word) segment_type) { + for (int i = 0; i < info->dlpi_phnum; ++i) { + if (info->dlpi_phdr[i].p_type == segment_type) { + return &info->dlpi_phdr[i]; + } + } + return nullptr; +} + +// Return DT_SONAME for the given image. If there is no PT_DYNAMIC or if +// PT_DYNAMIC does not contain DT_SONAME, return nullptr. +static const char* GetSoName(const dl_phdr_info* const info) { + const ElfW(Phdr)* const pt_dynamic = GetFirstSegment(info, PT_DYNAMIC); + if (pt_dynamic == nullptr) { + return nullptr; + } + const ElfW(Dyn)* dyn = + reinterpret_cast(info->dlpi_addr + pt_dynamic->p_vaddr); + const ElfW(Dyn)* dt_strtab = nullptr; + const ElfW(Dyn)* dt_strsz = nullptr; + const ElfW(Dyn)* dt_soname = nullptr; + for (; dyn->d_tag != DT_NULL; ++dyn) { + if (dyn->d_tag == DT_SONAME) { + dt_soname = dyn; + } else if (dyn->d_tag == DT_STRTAB) { + dt_strtab = dyn; + } else if (dyn->d_tag == DT_STRSZ) { + dt_strsz = dyn; + } + } + if (dt_soname == nullptr) { + return nullptr; + } + ABSL_RAW_CHECK(dt_strtab != nullptr, "Unexpected nullptr"); + ABSL_RAW_CHECK(dt_strsz != nullptr, "Unexpected nullptr"); + const char* const strtab = reinterpret_cast( + info->dlpi_addr + static_cast(dt_strtab->d_un.d_val)); + ABSL_RAW_CHECK(dt_soname->d_un.d_val < dt_strsz->d_un.d_val, + "Unexpected order"); + return strtab + dt_soname->d_un.d_val; +} + +// Helper function to get the build ID of a shared object. +std::string GetBuildId(const dl_phdr_info* const info) { + std::string result; + + // pt_note contains entries (of type ElfW(Nhdr)) starting at + // info->dlpi_addr + pt_note->p_vaddr + // with length + // pt_note->p_memsz + // + // The length of each entry is given by + // Align(sizeof(ElfW(Nhdr)) + nhdr->n_namesz) + Align(nhdr->n_descsz) + for (int i = 0; i < info->dlpi_phnum; ++i) { + const ElfW(Phdr)* pt_note = &info->dlpi_phdr[i]; + if (pt_note->p_type != PT_NOTE) continue; + + const char* note = + reinterpret_cast(info->dlpi_addr + pt_note->p_vaddr); + const char* const last = note + pt_note->p_filesz; + const ElfW(Xword) align = pt_note->p_align; + while (note < last) { + const ElfW(Nhdr)* const nhdr = reinterpret_cast(note); + if (note + sizeof(*nhdr) > last) { + // Corrupt PT_NOTE + break; + } + + // Both the start and end of the descriptor are aligned by sh_addralign + // (= p_align). + const ElfW(Xword) desc_start = + (sizeof(*nhdr) + nhdr->n_namesz + align - 1) & -align; + const ElfW(Xword) size = + desc_start + ((nhdr->n_descsz + align - 1) & -align); + + // Beware of wrap-around. + if (nhdr->n_namesz >= static_cast(-align) || + nhdr->n_descsz >= static_cast(-align) || + desc_start < sizeof(*nhdr) || size < desc_start || + size > static_cast(last - note)) { + // Corrupt PT_NOTE + break; + } + + if (nhdr->n_type == NT_GNU_BUILD_ID) { + const char* const note_name = note + sizeof(*nhdr); + // n_namesz is the length of note_name. + if (nhdr->n_namesz == 4 && memcmp(note_name, "GNU\0", 4) == 0) { + if (!result.empty()) { + // Repeated build-ids. Ignore them. + return ""; + } + result = absl::BytesToHexString( + absl::string_view(note + desc_start, nhdr->n_descsz)); + } + } + note += size; + } + } + + return result; +} +#endif // __linux__ + +// A varint-encoded integer. +struct Varint { + explicit Varint(uint64_t v) : value(v) {} + explicit Varint(StringId v) : value(static_cast(v)) {} + explicit Varint(LocationId v) : value(static_cast(v)) {} + explicit Varint(MappingId v) : value(static_cast(v)) {} + + uint64_t value; + + template + friend void AbslStringify(Sink& sink, const Varint& v) { + char buf[10]; + char* p = buf; + uint64_t u = v.value; + while (u >= 0x80) { + *p++ = static_cast((u & 0x7f) | 0x80); + u >>= 7; + } + *p++ = static_cast(u); + sink.Append(absl::string_view(buf, static_cast(p - buf))); + } +}; + +struct Tag { + int field_number; + WireType wire_type; + + template + friend void AbslStringify(Sink& sink, const Tag& t) { + absl::Format(&sink, "%v", + Varint((static_cast(t.field_number) << 3) | + static_cast(t.wire_type))); + } +}; + +struct LengthDelimited { + int field_number; + absl::string_view value; + + template + friend void AbslStringify(Sink& sink, const LengthDelimited& ld) { + absl::Format(&sink, "%v%v%v", + Tag{ld.field_number, WireType::kLengthDelimited}, + Varint(ld.value.size()), ld.value); + } +}; + +struct VarintField { + int field_number; + Varint value; + + template + friend void AbslStringify(Sink& sink, const VarintField& vf) { + absl::Format(&sink, "%v%v", Tag{vf.field_number, WireType::kVarint}, + vf.value); + } +}; + +} // namespace + +StringId ProfileBuilder::InternString(absl::string_view str) { + if (str.empty()) return StringId(0); + return string_table_.emplace(str, StringId(string_table_.size())) + .first->second; +} + +LocationId ProfileBuilder::InternLocation(const void* address) { + return location_table_ + .emplace(absl::bit_cast(address), + LocationId(location_table_.size() + 1)) + .first->second; +} + +void ProfileBuilder::AddSample( + int64_t value, absl::Span stack, + absl::Span> labels) { + std::string sample_proto; + absl::StrAppend( + &sample_proto, + VarintField{SampleProto::kValue, Varint(static_cast(value))}); + + for (const void* addr : stack) { + // Profile addresses are raw stack unwind addresses, so they should be + // adjusted by -1 to land inside the call instruction (although potentially + // misaligned). + absl::StrAppend( + &sample_proto, + VarintField{SampleProto::kLocationId, + Varint(InternLocation(absl::bit_cast( + absl::bit_cast(addr) - 1)))}); + } + + for (const auto& label : labels) { + std::string label_proto = + absl::StrCat(VarintField{LabelProto::kKey, Varint(label.first)}, + VarintField{LabelProto::kNum, + Varint(static_cast(label.second))}); + absl::StrAppend(&sample_proto, + LengthDelimited{SampleProto::kLabel, label_proto}); + } + samples_.push_back(std::move(sample_proto)); +} + +void ProfileBuilder::AddSampleType(StringId type, StringId unit) { + std::string sample_type_proto = + absl::StrCat(VarintField{ValueTypeProto::kType, Varint(type)}, + VarintField{ValueTypeProto::kUnit, Varint(unit)}); + sample_types_.push_back(std::move(sample_type_proto)); +} + +MappingId ProfileBuilder::AddMapping(uintptr_t memory_start, + uintptr_t memory_limit, + uintptr_t file_offset, + absl::string_view filename, + absl::string_view build_id) { + size_t index = mappings_.size() + 1; + auto [it, inserted] = mapping_table_.emplace(memory_start, index); + if (!inserted) { + return static_cast(it->second); + } + + Mapping m; + m.start = memory_start; + m.limit = memory_limit; + m.offset = file_offset; + m.filename = std::string(filename); + m.build_id = std::string(build_id); + + mappings_.push_back(std::move(m)); + return static_cast(index); +} + +std::string ProfileBuilder::Emit() && { + std::string profile_proto; + for (const auto& sample_type : sample_types_) { + absl::StrAppend(&profile_proto, + LengthDelimited{ProfileProto::kSampleType, sample_type}); + } + for (const auto& sample : samples_) { + absl::StrAppend(&profile_proto, + LengthDelimited{ProfileProto::kSample, sample}); + } + + // Build mapping table. + for (size_t i = 0, n = mappings_.size(); i < n; ++i) { + const auto& mapping = mappings_[i]; + std::string mapping_proto = absl::StrCat( + VarintField{MappingProto::kId, Varint(static_cast(i + 1))}, + VarintField{MappingProto::kMemoryStart, Varint(mapping.start)}, + VarintField{MappingProto::kMemoryLimit, Varint(mapping.limit)}, + VarintField{MappingProto::kFileOffset, Varint(mapping.offset)}, + VarintField{MappingProto::kFilename, + Varint(InternString(mapping.filename))}, + VarintField{MappingProto::kBuildId, + Varint(InternString(mapping.build_id))}); + + absl::StrAppend(&profile_proto, + LengthDelimited{ProfileProto::kMapping, mapping_proto}); + } + + // Build location table. + for (const auto& [address, id] : location_table_) { + std::string location = + absl::StrCat(VarintField{LocationProto::kId, Varint(id)}, + VarintField{LocationProto::kAddress, Varint(address)}); + + if (!mappings_.empty()) { + // Find the mapping ID. + auto it = mapping_table_.upper_bound(address); + if (it != mapping_table_.begin()) { + --it; + } + + // If *it contains address, add mapping to location. + const size_t mapping_index = it->second; + const Mapping& mapping = mappings_[mapping_index - 1]; + + if (it->first <= address && address < mapping.limit) { + absl::StrAppend( + &location, + VarintField{LocationProto::kMappingId, + Varint(static_cast(mapping_index))}); + } + } + + absl::StrAppend(&profile_proto, + LengthDelimited{ProfileProto::kLocation, location}); + } + + std::string string_table_proto; + std::vector sorted_strings(string_table_.size()); + for (const auto& p : string_table_) { + sorted_strings[static_cast(p.second)] = p.first; + } + for (const auto& s : sorted_strings) { + absl::StrAppend(&string_table_proto, + LengthDelimited{ProfileProto::kStringTable, s}); + } + absl::StrAppend(&profile_proto, VarintField{ProfileProto::kDropFrames, + Varint(drop_frames_id_)}); + absl::StrAppend(&profile_proto, + VarintField{ProfileProto::kComment, Varint(comment_id_)}); + absl::StrAppend(&profile_proto, VarintField{ProfileProto::kDefaultSampleType, + Varint(default_sample_type_id_)}); + return absl::StrCat(string_table_proto, profile_proto); +} + +void ProfileBuilder::set_drop_frames_id(StringId drop_frames_id) { + drop_frames_id_ = drop_frames_id; +} + +void ProfileBuilder::set_comment_id(StringId comment_id) { + comment_id_ = comment_id; +} + +void ProfileBuilder::set_default_sample_type_id( + StringId default_sample_type_id) { + default_sample_type_id_ = default_sample_type_id; +} + +void ProfileBuilder::AddCurrentMappings() { +#ifdef __linux__ + dl_iterate_phdr( + +[](dl_phdr_info* info, size_t, void* data) { + auto& builder = *reinterpret_cast(data); + + // Skip dummy entry introduced since glibc 2.18. + if (info->dlpi_phdr == nullptr && info->dlpi_phnum == 0) { + return 0; + } + + const bool is_main_executable = builder.mappings_.empty(); + + // Evaluate all the loadable segments. + for (int i = 0; i < info->dlpi_phnum; ++i) { + if (info->dlpi_phdr[i].p_type != PT_LOAD) { + continue; + } + const ElfW(Phdr)* pt_load = &info->dlpi_phdr[i]; + + ABSL_RAW_CHECK(pt_load != nullptr, "Unexpected nullptr"); + + // Extract data. + const size_t memory_start = info->dlpi_addr + pt_load->p_vaddr; + const size_t memory_limit = memory_start + pt_load->p_memsz; + const size_t file_offset = pt_load->p_offset; + + // Storage for path to executable as dlpi_name isn't populated for the + // main executable. +1 to allow for the null terminator that readlink + // does not add. + char self_filename[PATH_MAX + 1]; + const char* filename = info->dlpi_name; + if (filename == nullptr || filename[0] == '\0') { + // This is either the main executable or the VDSO. The main + // executable is always the first entry processed by callbacks. + if (is_main_executable) { + // This is the main executable. + ssize_t ret = readlink("/proc/self/exe", self_filename, + sizeof(self_filename) - 1); + if (ret >= 0 && + static_cast(ret) < sizeof(self_filename)) { + self_filename[ret] = '\0'; + filename = self_filename; + } + } else { + // This is the VDSO. + filename = GetSoName(info); + } + } + + char resolved_path[PATH_MAX]; + absl::string_view resolved_filename; + if (realpath(filename, resolved_path)) { + resolved_filename = resolved_path; + } else { + resolved_filename = filename; + } + + const std::string build_id = GetBuildId(info); + + // Add to profile. + builder.AddMapping(memory_start, memory_limit, file_offset, + resolved_filename, build_id); + } + // Keep going. + return 0; + }, + this); +#endif // __linux__ +} + +} // namespace debugging_internal +ABSL_NAMESPACE_END +} // namespace absl diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/profiling/internal/profile_builder.h b/naiveproxy/src/third_party/abseil-cpp/absl/profiling/internal/profile_builder.h new file mode 100644 index 0000000000..45075e6015 --- /dev/null +++ b/naiveproxy/src/third_party/abseil-cpp/absl/profiling/internal/profile_builder.h @@ -0,0 +1,138 @@ +// Copyright 2025 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_PROFILING_INTERNAL_PROFILE_BUILDER_H_ +#define ABSL_PROFILING_INTERNAL_PROFILE_BUILDER_H_ + +#include +#include +#include +#include + +#include "absl/container/btree_map.h" +#include "absl/container/flat_hash_map.h" +#include "absl/strings/string_view.h" +#include "absl/types/span.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace debugging_internal { + +// Field numbers for perftools.profiles.Profile. +// https://github.com/google/pprof/blob/master/proto/profile.proto +struct ProfileProto { + static constexpr int kSampleType = 1; + static constexpr int kSample = 2; + static constexpr int kMapping = 3; + static constexpr int kLocation = 4; + static constexpr int kStringTable = 6; + static constexpr int kDropFrames = 7; + static constexpr int kComment = 13; + static constexpr int kDefaultSampleType = 14; +}; + +struct ValueTypeProto { + static constexpr int kType = 1; + static constexpr int kUnit = 2; +}; + +struct SampleProto { + static constexpr int kLocationId = 1; + static constexpr int kValue = 2; + static constexpr int kLabel = 3; +}; + +struct LabelProto { + static constexpr int kKey = 1; + static constexpr int kStr = 2; + static constexpr int kNum = 3; + static constexpr int kNumUnit = 4; +}; + +struct MappingProto { + static constexpr int kId = 1; + static constexpr int kMemoryStart = 2; + static constexpr int kMemoryLimit = 3; + static constexpr int kFileOffset = 4; + static constexpr int kFilename = 5; + static constexpr int kBuildId = 6; +}; + +struct LocationProto { + static constexpr int kId = 1; + static constexpr int kMappingId = 2; + static constexpr int kAddress = 3; +}; + +enum class StringId : size_t {}; +enum class LocationId : size_t {}; +enum class MappingId : size_t {}; + +// A helper class to build a profile protocol buffer. +class ProfileBuilder { + public: + struct Mapping { + uint64_t start; + uint64_t limit; + uint64_t offset; + std::string filename; + std::string build_id; + }; + + StringId InternString(absl::string_view str); + + LocationId InternLocation(const void* address); + + void AddSample(int64_t value, absl::Span stack, + absl::Span> labels); + + void AddSampleType(StringId type, StringId unit); + + // Adds the current process mappings to the profile. + void AddCurrentMappings(); + + // Adds a single mapping to the profile and to lookup cache and returns the + // resulting ID. + MappingId AddMapping(uintptr_t memory_start, uintptr_t memory_limit, + uintptr_t file_offset, absl::string_view filename, + absl::string_view build_id); + + std::string Emit() &&; + + void set_drop_frames_id(StringId drop_frames_id); + void set_comment_id(StringId comment_id); + void set_default_sample_type_id(StringId default_sample_type_id); + + private: + absl::flat_hash_map string_table_{{"", StringId(0)}}; + absl::flat_hash_map location_table_; + // mapping_table_ stores the start address of each mapping in mapping_ + // to its index. + absl::btree_map mapping_table_; + std::vector mappings_; + + std::vector sample_types_; + std::vector samples_; + + StringId drop_frames_id_{}; + StringId comment_id_{}; + StringId default_sample_type_id_{}; +}; + +} // namespace debugging_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_PROFILING_INTERNAL_PROFILE_BUILDER_H_ diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/profiling/internal/sample_recorder.h b/naiveproxy/src/third_party/abseil-cpp/absl/profiling/internal/sample_recorder.h index 371f6c473f..84843fdf98 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/profiling/internal/sample_recorder.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/profiling/internal/sample_recorder.h @@ -75,7 +75,7 @@ class SampleRecorder { // Iterates over all the registered `StackInfo`s. Returning the number of // samples that have been dropped. - int64_t Iterate(const std::function& f); + size_t Iterate(const std::function& f); size_t GetMaxSamples() const; void SetMaxSamples(size_t max); @@ -222,7 +222,7 @@ void SampleRecorder::Unregister(T* sample) { } template -int64_t SampleRecorder::Iterate( +size_t SampleRecorder::Iterate( const std::function& f) { T* s = all_.load(std::memory_order_acquire); while (s != nullptr) { diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/random/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/random/BUILD.bazel index 887ab0f220..8986211d2f 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/random/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/random/BUILD.bazel @@ -16,6 +16,9 @@ # ABSL random-number generation libraries. +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/random/internal/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/random/internal/BUILD.bazel index 994fb5c9f3..a9adea3c88 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/random/internal/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/random/internal/BUILD.bazel @@ -15,6 +15,9 @@ # load("@bazel_skylib//lib:selects.bzl", "selects") +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") # Internal-only implementation classes for Abseil Random load( diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/status/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/status/BUILD.bazel index b61abeb43c..7537797a4c 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/status/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/status/BUILD.bazel @@ -17,6 +17,9 @@ # It will expand later to have utilities around `Status` like `StatusOr`, # `StatusBuilder` and macros. +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", 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 e986611396..b6641041ea 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 @@ -46,6 +46,16 @@ template struct HasConversionOperatorToStatusOr(0))> : std::true_type {}; +// Detects whether `T` is equality-comparable. +template +struct IsEqualityComparable : std::false_type {}; + +template +struct IsEqualityComparable< + T, std::enable_if_t() == std::declval()), + bool>::value>> : std::true_type {}; + // Detects whether `T` is constructible or convertible from `StatusOr`. template using IsConstructibleOrConvertibleFromStatusOr = @@ -80,17 +90,34 @@ template struct IsDirectInitializationAmbiguous> : public IsConstructibleOrConvertibleFromStatusOr {}; +// Checks whether the conversion from U to T can be done without dangling +// temporaries. +// REQUIRES: T and U are references. +template +using IsReferenceConversionValid = absl::conjunction< // + std::is_reference, std::is_reference, + // The references are convertible. This checks for + // lvalue/rvalue compatibility. + std::is_convertible, + // The pointers are convertible. This checks we don't have + // a temporary. + std::is_convertible*, + std::remove_reference_t*>>; + // Checks against the constraints of the direction initialization, i.e. when // `StatusOr::StatusOr(U&&)` should participate in overload resolution. template using IsDirectInitializationValid = absl::disjunction< // Short circuits if T is basically U. - std::is_same>, - absl::negation, absl::remove_cvref_t>, - std::is_same>, - std::is_same>, - IsDirectInitializationAmbiguous>>>; + std::is_same>, // + std::conditional_t< + std::is_reference_v, // + IsReferenceConversionValid, + absl::negation, absl::remove_cvref_t>, + std::is_same>, + std::is_same>, + IsDirectInitializationAmbiguous>>>>; // This trait detects whether `StatusOr::operator=(U&&)` is ambiguous, which // is equivalent to whether all the following conditions are met: @@ -130,7 +157,9 @@ using Equality = std::conditional_t>; template using IsConstructionValid = absl::conjunction< Equality>, + absl::disjunction< + std::is_reference, + type_traits_internal::IsLifetimeBoundAssignment>>, IsDirectInitializationValid, std::is_constructible, Equality>, absl::disjunction< @@ -146,8 +175,13 @@ using IsConstructionValid = absl::conjunction< template using IsAssignmentValid = absl::conjunction< Equality>, - std::is_constructible, std::is_assignable, + absl::disjunction< + std::is_reference, + type_traits_internal::IsLifetimeBoundAssignment>>, + std::conditional_t, + IsReferenceConversionValid, + absl::conjunction, + std::is_assignable>>, absl::disjunction< std::is_same>, absl::conjunction< @@ -168,6 +202,9 @@ template using IsConstructionFromStatusOrValid = absl::conjunction< absl::negation>, + // If `T` is a reference, then U must be a compatible one. + absl::disjunction>, + IsReferenceConversionValid>, Equality>, std::is_constructible, @@ -183,6 +220,16 @@ using IsStatusOrAssignmentValid = absl::conjunction< absl::negation>>>; +template +using IsValueOrValid = absl::conjunction< + // If `T` is a reference, then U must be a compatible one. + absl::disjunction>, + IsReferenceConversionValid>, + Equality, + type_traits_internal::IsLifetimeBoundAssignment>>>; + class Helper { public: // Move type-agnostic error handling to the .cc. @@ -199,6 +246,26 @@ void PlacementNew(void* absl_nonnull p, Args&&... args) { new (p) T(std::forward(args)...); } +template +class Reference { + public: + constexpr explicit Reference(T ref ABSL_ATTRIBUTE_LIFETIME_BOUND) + : payload_(std::addressof(ref)) {} + + Reference(const Reference&) = default; + Reference& operator=(const Reference&) = default; + Reference& operator=(T value) { + payload_ = std::addressof(value); + return *this; + } + + operator T() const { return static_cast(*payload_); } // NOLINT + T get() const { return *this; } + + private: + std::remove_reference_t* absl_nonnull payload_; +}; + // Helper base class to hold the data and all operations. // We move all this to a base class to allow mixing with the appropriate // TraitsBase specialization. @@ -207,6 +274,14 @@ class StatusOrData { template friend class StatusOrData; + decltype(auto) MaybeMoveData() { + if constexpr (std::is_reference_v) { + return data_.get(); + } else { + return std::move(data_); + } + } + public: StatusOrData() = delete; @@ -221,7 +296,7 @@ class StatusOrData { StatusOrData(StatusOrData&& other) noexcept { if (other.ok()) { - MakeValue(std::move(other.data_)); + MakeValue(other.MaybeMoveData()); MakeStatus(); } else { MakeStatus(std::move(other.status_)); @@ -241,7 +316,7 @@ class StatusOrData { template explicit StatusOrData(StatusOrData&& other) { if (other.ok()) { - MakeValue(std::move(other.data_)); + MakeValue(other.MaybeMoveData()); MakeStatus(); } else { MakeStatus(std::move(other.status_)); @@ -254,13 +329,6 @@ class StatusOrData { MakeStatus(); } - explicit StatusOrData(const T& value) : data_(value) { - MakeStatus(); - } - explicit StatusOrData(T&& value) : data_(std::move(value)) { - MakeStatus(); - } - template ::value, int> = 0> @@ -280,7 +348,7 @@ class StatusOrData { StatusOrData& operator=(StatusOrData&& other) { if (this == &other) return *this; if (other.ok()) - Assign(std::move(other.data_)); + Assign(other.MaybeMoveData()); else AssignStatus(std::move(other.status_)); return *this; @@ -289,7 +357,9 @@ class StatusOrData { ~StatusOrData() { if (ok()) { status_.~Status(); - data_.~T(); + if constexpr (!std::is_trivially_destructible_v) { + data_.~T(); + } } else { status_.~Status(); } @@ -330,11 +400,13 @@ class StatusOrData { // When T is const, we need some non-const object we can cast to void* for // the placement new. dummy_ is that object. Dummy dummy_; - T data_; + std::conditional_t, Reference, T> data_; }; void Clear() { - if (ok()) data_.~T(); + if constexpr (!std::is_trivially_destructible_v) { + if (ok()) data_.~T(); + } } void EnsureOk() const { @@ -349,7 +421,8 @@ class StatusOrData { // argument. template void MakeValue(Arg&&... arg) { - internal_statusor::PlacementNew(&dummy_, std::forward(arg)...); + internal_statusor::PlacementNew(&dummy_, + std::forward(arg)...); } // Construct the status (ie. status_) through placement new with the passed @@ -359,6 +432,94 @@ class StatusOrData { internal_statusor::PlacementNew(&status_, std::forward(args)...); } + + template + T ValueOrImpl(U&& default_value) const& { + if (ok()) { + return data_; + } + return std::forward(default_value); + } + + template + T ValueOrImpl(U&& default_value) && { + if (ok()) { + return std::move(data_); + } + return std::forward(default_value); + } +}; + +[[noreturn]] void ThrowBadStatusOrAccess(absl::Status status); + +template +struct OperatorBase { + auto& self() const { return static_cast&>(*this); } + auto& self() { return static_cast&>(*this); } + + const T& operator*() const& ABSL_ATTRIBUTE_LIFETIME_BOUND { + self().EnsureOk(); + return self().data_; + } + T& operator*() & ABSL_ATTRIBUTE_LIFETIME_BOUND { + self().EnsureOk(); + return self().data_; + } + const T&& operator*() const&& ABSL_ATTRIBUTE_LIFETIME_BOUND { + self().EnsureOk(); + return std::move(self().data_); + } + T&& operator*() && ABSL_ATTRIBUTE_LIFETIME_BOUND { + self().EnsureOk(); + return std::move(self().data_); + } + + const T& value() const& ABSL_ATTRIBUTE_LIFETIME_BOUND { + if (!self().ok()) internal_statusor::ThrowBadStatusOrAccess(self().status_); + return self().data_; + } + T& value() & ABSL_ATTRIBUTE_LIFETIME_BOUND { + if (!self().ok()) internal_statusor::ThrowBadStatusOrAccess(self().status_); + return self().data_; + } + const T&& value() const&& ABSL_ATTRIBUTE_LIFETIME_BOUND { + if (!self().ok()) { + internal_statusor::ThrowBadStatusOrAccess(std::move(self().status_)); + } + return std::move(self().data_); + } + T&& value() && ABSL_ATTRIBUTE_LIFETIME_BOUND { + if (!self().ok()) { + internal_statusor::ThrowBadStatusOrAccess(std::move(self().status_)); + } + return std::move(self().data_); + } + + const T* absl_nonnull operator->() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + return std::addressof(**this); + } + T* absl_nonnull operator->() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return std::addressof(**this); + } +}; + +template +struct OperatorBase { + auto& self() const { return static_cast&>(*this); } + + T& operator*() const { + self().EnsureOk(); + return self().data_; + } + + T& value() const { + if (!self().ok()) internal_statusor::ThrowBadStatusOrAccess(self().status_); + return self().data_; + } + + T* absl_nonnull operator->() const { + return std::addressof(**this); + } }; // Helper base classes to allow implicitly deleted constructors and assignment @@ -401,8 +562,9 @@ struct MoveCtorBase { MoveCtorBase& operator=(MoveCtorBase&&) = default; }; -template ::value&& - std::is_copy_assignable::value> +template ::value && + std::is_copy_assignable::value) || + std::is_reference_v> struct CopyAssignBase { CopyAssignBase() = default; CopyAssignBase(const CopyAssignBase&) = default; @@ -420,8 +582,9 @@ struct CopyAssignBase { CopyAssignBase& operator=(CopyAssignBase&&) = default; }; -template ::value&& - std::is_move_assignable::value> +template ::value && + std::is_move_assignable::value) || + std::is_reference_v> struct MoveAssignBase { MoveAssignBase() = default; MoveAssignBase(const MoveAssignBase&) = default; @@ -439,8 +602,6 @@ struct MoveAssignBase { MoveAssignBase& operator=(MoveAssignBase&&) = delete; }; -[[noreturn]] void ThrowBadStatusOrAccess(absl::Status status); - // Used to introduce jitter into the output of printing functions for // `StatusOr` (i.e. `AbslStringify` and `operator<<`). class StringifyRandom { diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/status/statusor.h b/naiveproxy/src/third_party/abseil-cpp/absl/status/statusor.h index 6142a2f8dd..56309af32e 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/status/statusor.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/status/statusor.h @@ -189,14 +189,22 @@ class ABSL_MUST_USE_RESULT StatusOr; // return Foo(arg); // } template -class StatusOr : private internal_statusor::StatusOrData, +class StatusOr : private internal_statusor::OperatorBase, + private internal_statusor::StatusOrData, private internal_statusor::CopyCtorBase, private internal_statusor::MoveCtorBase, private internal_statusor::CopyAssignBase, private internal_statusor::MoveAssignBase { +#ifndef SWIG + static_assert(!std::is_rvalue_reference_v, + "rvalue references are not yet supported."); +#endif // SWIG + template friend class StatusOr; + friend internal_statusor::OperatorBase; + typedef internal_statusor::StatusOrData Base; public: @@ -397,7 +405,7 @@ class StatusOr : private internal_statusor::StatusOrData, typename std::enable_if< internal_statusor::IsAssignmentValid::value, int>::type = 0> - StatusOr& operator=(U&& v ABSL_ATTRIBUTE_LIFETIME_BOUND) { + StatusOr& operator=(U&& v ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this)) { this->Assign(std::forward(v)); return *this; } @@ -493,10 +501,7 @@ class StatusOr : private internal_statusor::StatusOrData, // // The `std::move` on statusor instead of on the whole expression enables // warnings about possible uses of the statusor object after the move. - const T& value() const& ABSL_ATTRIBUTE_LIFETIME_BOUND; - T& value() & ABSL_ATTRIBUTE_LIFETIME_BOUND; - const T&& value() const&& ABSL_ATTRIBUTE_LIFETIME_BOUND; - T&& value() && ABSL_ATTRIBUTE_LIFETIME_BOUND; + using StatusOr::OperatorBase::value; // StatusOr:: operator*() // @@ -508,10 +513,7 @@ class StatusOr : private internal_statusor::StatusOrData, // `absl::StatusOr`. Alternatively, see the `value()` member function for a // similar API that guarantees crashing or throwing an exception if there is // no current value. - const T& operator*() const& ABSL_ATTRIBUTE_LIFETIME_BOUND; - T& operator*() & ABSL_ATTRIBUTE_LIFETIME_BOUND; - const T&& operator*() const&& ABSL_ATTRIBUTE_LIFETIME_BOUND; - T&& operator*() && ABSL_ATTRIBUTE_LIFETIME_BOUND; + using StatusOr::OperatorBase::operator*; // StatusOr::operator->() // @@ -520,8 +522,7 @@ class StatusOr : private internal_statusor::StatusOrData, // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined. // // Use `this->ok()` to verify that there is a current value. - const T* absl_nonnull operator->() const ABSL_ATTRIBUTE_LIFETIME_BOUND; - T* absl_nonnull operator->() ABSL_ATTRIBUTE_LIFETIME_BOUND; + using StatusOr::OperatorBase::operator->; // StatusOr::value_or() // @@ -536,10 +537,34 @@ class StatusOr : private internal_statusor::StatusOrData, // // Unlike with `value`, calling `std::move()` on the result of `value_or` will // still trigger a copy. - template - T value_or(U&& default_value) const&; - template - T value_or(U&& default_value) &&; + template < + typename U, + std::enable_if_t::value, + int> = 0> + T value_or(U&& default_value) const& { + return this->ValueOrImpl(std::forward(default_value)); + } + template < + typename U, + std::enable_if_t::value, + int> = 0> + T value_or(U&& default_value) && { + return std::move(*this).ValueOrImpl(std::forward(default_value)); + } + template < + typename U, + std::enable_if_t::value, + int> = 0> + T value_or(U&& default_value ABSL_ATTRIBUTE_LIFETIME_BOUND) const& { + return this->ValueOrImpl(std::forward(default_value)); + } + template < + typename U, + std::enable_if_t::value, + int> = 0> + T value_or(U&& default_value ABSL_ATTRIBUTE_LIFETIME_BOUND) && { + return std::move(*this).ValueOrImpl(std::forward(default_value)); + } // StatusOr::IgnoreError() // @@ -607,7 +632,9 @@ class StatusOr : private internal_statusor::StatusOrData, // operator==() // // This operator checks the equality of two `absl::StatusOr` objects. -template +template ::value, + int> = 0> bool operator==(const StatusOr& lhs, const StatusOr& rhs) { if (lhs.ok() && rhs.ok()) return *lhs == *rhs; return lhs.status() == rhs.status(); @@ -616,7 +643,9 @@ bool operator==(const StatusOr& lhs, const StatusOr& rhs) { // operator!=() // // This operator checks the inequality of two `absl::StatusOr` objects. -template +template ::value, + int> = 0> bool operator!=(const StatusOr& lhs, const StatusOr& rhs) { return !(lhs == rhs); } @@ -703,88 +732,6 @@ Status StatusOr::status() && { return ok() ? OkStatus() : std::move(this->status_); } -template -const T& StatusOr::value() const& { - if (!this->ok()) internal_statusor::ThrowBadStatusOrAccess(this->status_); - return this->data_; -} - -template -T& StatusOr::value() & { - if (!this->ok()) internal_statusor::ThrowBadStatusOrAccess(this->status_); - return this->data_; -} - -template -const T&& StatusOr::value() const&& { - if (!this->ok()) { - internal_statusor::ThrowBadStatusOrAccess(std::move(this->status_)); - } - return std::move(this->data_); -} - -template -T&& StatusOr::value() && { - if (!this->ok()) { - internal_statusor::ThrowBadStatusOrAccess(std::move(this->status_)); - } - return std::move(this->data_); -} - -template -const T& StatusOr::operator*() const& { - this->EnsureOk(); - return this->data_; -} - -template -T& StatusOr::operator*() & { - this->EnsureOk(); - return this->data_; -} - -template -const T&& StatusOr::operator*() const&& { - this->EnsureOk(); - return std::move(this->data_); -} - -template -T&& StatusOr::operator*() && { - this->EnsureOk(); - return std::move(this->data_); -} - -template -const T* absl_nonnull StatusOr::operator->() const { - this->EnsureOk(); - return &this->data_; -} - -template -T* absl_nonnull StatusOr::operator->() { - this->EnsureOk(); - return &this->data_; -} - -template -template -T StatusOr::value_or(U&& default_value) const& { - if (ok()) { - return this->data_; - } - return std::forward(default_value); -} - -template -template -T StatusOr::value_or(U&& default_value) && { - if (ok()) { - return std::move(this->data_); - } - return std::forward(default_value); -} - template void StatusOr::IgnoreError() const { // no-op 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 0b9d37298f..2e73f80fec 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/strings/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/strings/BUILD.bazel @@ -13,6 +13,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/strings/internal/cordz_info.h b/naiveproxy/src/third_party/abseil-cpp/absl/strings/internal/cordz_info.h index 2dc9d16def..0091fa2ea2 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/strings/internal/cordz_info.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/strings/internal/cordz_info.h @@ -191,9 +191,7 @@ class ABSL_LOCKABLE CordzInfo : public CordzHandle { // Global cordz info list. CordzInfo stores a pointer to the global list // instance to harden against ODR violations. struct List { - constexpr explicit List(absl::ConstInitType) - : mutex(absl::kConstInit, - absl::base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL) {} + constexpr explicit List(absl::ConstInitType) {} SpinLock mutex; std::atomic head ABSL_GUARDED_BY(mutex){nullptr}; diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/strings/internal/str_split_internal.h b/naiveproxy/src/third_party/abseil-cpp/absl/strings/internal/str_split_internal.h index ed1f117cda..31f1d657d5 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/strings/internal/str_split_internal.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/strings/internal/str_split_internal.h @@ -30,6 +30,7 @@ #define ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_ #include +#include #include #include #include @@ -58,8 +59,12 @@ namespace strings_internal { class ConvertibleToStringView { public: ConvertibleToStringView(const char* s) // NOLINT(runtime/explicit) - : value_(s) {} - ConvertibleToStringView(char* s) : value_(s) {} // NOLINT(runtime/explicit) + : value_(s) { + assert(s != nullptr); + } + ConvertibleToStringView(char* s) : value_(s) { // NOLINT(runtime/explicit) + assert(s != nullptr); + } ConvertibleToStringView(absl::string_view s) // NOLINT(runtime/explicit) : value_(s) {} ConvertibleToStringView(const std::string& s) // NOLINT(runtime/explicit) diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/strings/str_split.h b/naiveproxy/src/third_party/abseil-cpp/absl/strings/str_split.h index 761568a31b..cf53ccf1f1 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/strings/str_split.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/strings/str_split.h @@ -127,7 +127,7 @@ class ByString { absl::string_view Find(absl::string_view text, size_t pos) const; private: - const std::string delimiter_; + std::string delimiter_; }; // ByAsciiWhitespace diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/BUILD.bazel index 5c490121f6..9a1aa83379 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/BUILD.bazel @@ -14,6 +14,9 @@ # limitations under the License. # +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc b/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc index 93cd376bde..2ec8075019 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc @@ -35,7 +35,7 @@ namespace synchronization_internal { // ThreadIdentity storage is persistent, we maintain a free-list of previously // released ThreadIdentity objects. ABSL_CONST_INIT static base_internal::SpinLock freelist_lock( - absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY); + base_internal::SCHEDULE_KERNEL_ONLY); ABSL_CONST_INIT static base_internal::ThreadIdentity* thread_identity_freelist; // A per-thread destructor for reclaiming associated ThreadIdentity objects. 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 129067c151..e332520dbe 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 @@ -33,15 +33,15 @@ #include "absl/base/internal/low_level_alloc.h" #ifndef ABSL_LOW_LEVEL_ALLOC_MISSING -#include "absl/synchronization/internal/graphcycles.h" - #include #include #include #include + #include "absl/base/internal/hide_ptr.h" #include "absl/base/internal/raw_logging.h" #include "absl/base/internal/spinlock.h" +#include "absl/synchronization/internal/graphcycles.h" // Do not use STL. This module does not use standard memory allocation. @@ -54,15 +54,14 @@ namespace { // Avoid LowLevelAlloc's default arena since it calls malloc hooks in // which people are doing things like acquiring Mutexes. ABSL_CONST_INIT static absl::base_internal::SpinLock arena_mu( - absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY); + base_internal::SCHEDULE_KERNEL_ONLY); ABSL_CONST_INIT static base_internal::LowLevelAlloc::Arena* arena; static void InitArenaIfNecessary() { - arena_mu.Lock(); + base_internal::SpinLockHolder l(&arena_mu); if (arena == nullptr) { arena = base_internal::LowLevelAlloc::NewArena(0); } - arena_mu.Unlock(); } // Number of inlined elements in Vec. Hash table implementation @@ -89,7 +88,7 @@ class Vec { T* end() { return ptr_ + size_; } const T& operator[](uint32_t i) const { return ptr_[i]; } T& operator[](uint32_t i) { return ptr_[i]; } - const T& back() const { return ptr_[size_-1]; } + const T& back() const { return ptr_[size_ - 1]; } void pop_back() { size_--; } void push_back(const T& v) { @@ -178,7 +177,7 @@ class NodeSet { } table_[i] = v; // Double when 75% full. - if (occupied_ >= table_.size() - table_.size()/4) Grow(); + if (occupied_ >= table_.size() - table_.size() / 4) Grow(); return true; } @@ -193,7 +192,7 @@ class NodeSet { // Example: // HASH_FOR_EACH(elem, node->out) { ... } #define HASH_FOR_EACH(elem, eset) \ - for (int32_t elem, _cursor = 0; (eset).Next(&_cursor, &elem); ) + for (int32_t elem, _cursor = 0; (eset).Next(&_cursor, &elem);) bool Next(int32_t* cursor, int32_t* elem) { while (static_cast(*cursor) < table_.size()) { int32_t v = table_[static_cast(*cursor)]; @@ -209,7 +208,7 @@ class NodeSet { private: enum : int32_t { kEmpty = -1, kDel = -2 }; Vec table_; - uint32_t occupied_; // Count of non-empty slots (includes deleted slots) + uint32_t occupied_; // Count of non-empty slots (includes deleted slots) static uint32_t Hash(int32_t a) { return static_cast(a) * 41; } @@ -270,25 +269,23 @@ inline GraphId MakeId(int32_t index, uint32_t version) { return g; } -inline int32_t NodeIndex(GraphId id) { - return static_cast(id.handle); -} +inline int32_t NodeIndex(GraphId id) { return static_cast(id.handle); } inline uint32_t NodeVersion(GraphId id) { return static_cast(id.handle >> 32); } struct Node { - int32_t rank; // rank number assigned by Pearce-Kelly algorithm - uint32_t version; // Current version number - int32_t next_hash; // Next entry in hash table - bool visited; // Temporary marker used by depth-first-search - uintptr_t masked_ptr; // User-supplied pointer - NodeSet in; // List of immediate predecessor nodes in graph - NodeSet out; // List of immediate successor nodes in graph - int priority; // Priority of recorded stack trace. - int nstack; // Depth of recorded stack trace. - void* stack[40]; // stack[0,nstack-1] holds stack trace for node. + int32_t rank; // rank number assigned by Pearce-Kelly algorithm + uint32_t version; // Current version number + int32_t next_hash; // Next entry in hash table + bool visited; // Temporary marker used by depth-first-search + uintptr_t masked_ptr; // User-supplied pointer + NodeSet in; // List of immediate predecessor nodes in graph + NodeSet out; // List of immediate successor nodes in graph + int priority; // Priority of recorded stack trace. + int nstack; // Depth of recorded stack trace. + void* stack[40]; // stack[0,nstack-1] holds stack trace for node. }; // Hash table for pointer to node index lookups. @@ -318,7 +315,7 @@ class PointerMap { // Advance through linked list while keeping track of the // predecessor slot that points to the current entry. auto masked = base_internal::HidePtr(ptr); - for (int32_t* slot = &table_[Hash(ptr)]; *slot != -1; ) { + for (int32_t* slot = &table_[Hash(ptr)]; *slot != -1;) { int32_t index = *slot; Node* n = (*nodes_)[static_cast(index)]; if (n->masked_ptr == masked) { @@ -381,7 +378,9 @@ GraphCycles::GraphCycles() { GraphCycles::~GraphCycles() { for (auto* node : rep_->nodes_) { - if (node == nullptr) { continue; } + if (node == nullptr) { + continue; + } node->Node::~Node(); base_internal::LowLevelAlloc::Free(node); } @@ -474,8 +473,7 @@ void GraphCycles::RemoveNode(void* ptr) { void* GraphCycles::Ptr(GraphId id) { Node* n = FindNode(rep_, id); - return n == nullptr ? nullptr - : base_internal::UnhidePtr(n->masked_ptr); + return n == nullptr ? nullptr : base_internal::UnhidePtr(n->masked_ptr); } bool GraphCycles::HasNode(GraphId node) { @@ -502,8 +500,8 @@ static bool ForwardDFS(GraphCycles::Rep* r, int32_t n, int32_t upper_bound); static void BackwardDFS(GraphCycles::Rep* r, int32_t n, int32_t lower_bound); static void Reorder(GraphCycles::Rep* r); static void Sort(const Vec&, Vec* delta); -static void MoveToList( - GraphCycles::Rep* r, Vec* src, Vec* dst); +static void MoveToList(GraphCycles::Rep* r, Vec* src, + Vec* dst); bool GraphCycles::InsertEdge(GraphId idx, GraphId idy) { Rep* r = rep_; @@ -605,9 +603,8 @@ static void Reorder(GraphCycles::Rep* r) { // Produce sorted list of all ranks that will be reassigned. r->merged_.resize(r->deltab_.size() + r->deltaf_.size()); - std::merge(r->deltab_.begin(), r->deltab_.end(), - r->deltaf_.begin(), r->deltaf_.end(), - r->merged_.begin()); + std::merge(r->deltab_.begin(), r->deltab_.end(), r->deltaf_.begin(), + r->deltaf_.end(), r->merged_.begin()); // Assign the ranks in order to the collected list. for (uint32_t i = 0; i < r->list_.size(); i++) { @@ -628,8 +625,8 @@ static void Sort(const Vec& nodes, Vec* delta) { std::sort(delta->begin(), delta->end(), cmp); } -static void MoveToList( - GraphCycles::Rep* r, Vec* src, Vec* dst) { +static void MoveToList(GraphCycles::Rep* r, Vec* src, + Vec* dst) { for (auto& v : *src) { int32_t w = v; // Replace v entry with its rank diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/mutex.cc b/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/mutex.cc index 5091b8fd34..4c862fc6ec 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/mutex.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/mutex.cc @@ -226,7 +226,7 @@ static bool AtomicSetBits(std::atomic* pv, intptr_t bits, // Data for doing deadlock detection. ABSL_CONST_INIT static absl::base_internal::SpinLock deadlock_graph_mu( - absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY); + base_internal::SCHEDULE_KERNEL_ONLY); // Graph used to detect deadlocks. ABSL_CONST_INIT static GraphCycles* deadlock_graph @@ -292,7 +292,7 @@ static const struct { }; ABSL_CONST_INIT static absl::base_internal::SpinLock synch_event_mu( - absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY); + base_internal::SCHEDULE_KERNEL_ONLY); // Hash table size; should be prime > 2. // Can't be too small, as it's used for deadlock detection information. @@ -330,7 +330,7 @@ static SynchEvent* EnsureSynchEvent(std::atomic* addr, const char* name, intptr_t bits, intptr_t lockbit) { uint32_t h = reinterpret_cast(addr) % kNSynchEvent; - synch_event_mu.Lock(); + synch_event_mu.lock(); // When a Mutex/CondVar is destroyed, we don't remove the associated // SynchEvent to keep destructors empty in release builds for performance // reasons. If the current call is the first to set bits (kMuEvent/kCVEvent), @@ -392,16 +392,16 @@ static SynchEvent* EnsureSynchEvent(std::atomic* addr, } else { e->refcount++; // for return value } - synch_event_mu.Unlock(); + synch_event_mu.unlock(); return e; } // Decrement the reference count of *e, or do nothing if e==null. static void UnrefSynchEvent(SynchEvent* e) { if (e != nullptr) { - synch_event_mu.Lock(); + synch_event_mu.lock(); bool del = (--(e->refcount) == 0); - synch_event_mu.Unlock(); + synch_event_mu.unlock(); if (del) { base_internal::LowLevelAlloc::Free(e); } @@ -414,7 +414,7 @@ static void UnrefSynchEvent(SynchEvent* e) { static SynchEvent* GetSynchEvent(const void* addr) { uint32_t h = reinterpret_cast(addr) % kNSynchEvent; SynchEvent* e; - synch_event_mu.Lock(); + synch_event_mu.lock(); for (e = synch_event[h]; e != nullptr && e->masked_addr != base_internal::HidePtr(addr); e = e->next) { @@ -422,7 +422,7 @@ static SynchEvent* GetSynchEvent(const void* addr) { if (e != nullptr) { e->refcount++; } - synch_event_mu.Unlock(); + synch_event_mu.unlock(); return e; } @@ -509,10 +509,10 @@ struct SynchWaitParams { const Condition* cond; // The condition that this thread is waiting for. // In Mutex, this field is set to zero if a timeout // expires. - KernelTimeout timeout; // timeout expiry---absolute time - // In Mutex, this field is set to zero if a timeout - // expires. - Mutex* const cvmu; // used for transfer from cond var to mutex + KernelTimeout timeout; // timeout expiry---absolute time + // In Mutex, this field is set to zero if a timeout + // expires. + Mutex* const cvmu; // used for transfer from cond var to mutex PerThreadSynch* const thread; // thread that is waiting // If not null, thread should be enqueued on the CondVar whose state @@ -1223,9 +1223,9 @@ static GraphId GetGraphIdLocked(Mutex* mu) } static GraphId GetGraphId(Mutex* mu) ABSL_LOCKS_EXCLUDED(deadlock_graph_mu) { - deadlock_graph_mu.Lock(); + deadlock_graph_mu.lock(); GraphId id = GetGraphIdLocked(mu); - deadlock_graph_mu.Unlock(); + deadlock_graph_mu.unlock(); return id; } @@ -1327,8 +1327,7 @@ static char* StackString(void** pcs, int n, char* buf, int maxlen, char sym[kSymLen]; int len = 0; for (int i = 0; i != n; i++) { - if (len >= maxlen) - return buf; + if (len >= maxlen) return buf; size_t count = static_cast(maxlen - len); if (symbolize) { if (!absl::Symbolize(pcs[i], sym, kSymLen)) { @@ -1457,7 +1456,7 @@ static GraphId DeadlockCheck(Mutex* mu) { } if (synch_deadlock_detection.load(std::memory_order_acquire) == OnDeadlockCycle::kAbort) { - deadlock_graph_mu.Unlock(); // avoid deadlock in fatal sighandler + deadlock_graph_mu.unlock(); // avoid deadlock in fatal sighandler ABSL_RAW_LOG(FATAL, "dying due to potential deadlock"); return mu_id; } @@ -1482,11 +1481,11 @@ static inline GraphId DebugOnlyDeadlockCheck(Mutex* mu) { void Mutex::ForgetDeadlockInfo() { if (kDebugMode && synch_deadlock_detection.load(std::memory_order_acquire) != OnDeadlockCycle::kIgnore) { - deadlock_graph_mu.Lock(); + deadlock_graph_mu.lock(); if (deadlock_graph != nullptr) { deadlock_graph->RemoveNode(this); } - deadlock_graph_mu.Unlock(); + deadlock_graph_mu.unlock(); } } @@ -1528,7 +1527,7 @@ static bool TryAcquireWithSpinning(std::atomic* mu) { return false; } -void Mutex::Lock() { +void Mutex::lock() { ABSL_TSAN_MUTEX_PRE_LOCK(this, 0); GraphId id = DebugOnlyDeadlockCheck(this); intptr_t v = mu_.load(std::memory_order_relaxed); @@ -1546,7 +1545,7 @@ void Mutex::Lock() { ABSL_TSAN_MUTEX_POST_LOCK(this, 0, 0); } -void Mutex::ReaderLock() { +void Mutex::lock_shared() { ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_read_lock); GraphId id = DebugOnlyDeadlockCheck(this); intptr_t v = mu_.load(std::memory_order_relaxed); @@ -1606,7 +1605,7 @@ bool Mutex::AwaitCommon(const Condition& cond, KernelTimeout t) { return res; } -bool Mutex::TryLock() { +bool Mutex::try_lock() { ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_try_lock); intptr_t v = mu_.load(std::memory_order_relaxed); // Try fast acquire. @@ -1644,7 +1643,7 @@ ABSL_ATTRIBUTE_NOINLINE bool Mutex::TryLockSlow() { return false; } -bool Mutex::ReaderTryLock() { +bool Mutex::try_lock_shared() { ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_read_lock | __tsan_mutex_try_lock); intptr_t v = mu_.load(std::memory_order_relaxed); @@ -1706,7 +1705,7 @@ ABSL_ATTRIBUTE_NOINLINE bool Mutex::ReaderTryLockSlow() { return false; } -void Mutex::Unlock() { +void Mutex::unlock() { ABSL_TSAN_MUTEX_PRE_UNLOCK(this, 0); DebugOnlyLockLeave(this); intptr_t v = mu_.load(std::memory_order_relaxed); @@ -1776,7 +1775,7 @@ static bool ExactlyOneReader(intptr_t v) { return (v & kMuMultipleWaitersMask) == 0; } -void Mutex::ReaderUnlock() { +void Mutex::unlock_shared() { ABSL_TSAN_MUTEX_PRE_UNLOCK(this, __tsan_mutex_read_lock); DebugOnlyLockLeave(this); intptr_t v = mu_.load(std::memory_order_relaxed); @@ -2286,7 +2285,7 @@ ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams* waitp) { // set up to walk the list PerThreadSynch* w_walk; // current waiter during list walk PerThreadSynch* pw_walk; // previous waiter during list walk - if (old_h != nullptr) { // we've searched up to old_h before + if (old_h != nullptr) { // we've searched up to old_h before pw_walk = old_h; w_walk = old_h->next; } else { // no prior search, start at beginning diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/mutex.h b/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/mutex.h index 78b1c7a048..110c2209d3 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/mutex.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/mutex.h @@ -92,10 +92,10 @@ struct SynchWaitParams; // invariants. Proper usage of mutexes prevents concurrent access by different // threads to the same resource. // -// A `Mutex` has two basic operations: `Mutex::Lock()` and `Mutex::Unlock()`. -// The `Lock()` operation *acquires* a `Mutex` (in a state known as an -// *exclusive* -- or *write* -- lock), and the `Unlock()` operation *releases* a -// Mutex. During the span of time between the Lock() and Unlock() operations, +// A `Mutex` has two basic operations: `Mutex::lock()` and `Mutex::unlock()`. +// The `lock()` operation *acquires* a `Mutex` (in a state known as an +// *exclusive* -- or *write* -- lock), and the `unlock()` operation *releases* a +// Mutex. During the span of time between the lock() and unlock() operations, // a mutex is said to be *held*. By design, all mutexes support exclusive/write // locks, as this is the most common way to use a mutex. // @@ -106,23 +106,23 @@ struct SynchWaitParams; // // The `Mutex` state machine for basic lock/unlock operations is quite simple: // -// | | Lock() | Unlock() | +// | | lock() | unlock() | // |----------------+------------------------+----------| // | Free | Exclusive | invalid | // | Exclusive | blocks, then exclusive | Free | // // The full conditions are as follows. // -// * Calls to `Unlock()` require that the mutex be held, and must be made in the -// same thread that performed the corresponding `Lock()` operation which +// * Calls to `unlock()` require that the mutex be held, and must be made in the +// same thread that performed the corresponding `lock()` operation which // acquired the mutex; otherwise the call is invalid. // // * The mutex being non-reentrant (or non-recursive) means that a call to -// `Lock()` or `TryLock()` must not be made in a thread that already holds the -// mutex; such a call is invalid. +// `lock()` or `try_lock()` must not be made in a thread that already holds +// the mutex; such a call is invalid. // // * In other words, the state of being "held" has both a temporal component -// (from `Lock()` until `Unlock()`) as well as a thread identity component: +// (from `lock()` until `unlock()`) as well as a thread identity component: // the mutex is held *by a particular thread*. // // An "invalid" operation has undefined behavior. The `Mutex` implementation @@ -174,24 +174,32 @@ class ABSL_LOCKABLE ABSL_ATTRIBUTE_WARN_UNUSED Mutex { ~Mutex(); - // Mutex::Lock() + // Mutex::lock() // // Blocks the calling thread, if necessary, until this `Mutex` is free, and // then acquires it exclusively. (This lock is also known as a "write lock.") - void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION(); + void lock() ABSL_EXCLUSIVE_LOCK_FUNCTION(); - // Mutex::Unlock() + inline void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() { lock(); } + + // Mutex::unlock() // // Releases this `Mutex` and returns it from the exclusive/write state to the // free state. Calling thread must hold the `Mutex` exclusively. - void Unlock() ABSL_UNLOCK_FUNCTION(); + void unlock() ABSL_UNLOCK_FUNCTION(); - // Mutex::TryLock() + inline void Unlock() ABSL_UNLOCK_FUNCTION() { unlock(); } + + // Mutex::try_lock() // // If the mutex can be acquired without blocking, does so exclusively and // returns `true`. Otherwise, returns `false`. Returns `true` with high // probability if the `Mutex` was free. - [[nodiscard]] bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true); + [[nodiscard]] bool try_lock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true); + + [[nodiscard]] bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) { + return try_lock(); + } // Mutex::AssertHeld() // @@ -211,19 +219,19 @@ class ABSL_LOCKABLE ABSL_ATTRIBUTE_WARN_UNUSED Mutex { // Neither read-locks nor write-locks are reentrant/recursive to avoid // potential client programming errors. // - // The Mutex API provides `Writer*()` aliases for the existing `Lock()`, - // `Unlock()` and `TryLock()` methods for use within applications mixing - // reader/writer locks. Using `Reader*()` and `Writer*()` operations in this + // The Mutex API provides `Writer*()` aliases for the existing `lock()`, + // `unlock()` and `try_lock()` methods for use within applications mixing + // reader/writer locks. Using `*_shared()` and `Writer*()` operations in this // manner can make locking behavior clearer when mixing read and write modes. // // Introducing reader locks necessarily complicates the `Mutex` state // machine somewhat. The table below illustrates the allowed state transitions - // of a mutex in such cases. Note that ReaderLock() may block even if the lock - // is held in shared mode; this occurs when another thread is blocked on a - // call to WriterLock(). + // of a mutex in such cases. Note that lock_shared() may block even if the + // lock is held in shared mode; this occurs when another thread is blocked on + // a call to lock(). // // --------------------------------------------------------------------------- - // Operation: WriterLock() Unlock() ReaderLock() ReaderUnlock() + // Operation: lock() unlock() lock_shared() unlock_shared() // --------------------------------------------------------------------------- // State // --------------------------------------------------------------------------- @@ -235,28 +243,35 @@ class ABSL_LOCKABLE ABSL_ATTRIBUTE_WARN_UNUSED Mutex { // // In comments below, "shared" refers to a state of Shared(n) for any n > 0. - // Mutex::ReaderLock() + // Mutex::lock_shared() // // Blocks the calling thread, if necessary, until this `Mutex` is either free, // or in shared mode, and then acquires a share of it. Note that - // `ReaderLock()` will block if some other thread has an exclusive/writer lock - // on the mutex. + // `lock_shared()` will block if some other thread has an exclusive/writer + // lock on the mutex. + void lock_shared() ABSL_SHARED_LOCK_FUNCTION(); - void ReaderLock() ABSL_SHARED_LOCK_FUNCTION(); + void ReaderLock() ABSL_SHARED_LOCK_FUNCTION() { lock_shared(); } - // Mutex::ReaderUnlock() + // Mutex::unlock_shared() // - // Releases a read share of this `Mutex`. `ReaderUnlock` may return a mutex to - // the free state if this thread holds the last reader lock on the mutex. Note - // that you cannot call `ReaderUnlock()` on a mutex held in write mode. - void ReaderUnlock() ABSL_UNLOCK_FUNCTION(); + // Releases a read share of this `Mutex`. `unlock_shared` may return a mutex + // to the free state if this thread holds the last reader lock on the mutex. + // Note that you cannot call `unlock_shared()` on a mutex held in write mode. + void unlock_shared() ABSL_UNLOCK_FUNCTION(); - // Mutex::ReaderTryLock() + void ReaderUnlock() ABSL_UNLOCK_FUNCTION() { unlock_shared(); } + + // Mutex::try_lock_shared() // // If the mutex can be acquired without blocking, acquires this mutex for // shared access and returns `true`. Otherwise, returns `false`. Returns // `true` with high probability if the `Mutex` was free or shared. - [[nodiscard]] bool ReaderTryLock() ABSL_SHARED_TRYLOCK_FUNCTION(true); + [[nodiscard]] bool try_lock_shared() ABSL_SHARED_TRYLOCK_FUNCTION(true); + + [[nodiscard]] bool ReaderTryLock() ABSL_SHARED_TRYLOCK_FUNCTION(true) { + return try_lock_shared(); + } // Mutex::AssertReaderHeld() // @@ -278,12 +293,12 @@ class ABSL_LOCKABLE ABSL_ATTRIBUTE_WARN_UNUSED Mutex { // These methods may be used (along with the complementary `Reader*()` // methods) to distinguish simple exclusive `Mutex` usage (`Lock()`, // etc.) from reader/writer lock usage. - void WriterLock() ABSL_EXCLUSIVE_LOCK_FUNCTION() { this->Lock(); } + void WriterLock() ABSL_EXCLUSIVE_LOCK_FUNCTION() { this->lock(); } - void WriterUnlock() ABSL_UNLOCK_FUNCTION() { this->Unlock(); } + void WriterUnlock() ABSL_UNLOCK_FUNCTION() { this->unlock(); } [[nodiscard]] bool WriterTryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) { - return this->TryLock(); + return this->try_lock(); } // --------------------------------------------------------------------------- diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/mutex_benchmark.cc b/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/mutex_benchmark.cc index 06888dfea2..1f33c0d7cb 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/mutex_benchmark.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/mutex_benchmark.cc @@ -72,24 +72,6 @@ static void DelayNs(int64_t ns, int* data) { } } -template -class RaiiLocker { - public: - explicit RaiiLocker(MutexType* mu) : mu_(mu) { mu_->Lock(); } - ~RaiiLocker() { mu_->Unlock(); } - private: - MutexType* mu_; -}; - -template <> -class RaiiLocker { - public: - explicit RaiiLocker(std::mutex* mu) : mu_(mu) { mu_->lock(); } - ~RaiiLocker() { mu_->unlock(); } - private: - std::mutex* mu_; -}; - // RAII object to change the Mutex priority of the running thread. class ScopedThreadMutexPriority { public: @@ -226,7 +208,7 @@ void BM_Contended(benchmark::State& state) { // to keep ratio between local work and critical section approximately // equal regardless of number of threads. DelayNs(100 * state.threads(), &local); - RaiiLocker locker(&shared->mu); + std::scoped_lock locker(shared->mu); DelayNs(state.range(0), &shared->data); } } diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/time/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/time/BUILD.bazel index ad0313c5cf..b61999b338 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/time/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/time/BUILD.bazel @@ -14,6 +14,9 @@ # limitations under the License. # +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/time/clock.cc b/naiveproxy/src/third_party/abseil-cpp/absl/time/clock.cc index ecd539e5ca..f920ada4eb 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/time/clock.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/time/clock.cc @@ -135,7 +135,7 @@ static inline uint64_t SeqAcquire(std::atomic *seq) { // fetch_add would be before it, not after. std::atomic_thread_fence(std::memory_order_release); - return x + 2; // original word plus 2 + return x + 2; // original word plus 2 } // Release seqlock (*seq) by writing x to it---a value previously returned by @@ -160,8 +160,8 @@ static const uint64_t kMinNSBetweenSamples = 2000 << 20; // We require that kMinNSBetweenSamples shifted by kScale // have at least a bit left over for 64-bit calculations. static_assert(((kMinNSBetweenSamples << (kScale + 1)) >> (kScale + 1)) == - kMinNSBetweenSamples, - "cannot represent kMaxBetweenSamplesNSScaled"); + kMinNSBetweenSamples, + "cannot represent kMaxBetweenSamplesNSScaled"); // data from a sample of the kernel's time value struct TimeSampleAtomic { @@ -206,8 +206,7 @@ struct ABSL_CACHELINE_ALIGNED TimeState { // A reader-writer lock protecting the static locations below. // See SeqAcquire() and SeqRelease() above. - absl::base_internal::SpinLock lock{absl::kConstInit, - base_internal::SCHEDULE_KERNEL_ONLY}; + absl::base_internal::SpinLock lock{base_internal::SCHEDULE_KERNEL_ONLY}; }; ABSL_CONST_INIT static TimeState time_state; @@ -416,7 +415,7 @@ static int64_t GetCurrentTimeNanosSlowPath() ABSL_LOCKS_EXCLUDED(time_state.lock) { // Serialize access to slow-path. Fast-path readers are not blocked yet, and // code below must not modify last_sample until the seqlock is acquired. - time_state.lock.Lock(); + base_internal::SpinLockHolder l(&time_state.lock); // Sample the kernel time base. This is the definition of // "now" if we take the slow path. @@ -439,16 +438,14 @@ static int64_t GetCurrentTimeNanosSlowPath() if (delta_cycles < sample.min_cycles_per_sample) { // Another thread updated the sample. This path does not take the seqlock // so that blocked readers can make progress without blocking new readers. - estimated_base_ns = sample.base_ns + - ((delta_cycles * sample.nsscaled_per_cycle) >> kScale); + estimated_base_ns = + sample.base_ns + ((delta_cycles * sample.nsscaled_per_cycle) >> kScale); time_state.stats_fast_slow_paths++; } else { estimated_base_ns = UpdateLastSample(now_cycles, now_ns, delta_cycles, &sample); } - time_state.lock.Unlock(); - return static_cast(estimated_base_ns); } @@ -494,8 +491,8 @@ static uint64_t UpdateLastSample(uint64_t now_cycles, uint64_t now_ns, estimated_scaled_ns = (delta_cycles >> s) * sample->nsscaled_per_cycle; } while (estimated_scaled_ns / sample->nsscaled_per_cycle != (delta_cycles >> s)); - estimated_base_ns = sample->base_ns + - (estimated_scaled_ns >> (kScale - s)); + estimated_base_ns = + sample->base_ns + (estimated_scaled_ns >> (kScale - s)); } // Compute the assumed cycle time kMinNSBetweenSamples ns into the future @@ -522,8 +519,8 @@ static uint64_t UpdateLastSample(uint64_t now_cycles, uint64_t now_ns, diff_ns - (diff_ns / 16)); uint64_t new_nsscaled_per_cycle = SafeDivideAndScale(ns, assumed_next_sample_delta_cycles); - if (new_nsscaled_per_cycle != 0 && - diff_ns < 100 * 1000 * 1000 && -diff_ns < 100 * 1000 * 1000) { + if (new_nsscaled_per_cycle != 0 && diff_ns < 100 * 1000 * 1000 && + -diff_ns < 100 * 1000 * 1000) { // record the cycle time measurement time_state.last_sample.nsscaled_per_cycle.store( new_nsscaled_per_cycle, std::memory_order_relaxed); diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/time/duration.cc b/naiveproxy/src/third_party/abseil-cpp/absl/time/duration.cc index 38c4b63990..fb7c90a2d7 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/time/duration.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/time/duration.cc @@ -469,7 +469,7 @@ Duration& Duration::operator*=(int64_t r) { Duration& Duration::operator*=(double r) { if (time_internal::IsInfiniteDuration(*this) || !IsFinite(r)) { - const bool is_neg = std::signbit(r) != (rep_hi_.Get() < 0); + const bool is_neg = std::isnan(r) || std::signbit(r) != (rep_hi_.Get() < 0); return *this = is_neg ? -InfiniteDuration() : InfiniteDuration(); } return *this = ScaleDouble(*this, r); @@ -485,7 +485,7 @@ Duration& Duration::operator/=(int64_t r) { Duration& Duration::operator/=(double r) { if (time_internal::IsInfiniteDuration(*this) || !IsValidDivisor(r)) { - const bool is_neg = std::signbit(r) != (rep_hi_.Get() < 0); + const bool is_neg = std::isnan(r) || std::signbit(r) != (rep_hi_.Get() < 0); return *this = is_neg ? -InfiniteDuration() : InfiniteDuration(); } return *this = ScaleDouble(*this, r); diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/time/internal/cctz/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/time/internal/cctz/BUILD.bazel index da30a0f11b..8abc804ce3 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/time/internal/cctz/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/time/internal/cctz/BUILD.bazel @@ -12,6 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") load("//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", "ABSL_DEFAULT_LINKOPTS", "ABSL_TEST_COPTS") package(features = [ 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 53bca90d15..29beaac19a 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/time/time.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/time/time.h @@ -589,9 +589,10 @@ ABSL_ATTRIBUTE_CONST_FUNCTION Duration Seconds(T n) { } return time_internal::MakePosDoubleDuration(n); } else { - if (std::isnan(n)) - return std::signbit(n) ? -InfiniteDuration() : InfiniteDuration(); - if (n <= (std::numeric_limits::min)()) return -InfiniteDuration(); + if (std::isnan(n)) return -InfiniteDuration(); + if (n <= static_cast((std::numeric_limits::min)())) { + return -InfiniteDuration(); + } return -time_internal::MakePosDoubleDuration(-n); } } diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/types/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/types/BUILD.bazel index 0668a2e776..cac5e4b1c8 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/types/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/types/BUILD.bazel @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", 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 772681c849..3338e878e8 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/types/span.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/types/span.h @@ -186,8 +186,9 @@ class ABSL_ATTRIBUTE_VIEW Span { // type C. template using EnableIfConvertibleFrom = - typename std::enable_if::value && - span_internal::HasSize::value>::type; + std::enable_if_t> && + span_internal::HasData::value && + span_internal::HasSize::value>; // Used to SFINAE-enable a function when the slice elements are const. template diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/utility/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/utility/BUILD.bazel index 773f949688..a714b020a2 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/utility/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/utility/BUILD.bazel @@ -14,6 +14,7 @@ # limitations under the License. # +load("@rules_cc//cc:cc_library.bzl", "cc_library") load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", diff --git a/naiveproxy/src/third_party/abseil-cpp/ci/absl_alternate_options.h b/naiveproxy/src/third_party/abseil-cpp/ci/absl_alternate_options.h index a563859157..20bf0105f4 100644 --- a/naiveproxy/src/third_party/abseil-cpp/ci/absl_alternate_options.h +++ b/naiveproxy/src/third_party/abseil-cpp/ci/absl_alternate_options.h @@ -15,13 +15,12 @@ // Alternate options.h file, used in continuous integration testing to exercise // option settings not used by default. +// SKIP_ABSL_INLINE_NAMESPACE_CHECK + #ifndef ABSL_CI_ABSL_ALTERNATE_OPTIONS_H_ #define ABSL_CI_ABSL_ALTERNATE_OPTIONS_H_ -#define ABSL_OPTION_USE_STD_ANY 0 -#define ABSL_OPTION_USE_STD_OPTIONAL 0 #define ABSL_OPTION_USE_STD_STRING_VIEW 0 -#define ABSL_OPTION_USE_STD_VARIANT 0 #define ABSL_OPTION_USE_STD_ORDERING 0 #define ABSL_OPTION_USE_INLINE_NAMESPACE 1 #define ABSL_OPTION_INLINE_NAMESPACE_NAME ns 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 ff05add3a7..e05d057398 100644 --- a/naiveproxy/src/third_party/abseil-cpp/symbols_arm64_dbg.def +++ b/naiveproxy/src/third_party/abseil-cpp/symbols_arm64_dbg.def @@ -5,14 +5,14 @@ EXPORTS ??$?0$$CBUCordRep@cord_internal@absl@@@Hex@absl@@QEAA@PEBUCordRep@cord_internal@1@W4PadSpec@1@@Z ??$?0$$CBVFormatArgImpl@str_format_internal@absl@@$$CBV012@@?$Span@$$CBVFormatArgImpl@str_format_internal@absl@@@absl@@QEAA@V?$initializer_list@VFormatArgImpl@str_format_internal@absl@@@std@@@Z ??$?0$$CB_W$0A@@VoidPtr@str_format_internal@absl@@QEAA@PEB_W@Z - ??$?0$$QEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V$$Z$0A@$$Z$S@?$pair@$$CBV?$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@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@$$QEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@AEAV?$tuple@$$V@12@U?$__tuple_indices@$0A@@12@U?$__tuple_indices@$S@12@@Z + ??$?0$$QEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V$$Z$0A@$$Z$S@?$pair@$$CBV?$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@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@$$QEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@AEAV?$tuple@$$V@12@U?$__integer_sequence@_K$0A@@12@U?$__integer_sequence@_K$S@12@@Z ??$?0$$QEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V@?$pair@$$CBV?$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@@QEAA@Upiecewise_construct_t@12@V?$tuple@$$QEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@V?$tuple@$$V@12@@Z - ??$?0$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAV?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@U?$__tuple_indices@$0A@@12@3@Z - ??$?0$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$tuple@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@23@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAV?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@U?$__tuple_indices@$0A@@12@3@Z + ??$?0$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAV?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@U?$__integer_sequence@_K$0A@@12@3@Z + ??$?0$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$tuple@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@23@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAV?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@U?$__integer_sequence@_K$0A@@12@3@Z ??$?0$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@@?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@QEAA@Upiecewise_construct_t@12@V?$tuple@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@@Z ??$?0$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@@?$pair@V?$tuple@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@23@@__Cr@std@@QEAA@Upiecewise_construct_t@12@V?$tuple@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@@Z - ??$?0$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAV?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@U?$__tuple_indices@$0A@@12@3@Z - ??$?0$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@23@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAV?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@U?$__tuple_indices@$0A@@12@3@Z + ??$?0$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAV?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@U?$__integer_sequence@_K$0A@@12@3@Z + ??$?0$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@23@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAV?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@U?$__integer_sequence@_K$0A@@12@3@Z ??$?0$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@@?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@QEAA@Upiecewise_construct_t@12@V?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@@Z ??$?0$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@@?$pair@V?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@23@@__Cr@std@@QEAA@Upiecewise_construct_t@12@V?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@@Z ??$?0$$T@?$Storage@PEAPEAUCordRep@cord_internal@absl@@$00U?$StorageTag@V?$allocator@PEAUCordRep@cord_internal@absl@@@__Cr@std@@PEAPEAUCordRep@cord_internal@absl@@@internal_compressed_tuple@container_internal@3@$0A@@internal_compressed_tuple@container_internal@absl@@QEAA@Uin_place_t@__Cr@std@@$$QEA$$T@Z @@ -55,10 +55,6 @@ EXPORTS ??$?0$00X@?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAA@PEAVZoneInfoSource@cctz@time_internal@absl@@@Z ??$?0$00X@?$unique_ptr@XUDynValueDeleter@flags_internal@absl@@@__Cr@std@@QEAA@$$T@Z ??$?0$00X@?$unique_ptr@XUDynValueDeleter@flags_internal@absl@@@__Cr@std@@QEAA@PEAX$$QEAUDynValueDeleter@flags_internal@absl@@@Z - ??$?0$0A@$$Z$$QEAPEAVCommandLineFlag@absl@@$$Z$S$$Z$$V$$ZPEAV01@@?$__tuple_impl@U?$__tuple_indices@$0A@@__Cr@std@@$$QEAPEAVCommandLineFlag@absl@@@__Cr@std@@QEAA@U?$__tuple_indices@$0A@@12@U?$__tuple_types@$$QEAPEAVCommandLineFlag@absl@@@12@U?$__tuple_indices@$S@12@U?$__tuple_types@$$V@12@$$QEAPEAVCommandLineFlag@absl@@@Z - ??$?0$0A@$$ZAEBQEAVCommandLineFlag@absl@@$$Z$S$$Z$$V$$ZAEBQEAV01@@?$__tuple_impl@U?$__tuple_indices@$0A@@__Cr@std@@AEBQEAVCommandLineFlag@absl@@@__Cr@std@@QEAA@U?$__tuple_indices@$0A@@12@U?$__tuple_types@AEBQEAVCommandLineFlag@absl@@@12@U?$__tuple_indices@$S@12@U?$__tuple_types@$$V@12@AEBQEAVCommandLineFlag@absl@@@Z - ??$?0$0A@$00$$ZAEAPEAVCommandLineFlag@absl@@AEA_N$$Z$S$$Z$$V$$ZAEAPEAV01@AEA_N@?$__tuple_impl@U?$__tuple_indices@$0A@$00@__Cr@std@@AEAPEAVCommandLineFlag@absl@@AEA_N@__Cr@std@@QEAA@U?$__tuple_indices@$0A@$00@12@U?$__tuple_types@AEAPEAVCommandLineFlag@absl@@AEA_N@12@U?$__tuple_indices@$S@12@U?$__tuple_types@$$V@12@AEAPEAVCommandLineFlag@absl@@AEA_N@Z - ??$?0$0A@$00$$ZPEAVCommandLineFlag@absl@@_N$$Z$S$$Z$$V$$ZAEAPEAV01@AEA_N@?$__tuple_impl@U?$__tuple_indices@$0A@$00@__Cr@std@@PEAVCommandLineFlag@absl@@_N@__Cr@std@@QEAA@U?$__tuple_indices@$0A@$00@12@U?$__tuple_types@PEAVCommandLineFlag@absl@@_N@12@U?$__tuple_indices@$S@12@U?$__tuple_types@$$V@12@AEAPEAVCommandLineFlag@absl@@AEA_N@Z ??$?0AEAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@AEAPEAPEAPEBV01234@$0A@@?$pair@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@@__Cr@std@@QEAA@AEAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@0@Z ??$?0AEAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV01234@$0A@@?$pair@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@@__Cr@std@@QEAA@AEAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@$$QEAPEAPEAPEBV34567@@Z ??$?0AEAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@AEAPEAPEAU0123@$0A@@?$pair@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU1234@@__Cr@std@@QEAA@AEAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@0@Z @@ -73,6 +69,8 @@ EXPORTS ??$?0AEAPEAVCommandLineFlag@absl@@$0A@@?$__tuple_leaf@$0A@AEAPEAVCommandLineFlag@absl@@$0A@@__Cr@std@@QEAA@AEAPEAVCommandLineFlag@absl@@@Z ??$?0AEAPEAVCommandLineFlag@absl@@$0A@@?$__tuple_leaf@$0A@PEAVCommandLineFlag@absl@@$0A@@__Cr@std@@QEAA@AEAPEAVCommandLineFlag@absl@@@Z ??$?0AEAPEAVCommandLineFlag@absl@@AEA_N$0A@@?$tuple@PEAVCommandLineFlag@absl@@_N@__Cr@std@@QEAA@AEAPEAVCommandLineFlag@absl@@AEA_N@Z + ??$?0AEAPEAVCommandLineFlag@absl@@AEA_N@?$__tuple_impl@U?$__integer_sequence@_K$0A@$00@__Cr@std@@AEAPEAVCommandLineFlag@absl@@AEA_N@__Cr@std@@QEAA@U__forward_args@12@AEAPEAVCommandLineFlag@absl@@AEA_N@Z + ??$?0AEAPEAVCommandLineFlag@absl@@AEA_N@?$__tuple_impl@U?$__integer_sequence@_K$0A@$00@__Cr@std@@PEAVCommandLineFlag@absl@@_N@__Cr@std@@QEAA@U__forward_args@12@AEAPEAVCommandLineFlag@absl@@AEA_N@Z ??$?0AEAPEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEAU0123@$0A@@?$pair@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@@__Cr@std@@QEAA@AEAPEBUPrefixCrc@CrcCordState@crc_internal@absl@@$$QEAPEAU3456@@Z ??$?0AEAUraw_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@@AEBV234@@Z@@?$__temp_value@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@@QEAA@AEAV?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAUraw_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@@12@AEBV678@@Z@@Z ??$?0AEAV?$__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@@12@$0A@@?$pair@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@@__Cr@std@@QEAA@AEAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@12@$$QEAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@12@@Z @@ -93,6 +91,7 @@ EXPORTS ??$?0AEA_KAEBV?$allocator@D@__Cr@std@@$00@?$CompressedTuple@_KV?$allocator@D@__Cr@std@@@container_internal@absl@@QEAA@AEA_KAEBV?$allocator@D@__Cr@std@@@Z ??$?0AEA_KAEBV?$allocator@D@__Cr@std@@@?$CompressedTupleImpl@V?$CompressedTuple@_KV?$allocator@D@__Cr@std@@@container_internal@absl@@U?$integer_sequence@_K$0A@$00@__Cr@std@@$00@internal_compressed_tuple@container_internal@absl@@QEAA@Uin_place_t@__Cr@std@@AEA_KAEBV?$allocator@D@56@@Z ??$?0AEBQEAVCommandLineFlag@absl@@$0A@@?$__tuple_leaf@$0A@AEBQEAVCommandLineFlag@absl@@$0A@@__Cr@std@@QEAA@AEBQEAVCommandLineFlag@absl@@@Z + ??$?0AEBQEAVCommandLineFlag@absl@@@?$__tuple_impl@U?$__integer_sequence@_K$0A@@__Cr@std@@AEBQEAVCommandLineFlag@absl@@@__Cr@std@@QEAA@U__forward_args@12@AEBQEAVCommandLineFlag@absl@@@Z ??$?0AEBV?$allocator@D@__Cr@std@@@?$Storage@V?$allocator@D@__Cr@std@@$00U?$StorageTag@_KV?$allocator@D@__Cr@std@@@internal_compressed_tuple@container_internal@absl@@$00@internal_compressed_tuple@container_internal@absl@@QEAA@Uin_place_t@__Cr@std@@AEBV?$allocator@D@56@@Z ??$?0AEBV?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@?$Storage@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@$0A@U?$StorageTag@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@_K@internal_compressed_tuple@container_internal@absl@@$00@internal_compressed_tuple@container_internal@absl@@QEAA@Uin_place_t@__Cr@std@@AEBV?$allocator@UPayload@status_internal@absl@@@56@@Z ??$?0AEBV?$allocator@UPayload@status_internal@absl@@@__Cr@std@@I$00@?$CompressedTuple@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@_K@container_internal@absl@@QEAA@AEBV?$allocator@UPayload@status_internal@absl@@@__Cr@std@@$$QEAI@Z @@ -100,11 +99,11 @@ EXPORTS ??$?0AEBV?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@@?$Storage@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@$0A@U?$StorageTag@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@_K@internal_compressed_tuple@container_internal@absl@@$00@internal_compressed_tuple@container_internal@absl@@QEAA@Uin_place_t@__Cr@std@@AEBV?$allocator@VFormatArgImpl@str_format_internal@absl@@@56@@Z ??$?0AEBV?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@I$00@?$CompressedTuple@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@_K@container_internal@absl@@QEAA@AEBV?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@$$QEAI@Z ??$?0AEBV?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@I@?$CompressedTupleImpl@V?$CompressedTuple@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@_K@container_internal@absl@@U?$integer_sequence@_K$0A@$00@__Cr@std@@$00@internal_compressed_tuple@container_internal@absl@@QEAA@Uin_place_t@__Cr@std@@AEBV?$allocator@VFormatArgImpl@str_format_internal@absl@@@56@$$QEAI@Z - ??$?0AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V$$Z$0A@$$Z$S@?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@AEAV?$tuple@$$V@12@U?$__tuple_indices@$0A@@12@U?$__tuple_indices@$S@12@@Z - ??$?0AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V$$Z$0A@$$Z$S@?$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@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@AEAV?$tuple@$$V@12@U?$__tuple_indices@$0A@@12@U?$__tuple_indices@$S@12@@Z + ??$?0AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V$$Z$0A@$$Z$S@?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@AEAV?$tuple@$$V@12@U?$__integer_sequence@_K$0A@@12@U?$__integer_sequence@_K$S@12@@Z + ??$?0AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V$$Z$0A@$$Z$S@?$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@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@AEAV?$tuple@$$V@12@U?$__integer_sequence@_K$0A@@12@U?$__integer_sequence@_K$S@12@@Z ??$?0AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V@?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@QEAA@Upiecewise_construct_t@12@V?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@V?$tuple@$$V@12@@Z ??$?0AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V@?$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@@QEAA@Upiecewise_construct_t@12@V?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@V?$tuple@$$V@12@@Z - ??$?0AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$ZAEBQEAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$tuple@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@AEBQEAVCommandLineFlag@absl@@@23@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAV?$tuple@AEBQEAVCommandLineFlag@absl@@@12@U?$__tuple_indices@$0A@@12@3@Z + ??$?0AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$ZAEBQEAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$tuple@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@AEBQEAVCommandLineFlag@absl@@@23@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAV?$tuple@AEBQEAVCommandLineFlag@absl@@@12@U?$__integer_sequence@_K$0A@@12@3@Z ??$?0AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$ZAEBQEAVCommandLineFlag@absl@@@?$pair@V?$tuple@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@AEBQEAVCommandLineFlag@absl@@@23@@__Cr@std@@QEAA@Upiecewise_construct_t@12@V?$tuple@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$tuple@AEBQEAVCommandLineFlag@absl@@@12@@Z ??$?0D@?$allocator@U?$AlignedType@$07@container_internal@absl@@@__Cr@std@@QEAA@AEBV?$allocator@D@12@@Z ??$?0D@?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@QEAA@AEBV?$allocator@D@12@@Z @@ -130,6 +129,7 @@ EXPORTS ??$?0PEAUraw_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@@AEBV234@@Z@PEAU0?1???R1234@QEBA?AV567@0@Z@$0A@@?$pair@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@PEAU1?1???R2345@QEBA?AV678@0@Z@@__Cr@std@@QEAA@$$QEAPEAUraw_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@@12@AEBV567@@Z@1@Z ??$?0PEAVCommandLineFlag@absl@@$0A@@?$__tuple_leaf@$0A@$$QEAPEAVCommandLineFlag@absl@@$0A@@__Cr@std@@QEAA@$$QEAPEAVCommandLineFlag@absl@@@Z ??$?0PEAVCommandLineFlag@absl@@$0A@@?$tuple@$$QEAPEAVCommandLineFlag@absl@@@__Cr@std@@QEAA@$$QEAPEAVCommandLineFlag@absl@@@Z + ??$?0PEAVCommandLineFlag@absl@@@?$__tuple_impl@U?$__integer_sequence@_K$0A@@__Cr@std@@$$QEAPEAVCommandLineFlag@absl@@@__Cr@std@@QEAA@U__forward_args@12@$$QEAPEAVCommandLineFlag@absl@@@Z ??$?0PEAW4ctrl_t@container_internal@absl@@AEAPEAX$0A@@?$pair@PEAW4ctrl_t@container_internal@absl@@PEAX@__Cr@std@@QEAA@$$QEAPEAW4ctrl_t@container_internal@absl@@AEAPEAX@Z ??$?0PEAW4ctrl_t@container_internal@absl@@AEBQEAX$0A@@?$pair@PEAW4ctrl_t@container_internal@absl@@PEAX@__Cr@std@@QEAA@$$QEAPEAW4ctrl_t@container_internal@absl@@AEBQEAX@Z ??$?0PEAW4ctrl_t@container_internal@absl@@PEAX$0A@@?$pair@PEAW4ctrl_t@container_internal@absl@@PEAX@__Cr@std@@QEAA@$$QEAPEAW4ctrl_t@container_internal@absl@@$$QEAPEAX@Z @@ -190,9 +190,7 @@ EXPORTS ??$?0V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@X@?$function@$$A6AXAEAVCommandLineFlag@absl@@@Z@__Cr@std@@QEAA@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@@Z ??$?0V?$InlinedVector@VFormatArgImpl@str_format_internal@absl@@$03V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@@absl@@XV01@H@?$Span@$$CBVFormatArgImpl@str_format_internal@absl@@@absl@@QEAA@AEBV?$InlinedVector@VFormatArgImpl@str_format_internal@absl@@$03V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@@1@@Z ??$?0V?$Span@D@absl@@XV01@$0A@@?$Span@$$CBD@absl@@QEAA@AEBV?$Span@D@1@@Z - ??$?0V?$Span@D@absl@@XV01@$0A@@?$Span@D@absl@@QEAA@AEAV01@@Z ??$?0V?$Span@I@absl@@XV01@$0A@@?$Span@$$CBI@absl@@QEAA@AEBV?$Span@I@1@@Z - ??$?0V?$Span@I@absl@@XV01@$0A@@?$Span@I@absl@@QEAA@AEAV01@@Z ??$?0V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V012@$0A@@?$pair@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V123@@__Cr@std@@QEAA@$$QEAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@12@0@Z ??$?0V?$__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@@12@$0A@@?$pair@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@@__Cr@std@@QEAA@$$QEAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@12@$$QEAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@12@@Z ??$?0V?$__hash_iterator@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@AEA_N$0A@@?$pair@V?$__hash_iterator@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@_N@__Cr@std@@QEAA@$$QEAV?$__hash_iterator@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@12@AEA_N@Z @@ -539,8 +537,6 @@ EXPORTS ??$GetData@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@span_internal@absl@@YAPEBDAEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??$GetData@U?$array@D$0DKJI@@__Cr@std@@@span_internal@absl@@YAPEADAEAU?$array@D$0DKJI@@__Cr@std@@@Z ??$GetData@V?$InlinedVector@PEAVLogSink@absl@@$0BA@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@absl@@@span_internal@absl@@YAPEAPEAVLogSink@1@AEAV?$InlinedVector@PEAVLogSink@absl@@$0BA@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@1@@Z - ??$GetData@V?$Span@D@absl@@@span_internal@absl@@YAPEADAEAV?$Span@D@1@@Z - ??$GetData@V?$Span@I@absl@@@span_internal@absl@@YAPEAIAEAV?$Span@I@1@@Z ??$GetData@V?$vector@PEAVLogSink@absl@@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@__Cr@std@@@span_internal@absl@@YAPEAPEAVLogSink@1@AEAV?$vector@PEAVLogSink@absl@@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@__Cr@std@@@Z ??$GetDataImpl@$$CBV?$InlinedVector@VFormatArgImpl@str_format_internal@absl@@$03V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@@absl@@@span_internal@absl@@YAPEBVFormatArgImpl@str_format_internal@1@AEBV?$InlinedVector@VFormatArgImpl@str_format_internal@absl@@$03V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@@1@D@Z ??$GetDataImpl@$$CBV?$Span@D@absl@@@span_internal@absl@@YAPEADAEBV?$Span@D@1@D@Z @@ -548,8 +544,6 @@ EXPORTS ??$GetDataImpl@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@span_internal@absl@@YAPEBDAEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@D@Z ??$GetDataImpl@U?$array@D$0DKJI@@__Cr@std@@@span_internal@absl@@YAPEADAEAU?$array@D$0DKJI@@__Cr@std@@D@Z ??$GetDataImpl@V?$InlinedVector@PEAVLogSink@absl@@$0BA@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@absl@@@span_internal@absl@@YAPEAPEAVLogSink@1@AEAV?$InlinedVector@PEAVLogSink@absl@@$0BA@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@1@D@Z - ??$GetDataImpl@V?$Span@D@absl@@@span_internal@absl@@YAPEADAEAV?$Span@D@1@D@Z - ??$GetDataImpl@V?$Span@I@absl@@@span_internal@absl@@YAPEAIAEAV?$Span@I@1@D@Z ??$GetDataImpl@V?$vector@PEAVLogSink@absl@@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@__Cr@std@@@span_internal@absl@@YAPEAPEAVLogSink@1@AEAV?$vector@PEAVLogSink@absl@@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@__Cr@std@@D@Z ??$GetFlag@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@@@absl@@YA?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@@AEBV?$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@0@@Z ??$GrowSooTableToNextCapacityAndPrepareInsert@$00$00@container_internal@absl@@YA_KAEAVCommonFields@01@AEBUPolicyFunctions@01@V?$FunctionRef@$$A6A_K_K@Z@1@_N@Z @@ -846,8 +840,8 @@ EXPORTS ??$__at@P6A_K$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@Z$03$$V@__base@__visitation@__variant_detail@__Cr@std@@CA$$QEA_PAEBU?$__farray@P6A_K$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@Z$03@34@_K@Z ??$__at@P6A_K$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@Z@__base@__visitation@__variant_detail@__Cr@std@@CAAEBQ6A_K$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@1234@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@234@@ZAEBQ6A_K01@Z@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 - ??$__call_impl@V?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@$$A6AXAEAVCommandLineFlag@5@@Z@__function@__Cr@std@@@?$__policy_invoker@$$A6AXAEAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@CAXPEBT__policy_storage@123@AEAVCommandLineFlag@absl@@@Z - ??$__choose_policy@V?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@$$A6AXAEAVCommandLineFlag@5@@Z@__function@__Cr@std@@@__policy@__function@__Cr@std@@CAPEBU0123@U?$integral_constant@_N$00@23@@Z + ??$__call_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@@?$__policy_func@$$A6AXAEAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@CAXPEBT__policy_storage@123@AEAVCommandLineFlag@absl@@@Z + ??$__choose_policy@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@@__policy@__function@__Cr@std@@CAPEBU0123@U?$integral_constant@_N$00@23@@Z ??$__constexpr_memmove@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEBV12345@@__Cr@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@0W4__element_count@01@@Z ??$__constexpr_memmove@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@@__Cr@std@@YAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU2345@0W4__element_count@01@@Z ??$__constexpr_memmove@PEAVLogSink@absl@@PEAV12@@__Cr@std@@YAPEAPEAVLogSink@absl@@PEAPEAV23@0W4__element_count@01@@Z @@ -907,7 +901,7 @@ EXPORTS ??$__construct_node@AEBUpiecewise_construct_t@__Cr@std@@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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AEAA?AV?$unique_ptr@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@@V?$__tree_node_destructor@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@@@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 ??$__construct_node@AEBUpiecewise_construct_t@__Cr@std@@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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__Cr@std@@AEAA?AV?$unique_ptr@V?$__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@__Cr@std@@V?$__tree_node_destructor@V?$allocator@V?$__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@__Cr@std@@@__Cr@std@@@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 ??$__construct_node_hash@AEBQEBUCordRep@cord_internal@absl@@$$V@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@AEAA?AV?$unique_ptr@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@23@@12@_KAEBQEBUCordRep@cord_internal@absl@@@Z - ??$__construct_node_hash@AEBUpiecewise_construct_t@__Cr@std@@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@@AEAA?AV?$unique_ptr@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@@V?$__hash_node_destructor@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@@@23@@12@_KAEBUpiecewise_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 + ??$__construct_node_hash@AEBUpiecewise_construct_t@__Cr@std@@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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AEAA?AV?$unique_ptr@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@@V?$__hash_node_destructor@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@@@23@@12@_KAEBUpiecewise_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 ??$__copy@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@PEAU1234@@__Cr@std@@YA?AU?$pair@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@@01@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@0PEAU3456@@Z ??$__copy@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@@__Cr@std@@YA?AU?$pair@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@@01@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@0V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@01@@Z ??$__copy@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V123@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@__Cr@std@@YA?AU?$pair@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@@01@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@01@0V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@01@@Z @@ -933,14 +927,15 @@ EXPORTS ??$__copy_trivial_impl@PEAVLogSink@absl@@PEAV12@@__Cr@std@@YA?AU?$pair@PEAPEAVLogSink@absl@@PEAPEAV12@@01@PEAPEAVLogSink@absl@@00@Z ??$__copy_trivial_impl@UTransition@cctz@time_internal@absl@@U1234@@__Cr@std@@YA?AU?$pair@PEAUTransition@cctz@time_internal@absl@@PEAU1234@@01@PEAUTransition@cctz@time_internal@absl@@00@Z ??$__copy_trivial_impl@UTransitionType@cctz@time_internal@absl@@U1234@@__Cr@std@@YA?AU?$pair@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@01@PEAUTransitionType@cctz@time_internal@absl@@00@Z - ??$__create@V?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@$$A6AXAEAVCommandLineFlag@5@@Z@__function@__Cr@std@@@?$__policy_invoker@$$A6AXAEAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@SA?AU0123@XZ - ??$__create@V?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@$$A6AXAEAVCommandLineFlag@5@@Z@__function@__Cr@std@@@__policy@__function@__Cr@std@@SAPEBU0123@XZ + ??$__create@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@@__policy@__function@__Cr@std@@SAPEBU0123@XZ + ??$__cxx_atomic_compare_exchange_strong@PEAUArena@LowLevelAlloc@base_internal@absl@@@__Cr@std@@YA_NPEAU?$__cxx_atomic_base_impl@PEAUArena@LowLevelAlloc@base_internal@absl@@@01@PEAPEAUArena@LowLevelAlloc@base_internal@absl@@PEAU3456@W4memory_order@01@3@Z ??$__cxx_atomic_compare_exchange_strong@PEAVTimeZone@absl@@@__Cr@std@@YA_NPEAU?$__cxx_atomic_base_impl@PEAVTimeZone@absl@@@01@PEAPEAVTimeZone@absl@@PEAV34@W4memory_order@01@3@Z ??$__cxx_atomic_compare_exchange_strong@PEAVVLogSite@log_internal@absl@@@__Cr@std@@YA_NPEAU?$__cxx_atomic_base_impl@PEAVVLogSite@log_internal@absl@@@01@PEAPEAVVLogSite@log_internal@absl@@PEAV345@W4memory_order@01@3@Z ??$__cxx_atomic_compare_exchange_weak@PEAUHashtablezInfo@container_internal@absl@@@__Cr@std@@YA_NPEAU?$__cxx_atomic_base_impl@PEAUHashtablezInfo@container_internal@absl@@@01@PEAPEAUHashtablezInfo@container_internal@absl@@PEAU345@W4memory_order@01@3@Z ??$__cxx_atomic_compare_exchange_weak@PEAVVLogSite@log_internal@absl@@@__Cr@std@@YA_NPEAU?$__cxx_atomic_base_impl@PEAVVLogSite@log_internal@absl@@@01@PEAPEAVVLogSite@log_internal@absl@@PEAV345@W4memory_order@01@3@Z ??$__cxx_atomic_exchange@PEAVVLogSite@log_internal@absl@@@__Cr@std@@YAPEAVVLogSite@log_internal@absl@@PEAU?$__cxx_atomic_base_impl@PEAVVLogSite@log_internal@absl@@@01@PEAV234@W4memory_order@01@@Z ??$__cxx_atomic_load@P6AXAEBUHashtablezInfo@container_internal@absl@@@Z@__Cr@std@@YAP6AXAEBUHashtablezInfo@container_internal@absl@@@ZPEBU?$__cxx_atomic_base_impl@P6AXAEBUHashtablezInfo@container_internal@absl@@@Z@01@W4memory_order@01@@Z + ??$__cxx_atomic_load@PEAUArena@LowLevelAlloc@base_internal@absl@@@__Cr@std@@YAPEAUArena@LowLevelAlloc@base_internal@absl@@PEBU?$__cxx_atomic_base_impl@PEAUArena@LowLevelAlloc@base_internal@absl@@@01@W4memory_order@01@@Z ??$__cxx_atomic_load@PEAUHashtablezInfo@container_internal@absl@@@__Cr@std@@YAPEAUHashtablezInfo@container_internal@absl@@PEBU?$__cxx_atomic_base_impl@PEAUHashtablezInfo@container_internal@absl@@@01@W4memory_order@01@@Z ??$__cxx_atomic_load@PEAVCordzHandle@cord_internal@absl@@@__Cr@std@@YAPEAVCordzHandle@cord_internal@absl@@PEBU?$__cxx_atomic_base_impl@PEAVCordzHandle@cord_internal@absl@@@01@W4memory_order@01@@Z ??$__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 @@ -997,7 +992,7 @@ EXPORTS ??$__distance@V?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YA_JV?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@01@0Urandom_access_iterator_tag@01@@Z ??$__distance@V?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YA_JV?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@0Urandom_access_iterator_tag@01@@Z ??$__do_rehash@$00@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@AEAAX_K@Z - ??$__do_rehash@$00@?$__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@@AEAAX_K@Z + ??$__do_rehash@$00@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AEAAX_K@Z ??$__emplace_back_assume_capacity@$$V@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXXZ ??$__emplace_back_assume_capacity@$$V@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXXZ ??$__emplace_back_assume_capacity@AEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@AEBV123@AEA_K@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXAEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@12@AEBV312@AEA_K@Z @@ -1024,9 +1019,11 @@ EXPORTS ??$__emplace_back_slow_path@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@?$vector@UConversionItem@ParsedFormatBase@str_format_internal@absl@@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAPEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@$$QEAU3456@@Z ??$__emplace_back_slow_path@V?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@@?$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@@AEAAPEAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@12@$$QEAV312@@Z ??$__emplace_back_slow_path@W4Source@UnrecognizedFlag@absl@@AEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$vector@UUnrecognizedFlag@absl@@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@@__Cr@std@@AEAAPEAUUnrecognizedFlag@absl@@$$QEAW4Source@34@AEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@12@@Z + ??$__emplace_unique@AEBQEBUCordRep@cord_internal@absl@@@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAA?AU?$pair@V?$__hash_iterator@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@_N@12@AEBQEBUCordRep@cord_internal@absl@@@Z + ??$__emplace_unique_extract_key@AEBQEBUCordRep@cord_internal@absl@@@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAA?AU?$pair@V?$__hash_iterator@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@_N@12@AEBQEBUCordRep@cord_internal@absl@@U__extract_key_self_tag@12@@Z ??$__emplace_unique_key_args@PEBUCordRep@cord_internal@absl@@AEBQEBU123@@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAA?AU?$pair@V?$__hash_iterator@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@_N@12@AEBQEBUCordRep@cord_internal@absl@@0@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@$$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEAAAEAPEAV?$__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 @@ -1068,13 +1065,6 @@ EXPORTS ??$__invoke_r@XAEAV@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@AEAVCommandLineFlag@5@@__Cr@std@@YAXAEAV@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@AEAVCommandLineFlag@6@@Z ??$__iter_move@AEAPEAPEAVCommandLineFlag@absl@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QEAPEAVCommandLineFlag@absl@@AEAPEAPEAV34@@Z ??$__iter_move@AEAPEAPEBVCommandLineFlag@absl@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QEAPEBVCommandLineFlag@absl@@AEAPEAPEBV34@@Z - ??$__launder@$$CBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YAPEBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@01@PEBU201@@Z - ??$__launder@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YAPEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@01@PEAU201@@Z - ??$__launder@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@YAPEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@01@PEAU201@@Z - ??$__launder@URefcountedRep@CrcCordState@crc_internal@absl@@@__Cr@std@@YAPEAURefcountedRep@CrcCordState@crc_internal@absl@@PEAU2345@@Z - ??$__launder@V?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@absl@@@__Cr@std@@YAPEAV?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@absl@@PEAV234@@Z - ??$__launder@VFlagRegistry@flags_internal@absl@@@__Cr@std@@YAPEAVFlagRegistry@flags_internal@absl@@PEAV234@@Z - ??$__launder@VMutex@absl@@@__Cr@std@@YAPEAVMutex@absl@@PEAV23@@Z ??$__libcpp_allocate@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@W4__element_count@01@_K@Z ??$__libcpp_allocate@PEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@YAPEAPEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@01@W4__element_count@01@_K@Z ??$__libcpp_allocate@PEAU?$__hash_node_base@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@@@__Cr@std@@YAPEAPEAU?$__hash_node_base@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@@@01@W4__element_count@01@_K@Z @@ -1127,63 +1117,11 @@ EXPORTS ??$__libcpp_deallocate@V?$__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@__Cr@std@@@__Cr@std@@YAXPEAV?$__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@01@W4__element_count@01@_K@Z ??$__libcpp_deallocate@V?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@@__Cr@std@@YAXPEAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@01@W4__element_count@01@_K@Z ??$__libcpp_deallocate@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@YAXPEAVFormatArgImpl@str_format_internal@absl@@W4__element_count@01@_K@Z - ??$__libcpp_operator_delete@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@YAXPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAPEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@YAXPEAPEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@01@@Z - ??$__libcpp_operator_delete@PEAPEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@W4align_val_t@3@@__Cr@std@@YAXPEAPEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@01@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAPEAU?$__hash_node_base@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@@@__Cr@std@@YAXPEAPEAU?$__hash_node_base@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@@@01@@Z - ??$__libcpp_operator_delete@PEAPEAU?$__hash_node_base@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@@W4align_val_t@3@@__Cr@std@@YAXPEAPEAU?$__hash_node_base@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@@@01@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAPEAUCordRep@cord_internal@absl@@@__Cr@std@@YAXPEAPEAUCordRep@cord_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAPEAUCordRep@cord_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAPEAUCordRep@cord_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@YAXPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAPEAVCommandLineFlag@absl@@@__Cr@std@@YAXPEAPEAVCommandLineFlag@absl@@@Z - ??$__libcpp_operator_delete@PEAPEAVCommandLineFlag@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAPEAVCommandLineFlag@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@YAXPEAPEAVCordzHandle@cord_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAPEAVCordzHandle@cord_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAPEAVCordzHandle@cord_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAPEAVLogSink@absl@@@__Cr@std@@YAXPEAPEAVLogSink@absl@@@Z - ??$__libcpp_operator_delete@PEAPEAVLogSink@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAPEAVLogSink@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAPEBVCommandLineFlag@absl@@@__Cr@std@@YAXPEAPEBVCommandLineFlag@absl@@@Z - ??$__libcpp_operator_delete@PEAPEBVCommandLineFlag@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAPEBVCommandLineFlag@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@YAXPEAPEBVCordzHandle@cord_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAPEBVCordzHandle@cord_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAPEBVCordzHandle@cord_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@YAXPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAPEBVImpl@time_zone@cctz@time_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAU?$AlignedType@$07@container_internal@absl@@@__Cr@std@@YAXPEAU?$AlignedType@$07@container_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAU?$AlignedType@$07@container_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAU?$AlignedType@$07@container_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@YAXPEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@01@@Z - ??$__libcpp_operator_delete@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@W4align_val_t@3@@__Cr@std@@YAXPEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@01@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@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@@YAXPEAU?$__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@01@@Z - ??$__libcpp_operator_delete@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@@W4align_val_t@3@@__Cr@std@@YAXPEAU?$__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@01@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@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@23@PEBXPEAX2@Z@@__Cr@std@@YAXPEAUAlignedSpace@?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@34@PEBXPEAX2@Z@@Z - ??$__libcpp_operator_delete@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@23@PEBXPEAX2@Z@W4align_val_t@std@@@__Cr@std@@YAXPEAUAlignedSpace@?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@34@PEBXPEAX2@Z@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@YAXPEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAUPayload@status_internal@absl@@@__Cr@std@@YAXPEAUPayload@status_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAUPayload@status_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAUPayload@status_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@YAXPEAUPrefixCrc@CrcCordState@crc_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAUPrefixCrc@CrcCordState@crc_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@YAXPEAUTransition@cctz@time_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAUTransition@cctz@time_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAUTransition@cctz@time_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@YAXPEAUTransitionType@cctz@time_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAUTransitionType@cctz@time_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAUTransitionType@cctz@time_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAUUnrecognizedFlag@absl@@@__Cr@std@@YAXPEAUUnrecognizedFlag@absl@@@Z - ??$__libcpp_operator_delete@PEAUUnrecognizedFlag@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAUUnrecognizedFlag@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@YAXPEAUViableSubstitution@strings_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAUViableSubstitution@strings_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAUViableSubstitution@strings_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@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@__Cr@std@@@__Cr@std@@YAXPEAV?$__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@01@@Z - ??$__libcpp_operator_delete@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@__Cr@std@@W4align_val_t@3@@__Cr@std@@YAXPEAV?$__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@01@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@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@__Cr@std@@@__Cr@std@@YAXPEAV?$__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@01@@Z - ??$__libcpp_operator_delete@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@__Cr@std@@W4align_val_t@3@@__Cr@std@@YAXPEAV?$__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@01@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@@__Cr@std@@YAXPEAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@01@@Z - ??$__libcpp_operator_delete@PEAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@W4align_val_t@3@@__Cr@std@@YAXPEAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@01@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAVFormatArgImpl@str_format_internal@absl@@@__Cr@std@@YAXPEAVFormatArgImpl@str_format_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAVFormatArgImpl@str_format_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAVFormatArgImpl@str_format_internal@absl@@W4align_val_t@1@@Z ??$__lower_bound@U_ClassicAlgPolicy@__Cr@std@@PEBUTransition@cctz@time_internal@absl@@PEBU4567@U4567@U__identity@23@UByUnixTime@4567@@__Cr@std@@YAPEBUTransition@cctz@time_internal@absl@@PEBU2345@0AEBU2345@AEAUByUnixTime@2345@AEAU__identity@01@@Z ??$__lower_bound_bisecting@U_ClassicAlgPolicy@__Cr@std@@PEBUTransition@cctz@time_internal@absl@@U4567@U__identity@23@UByUnixTime@4567@@__Cr@std@@YAPEBUTransition@cctz@time_internal@absl@@PEBU2345@AEBU2345@_JAEAUByUnixTime@2345@AEAU__identity@01@@Z ??$__make_exception_guard@V?$_AllocatorDestroyRangeReverse@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@PEAUUnrecognizedFlag@absl@@@__Cr@std@@@__Cr@std@@YA?AU?$__exception_guard_noexceptions@V?$_AllocatorDestroyRangeReverse@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@PEAUUnrecognizedFlag@absl@@@__Cr@std@@@01@V?$_AllocatorDestroyRangeReverse@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@PEAUUnrecognizedFlag@absl@@@01@@Z ??$__make_value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@CA?A_P$$QEAUBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@78@@Z@@Z - ??$__memberwise_forward_assign@V?$tuple@AEAPEAVCommandLineFlag@absl@@AEA_N@__Cr@std@@V?$tuple@PEAVCommandLineFlag@absl@@_N@23@PEAVCommandLineFlag@absl@@_N$$Z$0A@$00@__Cr@std@@YAXAEAV?$tuple@AEAPEAVCommandLineFlag@absl@@AEA_N@01@$$QEAV?$tuple@PEAVCommandLineFlag@absl@@_N@01@U?$__tuple_types@PEAVCommandLineFlag@absl@@_N@01@U?$__tuple_indices@$0A@$00@01@@Z + ??$__memberwise_forward_assign@V?$tuple@AEAPEAVCommandLineFlag@absl@@AEA_N@__Cr@std@@V?$tuple@PEAVCommandLineFlag@absl@@_N@23@PEAVCommandLineFlag@absl@@_N$$Z$0A@$00@__Cr@std@@YAXAEAV?$tuple@AEAPEAVCommandLineFlag@absl@@AEA_N@01@$$QEAV?$tuple@PEAVCommandLineFlag@absl@@_N@01@U?$__tuple_types@PEAVCommandLineFlag@absl@@_N@01@U?$__integer_sequence@_K$0A@$00@01@@Z ??$__move@U_ClassicAlgPolicy@__Cr@std@@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV45678@PEAPEAPEBV45678@@__Cr@std@@YA?AU?$pair@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@@01@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@00@Z ??$__move@U_ClassicAlgPolicy@__Cr@std@@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU4567@PEAPEAU4567@@__Cr@std@@YA?AU?$pair@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU1234@@01@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@00@Z ??$__move@U_ClassicAlgPolicy@__Cr@std@@PEAPEAVLogSink@absl@@PEAPEAV45@PEAPEAV45@@__Cr@std@@YA?AU?$pair@PEAPEAVLogSink@absl@@PEAPEAV12@@01@PEAPEAVLogSink@absl@@00@Z @@ -1195,7 +1133,7 @@ EXPORTS ??$__move_backward@U_ClassicAlgPolicy@__Cr@std@@PEAUTransitionType@cctz@time_internal@absl@@PEAU4567@PEAU4567@@__Cr@std@@YA?AU?$pair@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@01@PEAUTransitionType@cctz@time_internal@absl@@00@Z ??$__not_null@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@@__function@__Cr@std@@YA_NAEBV@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@@Z ??$__rehash@$00@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@AEAAX_K@Z - ??$__rehash@$00@?$__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@@AEAAX_K@Z + ??$__rehash@$00@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AEAAX_K@Z ??$__rewrap_iter@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@U?$__unwrap_iter_impl@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@$00@__Cr@std@@@__Cr@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@0@Z ??$__rewrap_iter@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU1234@U?$__unwrap_iter_impl@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@$00@__Cr@std@@@__Cr@std@@YAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU2345@0@Z ??$__rewrap_iter@PEAPEAVLogSink@absl@@PEAPEAV12@U?$__unwrap_iter_impl@PEAPEAVLogSink@absl@@$00@__Cr@std@@@__Cr@std@@YAPEAPEAVLogSink@absl@@PEAPEAV23@0@Z @@ -1481,7 +1419,7 @@ EXPORTS ??$end@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 ??$end@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 ??$find@V?$__wrap_iter@PEAPEAVLogSink@absl@@@__Cr@std@@PEAVLogSink@absl@@@__Cr@std@@YA?AV?$__wrap_iter@PEAPEAVLogSink@absl@@@01@V201@0AEBQEAVLogSink@absl@@@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@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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@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@@QEAA?AViterator@012@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??$find@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@@QEBA?AVconst_iterator@012@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??$find_large@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?AViterator@012@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@_K@Z @@ -1549,8 +1487,6 @@ EXPORTS ??$iter_swap@PEAPEAVCommandLineFlag@absl@@PEAPEAV12@@__Cr@std@@YAXPEAPEAVCommandLineFlag@absl@@0@Z ??$iter_swap@PEAPEBVCommandLineFlag@absl@@PEAPEBV12@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAX$$QEAPEAPEBVCommandLineFlag@absl@@0@Z ??$iter_swap@PEAPEBVCommandLineFlag@absl@@PEAPEBV12@@__Cr@std@@YAXPEAPEBVCommandLineFlag@absl@@0@Z - ??$launder@$$CBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YAPEBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@01@PEBU201@@Z - ??$launder@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YAPEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@01@PEAU201@@Z ??$launder@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@YAPEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@01@PEAU201@@Z ??$launder@URefcountedRep@CrcCordState@crc_internal@absl@@@__Cr@std@@YAPEAURefcountedRep@CrcCordState@crc_internal@absl@@PEAU2345@@Z ??$launder@V?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@absl@@@__Cr@std@@YAPEAV?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@absl@@PEAV234@@Z @@ -1740,7 +1676,6 @@ EXPORTS ??0?$__cxx_atomic_impl@PEAUHashtablezInfo@container_internal@absl@@U?$__cxx_atomic_base_impl@PEAUHashtablezInfo@container_internal@absl@@@__Cr@std@@@__Cr@std@@QEAA@PEAUHashtablezInfo@container_internal@absl@@@Z ??0?$__cxx_atomic_impl@PEAVCordzHandle@cord_internal@absl@@U?$__cxx_atomic_base_impl@PEAVCordzHandle@cord_internal@absl@@@__Cr@std@@@__Cr@std@@QEAA@PEAVCordzHandle@cord_internal@absl@@@Z ??0?$__cxx_atomic_impl@PEAVCordzInfo@cord_internal@absl@@U?$__cxx_atomic_base_impl@PEAVCordzInfo@cord_internal@absl@@@__Cr@std@@@__Cr@std@@QEAA@PEAVCordzInfo@cord_internal@absl@@@Z - ??0?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@$$A6AXAEAVCommandLineFlag@5@@Z@__function@__Cr@std@@QEAA@$$QEAV@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@@Z ??0?$__deque_iterator@PEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEBV12345@AEAPEBV12345@PEAPEAPEBV12345@_J$0A@@__Cr@std@@AEAA@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEBV34567@@Z ??0?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@AEAA@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAU3456@@Z ??0?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@AEAA@PEBQEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU3456@@Z @@ -1760,7 +1695,7 @@ EXPORTS ??0?$__hash_node_destructor@V?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@QEAA@AEAV?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@12@_N@Z ??0?$__hash_node_destructor@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@@QEAA@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@@@12@_N@Z ??0?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAA@XZ - ??0?$__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@XZ + ??0?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@XZ ??0?$__map_iterator@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@@@__Cr@std@@QEAA@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@12@@Z ??0?$__map_iterator@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@@@__Cr@std@@QEAA@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@12@@Z ??0?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@__Cr@std@@QEAA@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@@Z @@ -1799,12 +1734,6 @@ EXPORTS ??0?$__optional_move_assign_base@VCord@absl@@$0A@@__Cr@std@@QEAA@XZ ??0?$__optional_move_base@VCord@absl@@$0A@@__Cr@std@@QEAA@XZ ??0?$__optional_storage_base@VCord@absl@@$0A@@__Cr@std@@QEAA@XZ - ??0?$__policy_invoker@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@23@@Z@__function@__Cr@std@@AEAA@P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@23@PEBT__policy_storage@123@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@23@@Z@Z - ??0?$__policy_invoker@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@23@@Z@__function@__Cr@std@@QEAA@XZ - ??0?$__policy_invoker@$$A6AXAEAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@AEAA@P6AXPEBT__policy_storage@123@AEAVCommandLineFlag@absl@@@Z@Z - ??0?$__policy_invoker@$$A6AXAEAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@QEAA@XZ - ??0?$__policy_invoker@$$A6A_NAEBVCommandLineFlag@absl@@@Z@__function@__Cr@std@@AEAA@P6A_NPEBT__policy_storage@123@AEBVCommandLineFlag@absl@@@Z@Z - ??0?$__policy_invoker@$$A6A_NAEBVCommandLineFlag@absl@@@Z@__function@__Cr@std@@QEAA@XZ ??0?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@AEAV?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAA@_K0AEAV?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@12@@Z ??0?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAA@XZ ??0?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@AEAV?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAA@_K0AEAV?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@12@@Z @@ -1828,8 +1757,8 @@ EXPORTS ??0?$__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@@AEAA@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@12@@Z ??0?$__tree_node_destructor@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@@QEAA@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@@@12@_N@Z ??0?$__tree_node_destructor@V?$allocator@V?$__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@__Cr@std@@@__Cr@std@@@__Cr@std@@QEAA@AEAV?$allocator@V?$__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@__Cr@std@@@12@_N@Z - ??0?$__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@__Cr@std@@QEAA@XZ - ??0?$__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@__Cr@std@@QEAA@XZ + ??0?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@__Cr@std@@QEAA@XZ + ??0?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@__Cr@std@@QEAA@XZ ??0?$__wrap_iter@PEAPEAVCommandLineFlag@absl@@@__Cr@std@@AEAA@PEAPEAVCommandLineFlag@absl@@@Z ??0?$__wrap_iter@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@AEAA@PEAPEAVCordzHandle@cord_internal@absl@@@Z ??0?$__wrap_iter@PEAPEAVLogSink@absl@@@__Cr@std@@AEAA@PEAPEAVLogSink@absl@@@Z @@ -2485,8 +2414,7 @@ EXPORTS ??Buint128@absl@@QEBA_WXZ ??C?$NoDestructor@URefcountedRep@CrcCordState@crc_internal@absl@@@absl@@QEAAPEAURefcountedRep@CrcCordState@crc_internal@1@XZ ??C?$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@@QEBAPEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ - ??C?$__hash_const_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@@QEBAPEBU?$__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@@@12@XZ - ??C?$__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@@QEBAPEAU?$__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@@@12@XZ + ??C?$__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@@QEBAPEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@12@XZ ??C?$__hash_map_const_iterator@V?$__hash_const_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@@@__Cr@std@@QEBAPEBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@12@XZ ??C?$__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@@QEBAPEAU?$pair@$$CBV?$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@@12@XZ ??C?$__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@@QEBAPEAU?$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@@12@XZ @@ -2512,6 +2440,8 @@ EXPORTS ??D?$__deque_iterator@PEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEBV12345@AEAPEBV12345@PEAPEAPEBV12345@_J$0A@@__Cr@std@@QEBAAEAPEBVImpl@time_zone@cctz@time_internal@absl@@XZ ??D?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@QEBAAEAUPrefixCrc@CrcCordState@crc_internal@absl@@XZ ??D?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@QEBAAEBUPrefixCrc@CrcCordState@crc_internal@absl@@XZ + ??D?$__hash_const_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@@QEBAAEBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@12@XZ + ??D?$__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@@QEBAAEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@12@XZ ??D?$__hash_map_iterator@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@@@__Cr@std@@QEBAAEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@12@XZ ??D?$__map_iterator@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@@@__Cr@std@@QEBAAEAU?$pair@$$CBV?$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@@12@XZ ??D?$__map_iterator@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@@@__Cr@std@@QEBAAEAU?$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@@12@XZ @@ -2678,7 +2608,6 @@ EXPORTS ??R?$__allocator_destructor@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXPEAUPrefixCrc@CrcCordState@crc_internal@absl@@@Z ??R?$__bucket_list_deallocator@V?$allocator@PEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@@__Cr@std@@QEAAXPEAPEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@12@@Z ??R?$__bucket_list_deallocator@V?$allocator@PEAU?$__hash_node_base@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@@@__Cr@std@@@__Cr@std@@QEAAXPEAPEAU?$__hash_node_base@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@@Z - ??R?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@$$A6AXAEAVCommandLineFlag@5@@Z@__function@__Cr@std@@QEAAXAEAVCommandLineFlag@absl@@@Z ??R?$__hash_node_destructor@V?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@QEAAXPEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@12@@Z ??R?$__hash_node_destructor@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@@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@12@@Z ??R?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@__Cr@std@@QEBA_NAEBU?$pair@$$CBV?$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@@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z @@ -2690,8 +2619,8 @@ EXPORTS ??R?$__policy_func@$$A6A_NAEBVCommandLineFlag@absl@@@Z@__function@__Cr@std@@QEBA_NAEBVCommandLineFlag@absl@@@Z ??R?$__tree_node_destructor@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@@QEAAXPEAV?$__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@12@@Z ??R?$__tree_node_destructor@V?$allocator@V?$__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@__Cr@std@@@__Cr@std@@@__Cr@std@@QEAAXPEAV?$__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@12@@Z - ??R?$__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@__Cr@std@@QEBA_NAEBU?$__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@@@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z - ??R?$__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@__Cr@std@@QEBA_KAEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z + ??R?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@__Cr@std@@QEBA_NAEBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z + ??R?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@__Cr@std@@QEBA_KAEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z ??R?$default_delete@$$CBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@QEBAXPEBVImpl@time_zone@cctz@time_internal@absl@@@Z ??R?$default_delete@ULogMessageData@LogMessage@log_internal@absl@@@__Cr@std@@QEBAXPEAULogMessageData@LogMessage@log_internal@absl@@@Z ??R?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@__Cr@std@@QEBAXPEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@Z @@ -3155,7 +3084,8 @@ EXPORTS ?EqualsImpl@Cord@absl@@AEBA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@_K@Z ?EquivTransitions@TimeZoneInfo@cctz@time_internal@absl@@AEBA_NEE@Z ?Erase@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAPEAUPayload@status_internal@3@PEBU453@0@Z - ?EraseMetaOnly@container_internal@absl@@YAXAEAVCommonFields@12@PEBW4ctrl_t@12@_K@Z + ?EraseMetaOnlyLarge@container_internal@absl@@YAXAEAVCommonFields@12@PEBW4ctrl_t@12@_K@Z + ?EraseMetaOnlySmall@container_internal@absl@@YAXAEAVCommonFields@12@_N_K@Z ?ErasePayload@StatusRep@status_internal@absl@@QEAA?AUEraseResult@123@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?ErrnoToStatus@absl@@YA?AVStatus@1@HV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?ErrnoToStatusCode@absl@@YA?AW4StatusCode@1@H@Z @@ -3482,6 +3412,7 @@ EXPORTS ?InitFrom@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAXAEBV123@@Z ?InitGrowthLeftNoDeleted@GrowthInfo@container_internal@absl@@QEAAX_K@Z ?InitInstance@CordRepBtree@cord_internal@absl@@AEAAXH_K0@Z + ?InitSigSafeArena@base_internal@absl@@YAXXZ ?InitTables@CRC32@crc_internal@absl@@UEAAXXZ ?InitTree@ChunkIterator@Cord@absl@@AEAAXPEAUCordRep@cord_internal@3@@Z ?InitWhat@BadStatusOrAccess@absl@@AEBAXXZ @@ -3582,7 +3513,6 @@ EXPORTS ?Lock@CordzInfo@cord_internal@absl@@QEAAXW4MethodIdentifier@CordzUpdateTracker@23@@Z ?Lock@FlagRegistry@flags_internal@absl@@QEAAXXZ ?Lock@Mutex@absl@@QEAAXXZ - ?Lock@SpinLock@base_internal@absl@@QEAAXXZ ?LockSlow@Mutex@absl@@AEAAXPEBUMuHowS@2@PEBVCondition@2@H@Z ?LockSlowLoop@Mutex@absl@@AEAAXPEAUSynchWaitParams@2@H@Z ?LockSlowWithDeadline@Mutex@absl@@AEAA_NPEBUMuHowS@2@PEBVCondition@2@VKernelTimeout@synchronization_internal@2@H@Z @@ -3605,6 +3535,7 @@ EXPORTS ?MakeAbsNanos@KernelTimeout@synchronization_internal@absl@@QEBA_JXZ ?MakeAbsTimespec@KernelTimeout@synchronization_internal@absl@@QEBA?AUtimespec@@XZ ?MakeCheckFailString@status_internal@absl@@YAPEBDPEBVStatus@2@PEBD@Z + ?MakeCheckOpUnprintableString@log_internal@absl@@YAXAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?MakeCheckOpValueString@log_internal@absl@@YAXAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@C@Z ?MakeCheckOpValueString@log_internal@absl@@YAXAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@D@Z ?MakeCheckOpValueString@log_internal@absl@@YAXAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@E@Z @@ -3631,7 +3562,6 @@ EXPORTS ?MaskEmpty@GroupAArch64Impl@container_internal@absl@@QEBA@XZ ?MaskEmptyOrDeleted@GroupPortableImpl@container_internal@absl@@QEBA@XZ ?MaskFull@GroupPortableImpl@container_internal@absl@@QEBA@XZ - ?MaskFullOrSentinel@GroupPortableImpl@container_internal@absl@@QEBA@XZ ?MaskNonFull@GroupAArch64Impl@container_internal@absl@@QEBA@XZ ?Match@GroupAArch64Impl@container_internal@absl@@QEBA@E@Z ?MatchesConversions@ParsedFormatBase@str_format_internal@absl@@AEBA_N_NV?$initializer_list@W4FormatConversionCharSet@absl@@@std@@@Z @@ -3818,7 +3748,6 @@ EXPORTS ?ReadSeedMaterialFromOSEntropy@random_internal@absl@@YA_NV?$Span@I@2@@Z ?ReadSequenceLockedData@FlagImpl@flags_internal@absl@@AEBAXPEAX@Z ?ReaderLock@Mutex@absl@@QEAAXXZ - ?ReaderTryLock@Mutex@absl@@QEAA_NXZ ?ReaderTryLockSlow@Mutex@absl@@AEAA_NXZ ?ReaderUnlock@Mutex@absl@@QEAAXXZ ?Rebuild@CordRepBtree@cord_internal@absl@@CAXPEAPEAV123@PEAV123@_N@Z @@ -3854,6 +3783,7 @@ EXPORTS ?RegisterMutexProfiler@absl@@YAXP6AX_J@Z@Z ?RegisterMutexTracer@absl@@YAXP6AXPEBDPEBX_J@Z@Z ?RegisterSpinLockProfiler@base_internal@absl@@YAXP6AXPEBX_J@Z@Z + ?RegisterWithTsan@SpinLock@base_internal@absl@@AEAAXXZ ?Rehash@container_internal@absl@@YAXAEAVCommonFields@12@AEBUPolicyFunctions@12@_K@Z ?RehashProbabilityConstant@container_internal@absl@@YA_KXZ ?RelaxedCopyFromAtomic@SequenceLock@flags_internal@absl@@CAXPEAXPEBU?$atomic@_K@__Cr@std@@_K@Z @@ -3993,6 +3923,7 @@ EXPORTS ?ShouldPrependLogPrefix@absl@@YA_NXZ ?ShouldSampleNextTable@container_internal@absl@@YA_NXZ ?ShouldSymbolizeLogStackTrace@log_internal@absl@@YA_NXZ + ?SigSafeArena@base_internal@absl@@YAPEAUArena@LowLevelAlloc@12@XZ ?Signal@CondVar@absl@@QEAAXXZ ?SignalAll@CondVar@absl@@QEAAXXZ ?SignedAddResult@int128_internal@absl@@YA?AVint128@2@V32@0@Z @@ -4189,7 +4120,6 @@ EXPORTS ?TrailingZeros@?$NonIterableBitMask@_K$07$02@container_internal@absl@@QEBAIXZ ?Trans@Mutex@absl@@AEAAXPEBUMuHowS@2@@Z ?Trunc@absl@@YA?AVDuration@1@V21@0@Z - ?TryLock@Mutex@absl@@QEAA_NXZ ?TryLockImpl@SpinLock@base_internal@absl@@AEAA_NXZ ?TryLockInternal@SpinLock@base_internal@absl@@AEAAIII@Z ?TryLockSlow@Mutex@absl@@AEAA_NXZ @@ -4227,7 +4157,6 @@ EXPORTS ?Unlock@CordzInfo@cord_internal@absl@@QEAAXXZ ?Unlock@FlagRegistry@flags_internal@absl@@QEAAXXZ ?Unlock@Mutex@absl@@QEAAXXZ - ?Unlock@SpinLock@base_internal@absl@@QEAAXXZ ?UnlockSlow@Mutex@absl@@AEAAXPEAUSynchWaitParams@2@@Z ?Unparse@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@F@Z ?Unparse@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@G@Z @@ -4419,15 +4348,10 @@ EXPORTS ?__base_destruct_at_end@?$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@@AEAAXPEAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@23@@Z ?__begin@?$__segmented_iterator_traits@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@@__Cr@std@@SAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU4567@@Z ?__begin@?$__segmented_iterator_traits@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@@__Cr@std@@SAPEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBQEBU4567@@Z - ?__begin_node@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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_end_node@PEAV?$__tree_node_base@PEAX@__Cr@std@@@23@XZ - ?__begin_node@?$__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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__Cr@std@@AEAAAEAPEAV?$__tree_end_node@PEAV?$__tree_node_base@PEAX@__Cr@std@@@23@XZ ?__call@?$__to_address_helper@V?$__wrap_iter@PEAPEAVCommandLineFlag@absl@@@__Cr@std@@X@__Cr@std@@SAPEAPEAVCommandLineFlag@absl@@AEBV?$__wrap_iter@PEAPEAVCommandLineFlag@absl@@@23@@Z ?__call@?$__to_address_helper@V?$__wrap_iter@PEAPEAVLogSink@absl@@@__Cr@std@@X@__Cr@std@@SAPEAPEAVLogSink@absl@@AEBV?$__wrap_iter@PEAPEAVLogSink@absl@@@23@@Z ?__call@?$__to_address_helper@V?$__wrap_iter@PEAPEBVCommandLineFlag@absl@@@__Cr@std@@X@__Cr@std@@SAPEAPEBVCommandLineFlag@absl@@AEBV?$__wrap_iter@PEAPEBVCommandLineFlag@absl@@@23@@Z ?__call@?$__to_address_helper@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@@X@__Cr@std@@SAPEAUraw_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@@23@AEBV678@@Z@AEBV?$__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@@23@@Z - ?__call_empty@?$__policy_invoker@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@23@@Z@__function@__Cr@std@@CA?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@34@PEBT__policy_storage@234@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@34@@Z - ?__call_empty@?$__policy_invoker@$$A6AXAEAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@CAXPEBT__policy_storage@234@AEAVCommandLineFlag@absl@@@Z - ?__call_empty@?$__policy_invoker@$$A6A_NAEBVCommandLineFlag@absl@@@Z@__function@__Cr@std@@CA_NPEBT__policy_storage@234@AEBVCommandLineFlag@absl@@@Z ?__capacity@?$deque@PEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ ?__capacity@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ ?__complete@?$__exception_guard_noexceptions@V?$_AllocatorDestroyRangeReverse@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@PEAUUnrecognizedFlag@absl@@@__Cr@std@@@__Cr@std@@QEAAXXZ @@ -4439,7 +4363,7 @@ EXPORTS ?__copy_assign_alloc@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAXAEBV123@@Z ?__copy_assign_alloc@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAXAEBV123@U?$integral_constant@_N$0A@@23@@Z ?__deallocate_node@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@AEAAXPEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@23@@Z - ?__deallocate_node@?$__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@@AEAAXPEAU?$__hash_node_base@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@@@23@@Z + ?__deallocate_node@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AEAAXPEAU?$__hash_node_base@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@@@23@@Z ?__destruct_at_begin@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@Z ?__destruct_at_begin@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@U?$integral_constant@_N$00@23@@Z ?__destruct_at_begin@?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@@Z @@ -4485,20 +4409,14 @@ EXPORTS ?__erase_to_end@?$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@@23@@Z ?__front_spare@?$deque@PEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ ?__front_spare@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ - ?__get_key@?$__hash_key_value_types@PEBUCordRep@cord_internal@absl@@@__Cr@std@@SAAEBQEBUCordRep@cord_internal@absl@@AEBQEBU456@@Z ?__get_np@?$__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@@AEBAPEAV?$__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@XZ ?__get_np@?$__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@@AEBAPEAV?$__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@XZ - ?__get_ptr@?$__hash_key_value_types@PEBUCordRep@cord_internal@absl@@@__Cr@std@@SAPEAPEBUCordRep@cord_internal@absl@@AEAPEBU456@@Z - ?__get_ptr@?$__hash_key_value_types@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@@@__Cr@std@@SAPEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@AEAU?$__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@@Z ?__get_value@?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@QEAAAEAPEBUCordRep@cord_internal@absl@@XZ - ?__get_value@?$__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@@QEAAAEAU?$__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@XZ - ?__get_value@?$__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@@QEAAAEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@XZ - ?__get_value@?$__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@@QEBAAEBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@XZ + ?__get_value@?$__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@@QEAAAEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@XZ ?__hash@?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@QEBA_KXZ ?__hash@?$__hash_node_base@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@@QEBA_KXZ ?__insert_node_at@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEAAXPEAV?$__tree_end_node@PEAV?$__tree_node_base@PEAX@__Cr@std@@@23@AEAPEAV?$__tree_node_base@PEAX@23@PEAV523@@Z ?__insert_node_at@?$__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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__Cr@std@@QEAAXPEAV?$__tree_end_node@PEAV?$__tree_node_base@PEAX@__Cr@std@@@23@AEAPEAV?$__tree_node_base@PEAX@23@PEAV523@@Z - ?__insert_unique@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAA?AU?$pair@V?$__hash_iterator@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@_N@23@AEBQEBUCordRep@cord_internal@absl@@@Z ?__local@?$__segmented_iterator_traits@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@@__Cr@std@@SAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@Z ?__local@?$__segmented_iterator_traits@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@@__Cr@std@@SAPEBUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@23@@Z ?__make_iter@?$vector@PEAVCommandLineFlag@absl@@V?$allocator@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@AEAA?AV?$__wrap_iter@PEAPEAVCommandLineFlag@absl@@@23@PEAPEAVCommandLineFlag@absl@@@Z @@ -4516,7 +4434,7 @@ EXPORTS ?__move_range@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAXPEAUTransition@cctz@time_internal@absl@@00@Z ?__move_range@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAXPEAUTransitionType@cctz@time_internal@absl@@00@Z ?__node_alloc@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAAAEAV?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@23@XZ - ?__node_alloc@?$__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@@QEAAAEAV?$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@XZ + ?__node_alloc@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEAAAEAV?$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@XZ ?__node_alloc@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$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@XZ ?__node_alloc@?$__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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__Cr@std@@QEAAAEAV?$allocator@V?$__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@__Cr@std@@@23@XZ ?__ptr@?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@QEAAPEAU123@XZ @@ -4534,7 +4452,7 @@ EXPORTS ?__recommend@?$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@@AEBA_K_K@Z ?__recommend_blocks@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@SA_K_K@Z ?__rehash_unique@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAAX_K@Z - ?__rehash_unique@?$__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@@QEAAX_K@Z + ?__rehash_unique@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEAAX_K@Z ?__rewrap@?$__unwrap_iter_impl@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@$00@__Cr@std@@SAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV45678@0@Z ?__rewrap@?$__unwrap_iter_impl@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@$00@__Cr@std@@SAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU4567@0@Z ?__rewrap@?$__unwrap_iter_impl@PEAPEAVLogSink@absl@@$00@__Cr@std@@SAPEAPEAVLogSink@absl@@PEAPEAV45@0@Z @@ -4673,6 +4591,7 @@ EXPORTS ?ascii_isxdigit@absl@@YA_NE@Z ?ascii_tolower@absl@@YADE@Z ?ascii_toupper@absl@@YADE@Z + ?assert_is_full@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@@AEBAXPEBD@Z ?at_end@?$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@@QEBA_NXZ ?back@?$InlinedVector@PEAUCordRep@cord_internal@absl@@$01V?$allocator@PEAUCordRep@cord_internal@absl@@@__Cr@std@@@absl@@QEAAAEAPEAUCordRep@cord_internal@2@XZ ?back@?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@AEAV?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAAEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@XZ @@ -4713,7 +4632,7 @@ EXPORTS ?begin@?$Splitter@VByAnyChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$SplitIterator@V?$Splitter@VByAnyChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@23@XZ ?begin@?$Splitter@VByAnyChar@absl@@USkipEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$SplitIterator@V?$Splitter@VByAnyChar@absl@@USkipEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@23@XZ ?begin@?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$SplitIterator@V?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@23@XZ - ?begin@?$__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@@@23@XZ + ?begin@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@@23@XZ ?begin@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@XZ ?begin@?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@XZ ?begin@?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEBAPEBQEAUPrefixCrc@CrcCordState@crc_internal@absl@@XZ @@ -4748,7 +4667,7 @@ EXPORTS ?btree@CordRepBtreeNavigator@cord_internal@absl@@QEBAPEAVCordRepBtree@23@XZ ?btree@CordRepBtreeReader@cord_internal@absl@@QEBAPEAVCordRepBtree@23@XZ ?bucket_count@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEBA_KXZ - ?bucket_count@?$__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@@QEBA_KXZ + ?bucket_count@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEBA_KXZ ?bytes_value@ProtoField@log_internal@absl@@QEBA?AV?$Span@$$CBD@3@XZ ?capacity@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@AEAV?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ ?capacity@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ @@ -4787,7 +4706,7 @@ EXPORTS ?chunk_begin@Cord@absl@@QEBA?AVChunkIterator@12@XZ ?chunk_end@Cord@absl@@QEBA?AVChunkIterator@12@XZ ?clear@?$InlinedVector@PEAVLogSink@absl@@$0BA@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@absl@@QEAAXXZ - ?clear@?$__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@@QEAAXXZ + ?clear@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEAAXXZ ?clear@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@AEAV?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXXZ ?clear@?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@AEAV?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXXZ ?clear@?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXXZ @@ -4823,6 +4742,7 @@ EXPORTS ?combine_raw@MixingHashState@hash_internal@absl@@CA?AV123@V123@_K@Z ?common@?$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@@AEAAAEAVCommonFields@23@XZ ?common@?$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@@AEBAAEBVCommonFields@23@XZ + ?compare_exchange_strong@?$__atomic_base@PEAUArena@LowLevelAlloc@base_internal@absl@@$0A@@__Cr@std@@QEAA_NAEAPEAUArena@LowLevelAlloc@base_internal@absl@@PEAU4567@W4memory_order@23@2@Z ?compare_exchange_strong@?$__atomic_base@PEAVTimeZone@absl@@$0A@@__Cr@std@@QEAA_NAEAPEAVTimeZone@absl@@PEAV45@W4memory_order@23@2@Z ?compare_exchange_strong@?$__atomic_base@PEAVVLogSite@log_internal@absl@@$0A@@__Cr@std@@QEAA_NAEAPEAVVLogSite@log_internal@absl@@PEAV456@W4memory_order@23@2@Z ?compare_exchange_weak@?$__atomic_base@PEAUHashtablezInfo@container_internal@absl@@$0A@@__Cr@std@@QEAA_NAEAPEAUHashtablezInfo@container_internal@absl@@PEAU456@W4memory_order@23@2@Z @@ -4986,7 +4906,7 @@ EXPORTS ?end@?$Splitter@VByAnyChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$SplitIterator@V?$Splitter@VByAnyChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@23@XZ ?end@?$Splitter@VByAnyChar@absl@@USkipEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$SplitIterator@V?$Splitter@VByAnyChar@absl@@USkipEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@23@XZ ?end@?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$SplitIterator@V?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@23@XZ - ?end@?$__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@@@23@XZ + ?end@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@@23@XZ ?end@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@XZ ?end@?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@XZ ?end@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?AV?$__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@23@XZ @@ -5022,7 +4942,6 @@ EXPORTS ?external@CordRep@cord_internal@absl@@QEBAPEBUCordRepExternal@23@XZ ?fetch_add_end@CordRepBtree@cord_internal@absl@@AEAA_K_K@Z ?find@?$unordered_map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@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@V?$allocator@U?$pair@$$CBV?$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_map_iterator@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@@@23@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@23@@Z - ?find_first_non_full@container_internal@absl@@YA?AUFindInfo@12@AEBVCommonFields@12@_K@Z ?fits_in_soo@?$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@@AEBA_N_K@Z ?fixed_time_zone@cctz@time_internal@absl@@YA?AVtime_zone@123@AEBV?$duration@_JV?$ratio@$00$00@__Cr@std@@@chrono@__Cr@std@@@Z ?flat@CordRep@cord_internal@absl@@QEAAPEAUCordRepFlat@23@XZ @@ -5131,7 +5050,7 @@ EXPORTS ?has_timeout@KernelTimeout@synchronization_internal@absl@@QEBA_NXZ ?has_zero_flag@FormatConversionSpecImpl@str_format_internal@absl@@QEBA_NXZ ?hash_function@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAAAEAU?$hash@PEBUCordRep@cord_internal@absl@@@23@XZ - ?hash_function@?$__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@@QEAAAEAV?$__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@XZ + ?hash_function@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEAAAEAV?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@XZ ?hash_ref@?$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@@AEAAAEAUStringHash@23@XZ ?hash_ref@?$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@@AEBAAEBUStringHash@23@XZ ?hash_with_seed@?$HashImpl@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@hash_internal@absl@@AEBA_KAEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@_K@Z @@ -5180,10 +5099,11 @@ EXPORTS ?iterator_at_ptr@?$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@@IEAA?AViterator@123@U?$pair@PEAW4ctrl_t@container_internal@absl@@PEAX@__Cr@std@@@Z ?kDefaultIterControl@container_internal@absl@@3W4ctrl_t@12@A ?key_eq@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAAAEAU?$equal_to@PEBUCordRep@cord_internal@absl@@@23@XZ - ?key_eq@?$__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@@QEAAAEAV?$__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@XZ + ?key_eq@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEAAAEAV?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@XZ ?length@CordRepBtreeReader@cord_internal@absl@@QEBA_KXZ ?length_mod@FormatConversionSpecImpl@str_format_internal@absl@@QEBA?AW4LengthMod@3@XZ ?load@?$__atomic_base@P6AXAEBUHashtablezInfo@container_internal@absl@@@Z$0A@@__Cr@std@@QEBAP6AXAEBUHashtablezInfo@container_internal@absl@@@ZW4memory_order@23@@Z + ?load@?$__atomic_base@PEAUArena@LowLevelAlloc@base_internal@absl@@$0A@@__Cr@std@@QEBAPEAUArena@LowLevelAlloc@base_internal@absl@@W4memory_order@23@@Z ?load@?$__atomic_base@PEAUHashtablezInfo@container_internal@absl@@$0A@@__Cr@std@@QEBAPEAUHashtablezInfo@container_internal@absl@@W4memory_order@23@@Z ?load@?$__atomic_base@PEAVCordzHandle@cord_internal@absl@@$0A@@__Cr@std@@QEBAPEAVCordzHandle@cord_internal@absl@@W4memory_order@23@@Z ?load@?$__atomic_base@PEAVCordzInfo@cord_internal@absl@@$0A@@__Cr@std@@QEBAPEAVCordzInfo@cord_internal@absl@@W4memory_order@23@@Z @@ -5194,6 +5114,9 @@ EXPORTS ?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 ?local_time_zone@cctz@time_internal@absl@@YA?AVtime_zone@123@XZ + ?lock@Mutex@absl@@QEAAXXZ + ?lock@SpinLock@base_internal@absl@@QEAAXXZ + ?lock_shared@Mutex@absl@@QEAAXXZ ?log_severity@LogEntry@absl@@QEBA?AW4LogSeverity@2@XZ ?lookup@time_zone@cctz@time_internal@absl@@QEBA?AUabsolute_lookup@1234@AEBV?$time_point@Vsystem_clock@chrono@__Cr@std@@V?$duration@_JV?$ratio@$00$00@__Cr@std@@@234@@chrono@__Cr@std@@@Z ?lookup@time_zone@cctz@time_internal@absl@@QEBA?AUcivil_lookup@1234@AEBV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@detail@234@@Z @@ -5204,7 +5127,7 @@ EXPORTS ?max@?$numeric_limits@Vint128@absl@@@__Cr@std@@SA?AVint128@absl@@XZ ?max@?$numeric_limits@Vuint128@absl@@@__Cr@std@@SA?AVuint128@absl@@XZ ?max_load_factor@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAAAEAMXZ - ?max_load_factor@?$__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@@QEAAAEAMXZ + ?max_load_factor@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEAAAEAMXZ ?max_size@?$vector@PEAVCommandLineFlag@absl@@V?$allocator@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ ?max_size@?$vector@PEAVCordzHandle@cord_internal@absl@@V?$allocator@PEAVCordzHandle@cord_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ ?max_size@?$vector@PEAVLogSink@absl@@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ @@ -5251,10 +5174,9 @@ EXPORTS ?parsed_conversion@UntypedFormatSpecImpl@str_format_internal@absl@@QEBAPEBVParsedFormatBase@23@XZ ?pointer_to@?$pointer_traits@PEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SAPEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@23@AEAU423@@Z ?pointer_to@?$pointer_traits@PEAU?$__hash_node_base@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@@@__Cr@std@@SAPEAU?$__hash_node_base@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@@@23@AEAU423@@Z - ?pointer_to@?$pointer_traits@PEAU?$__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@@@__Cr@std@@SAPEAU?$__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@AEAU423@@Z + ?pointer_to@?$pointer_traits@PEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@SAPEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@AEAU423@@Z ?pointer_to@?$pointer_traits@PEAU?$pair@$$CBV?$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@@@__Cr@std@@SAPEAU?$pair@$$CBV?$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@AEAU423@@Z ?pointer_to@?$pointer_traits@PEAU?$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@@@__Cr@std@@SAPEAU?$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@@23@AEAU423@@Z - ?pointer_to@?$pointer_traits@PEBU?$__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@@@__Cr@std@@SAPEBU?$__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@AEBU423@@Z ?pointer_to@?$pointer_traits@PEBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@SAPEBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@AEBU423@@Z ?poison@InlineData@cord_internal@absl@@QEAAXXZ ?poison_this@InlineData@cord_internal@absl@@QEAAXXZ @@ -5371,6 +5293,7 @@ EXPORTS ?set_cordz_mean_interval@cord_internal@absl@@YAXH@Z ?set_data@InlineRep@Cord@absl@@QEAAPEAD_K@Z ?set_data@InlineRep@Cord@absl@@QEAAXPEBD_K@Z + ?set_empty_soo@CommonFields@container_internal@absl@@QEAAXXZ ?set_end@CordRepBtree@cord_internal@absl@@AEAAX_K@Z ?set_from_arg@InputValue@UnboundConversion@str_format_internal@absl@@QEAAXH@Z ?set_full_soo@CommonFields@container_internal@absl@@QEAAXXZ @@ -5422,12 +5345,10 @@ EXPORTS ?size@?$__bucket_list_deallocator@V?$allocator@PEAU?$__hash_node_base@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@@@__Cr@std@@@__Cr@std@@QEAAAEA_KXZ ?size@?$__bucket_list_deallocator@V?$allocator@PEAU?$__hash_node_base@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@@@__Cr@std@@@__Cr@std@@QEBA_KXZ ?size@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@AEAAAEA_KXZ - ?size@?$__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@@AEAAAEA_KXZ + ?size@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AEAAAEA_KXZ ?size@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ ?size@?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ - ?size@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AEAAAEA_KXZ - ?size@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEBAAEB_KXZ - ?size@?$__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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__Cr@std@@AEAAAEA_KXZ + ?size@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEBA_KXZ ?size@?$array@Uraw_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@$0BA@@__Cr@std@@QEBA_KXZ ?size@?$deque@PEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ ?size@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ @@ -5504,8 +5425,13 @@ EXPORTS ?transfer_unprobed_elements_to_next_capacity_fn@?$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@@CAXAEAVCommonFields@23@PEBW4ctrl_t@23@PEAX2P6AX2E_K3@Z@Z ?tree@InlineRep@Cord@absl@@QEBAPEAUCordRep@cord_internal@3@XZ ?tree@Rep@InlineData@cord_internal@absl@@QEBAPEAUCordRep@34@XZ + ?try_lock@Mutex@absl@@QEAA_NXZ + ?try_lock_shared@Mutex@absl@@QEAA_NXZ ?type@ProtoField@log_internal@absl@@QEBA?AW4WireType@23@XZ ?unchecked_deref@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@@AEBAAEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@XZ + ?unlock@Mutex@absl@@QEAAXXZ + ?unlock@SpinLock@base_internal@absl@@QEAAXXZ + ?unlock_shared@Mutex@absl@@QEAAXXZ ?unpoison@InlineData@cord_internal@absl@@QEAAXXZ ?utc_time_zone@cctz@time_internal@absl@@YA?AVtime_zone@123@XZ ?value@ConvertibleToStringView@strings_internal@absl@@QEBA?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ 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 13559d2156..9f6cfd644d 100644 --- a/naiveproxy/src/third_party/abseil-cpp/symbols_arm64_rel.def +++ b/naiveproxy/src/third_party/abseil-cpp/symbols_arm64_rel.def @@ -152,19 +152,19 @@ EXPORTS ??$UnparseFloatingPointVal@N@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@N@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_impl@V?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@$$A6AXAEAVCommandLineFlag@5@@Z@__function@__Cr@std@@@?$__policy_invoker@$$A6AXAEAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@CAXPEBT__policy_storage@123@AEAVCommandLineFlag@absl@@@Z + ??$__call_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@@?$__policy_func@$$A6AXAEAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@CAXPEBT__policy_storage@123@AEAVCommandLineFlag@absl@@@Z ??$__dispatch@$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@?$__dispatcher@$00@__base@__visitation@__variant_detail@__Cr@std@@SA?A_T$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@2345@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@345@@Z ??$__dispatch@$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@?$__dispatcher@$01@__base@__visitation@__variant_detail@__Cr@std@@SA?A_T$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@2345@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@345@@Z ??$__dispatch@$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@?$__dispatcher@$02@__base@__visitation@__variant_detail@__Cr@std@@SA?A_T$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@2345@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@345@@Z ??$__dispatch@$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@?$__dispatcher@$0A@@__base@__visitation@__variant_detail@__Cr@std@@SA?A_T$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@2345@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@345@@Z ??$__do_rehash@$00@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@AEAAX_K@Z - ??$__do_rehash@$00@?$__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@@AEAAX_K@Z + ??$__do_rehash@$00@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AEAAX_K@Z ??$__emplace_back_slow_path@AEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@AEBV123@AEA_K@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAPEAUViableSubstitution@strings_internal@absl@@AEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@12@AEBV612@AEA_K@Z ??$__emplace_back_slow_path@AEBUUnrecognizedFlag@absl@@@?$vector@UUnrecognizedFlag@absl@@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@@__Cr@std@@AEAAPEAUUnrecognizedFlag@absl@@AEBU34@@Z ??$__emplace_back_slow_path@W4Source@UnrecognizedFlag@absl@@AEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$vector@UUnrecognizedFlag@absl@@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@@__Cr@std@@AEAAPEAUUnrecognizedFlag@absl@@$$QEAW4Source@34@AEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@12@@Z ??$__emplace_unique_key_args@PEBUCordRep@cord_internal@absl@@AEBQEBU123@@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAA?AU?$pair@V?$__hash_iterator@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@_N@12@AEBQEBUCordRep@cord_internal@absl@@0@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@$$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__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 ??$__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@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@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 @@ -192,7 +192,7 @@ EXPORTS ??$emplace_front@AEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@@?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@AEAV?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXAEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@@Z ??$emplace_front@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAX$$QEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@Z ??$emplace_front@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAX$$QEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@@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@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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@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@@QEAA?AViterator@012@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??$find_or_prepare_insert@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@@IEAA?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 ??$find_or_prepare_insert_large@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 @@ -255,7 +255,6 @@ EXPORTS ??0Randen@random_internal@absl@@QEAA@XZ ??0ScopedMinLogLevel@log_internal@absl@@QEAA@W4LogSeverityAtLeast@2@@Z ??0ScopedStderrThreshold@absl@@QEAA@W4LogSeverityAtLeast@1@@Z - ??0SpinLock@base_internal@absl@@QEAA@W4SchedulingMode@12@@Z ??0Status@absl@@QEAA@W4StatusCode@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??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 @@ -332,7 +331,6 @@ EXPORTS ??ACord@absl@@QEBAD_K@Z ??BCord@absl@@QEBA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@XZ ??Bint128@absl@@QEBANXZ - ??Eiterator@?$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@@QEAAAEAV0123@XZ ??Gdetail@cctz@time_internal@absl@@YA?AV?$civil_time@Uday_tag@detail@cctz@time_internal@absl@@@0123@V40123@_J@Z ??Gdetail@cctz@time_internal@absl@@YA?AV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@0123@V40123@_J@Z ??Gdetail@cctz@time_internal@absl@@YA_JV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@0123@0@Z @@ -586,7 +584,8 @@ EXPORTS ?EqualsImpl@Cord@absl@@AEBA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@_K@Z ?EquivTransitions@TimeZoneInfo@cctz@time_internal@absl@@AEBA_NEE@Z ?Erase@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAPEAUPayload@status_internal@3@PEBU453@0@Z - ?EraseMetaOnly@container_internal@absl@@YAXAEAVCommonFields@12@PEBW4ctrl_t@12@_K@Z + ?EraseMetaOnlyLarge@container_internal@absl@@YAXAEAVCommonFields@12@PEBW4ctrl_t@12@_K@Z + ?EraseMetaOnlySmall@container_internal@absl@@YAXAEAVCommonFields@12@_N_K@Z ?ErasePayload@StatusRep@status_internal@absl@@QEAA?AUEraseResult@123@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?ErrnoToStatus@absl@@YA?AVStatus@1@HV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?ErrnoToStatusCode@absl@@YA?AW4StatusCode@1@H@Z @@ -780,6 +779,7 @@ EXPORTS ?Init@FlagImpl@flags_internal@absl@@AEAAXXZ ?InitDiscreteDistribution@random_internal@absl@@YA?AV?$vector@U?$pair@N_K@__Cr@std@@V?$allocator@U?$pair@N_K@__Cr@std@@@23@@__Cr@std@@PEAV?$vector@NV?$allocator@N@__Cr@std@@@45@@Z ?InitFrom@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAXAEBV123@@Z + ?InitSigSafeArena@base_internal@absl@@YAXXZ ?InitTables@CRC32@crc_internal@absl@@UEAAXXZ ?InitTree@ChunkIterator@Cord@absl@@AEAAXPEAUCordRep@cord_internal@3@@Z ?InitWhat@BadStatusOrAccess@absl@@AEBAXXZ @@ -835,7 +835,6 @@ EXPORTS ?LocalTime@TimeZoneInfo@cctz@time_internal@absl@@AEBA?AUabsolute_lookup@time_zone@234@_JAEBUTransition@234@@Z ?LocalTime@TimeZoneInfo@cctz@time_internal@absl@@AEBA?AUabsolute_lookup@time_zone@234@_JAEBUTransitionType@234@@Z ?Lock@CordzInfo@cord_internal@absl@@QEAAXW4MethodIdentifier@CordzUpdateTracker@23@@Z - ?Lock@Mutex@absl@@QEAAXXZ ?LockSlow@Mutex@absl@@AEAAXPEBUMuHowS@2@PEBVCondition@2@H@Z ?LockSlowLoop@Mutex@absl@@AEAAXPEAUSynchWaitParams@2@H@Z ?LockSlowWithDeadline@Mutex@absl@@AEAA_NPEBUMuHowS@2@PEBVCondition@2@VKernelTimeout@synchronization_internal@2@H@Z @@ -849,6 +848,7 @@ EXPORTS ?MakeAbsNanos@KernelTimeout@synchronization_internal@absl@@QEBA_JXZ ?MakeAbsTimespec@KernelTimeout@synchronization_internal@absl@@QEBA?AUtimespec@@XZ ?MakeCheckFailString@status_internal@absl@@YAPEBDPEBVStatus@2@PEBD@Z + ?MakeCheckOpUnprintableString@log_internal@absl@@YAXAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?MakeCheckOpValueString@log_internal@absl@@YAXAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@C@Z ?MakeCheckOpValueString@log_internal@absl@@YAXAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@D@Z ?MakeCheckOpValueString@log_internal@absl@@YAXAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@E@Z @@ -984,10 +984,7 @@ EXPORTS ?ReadOneWord@FlagImpl@flags_internal@absl@@QEBA_JXZ ?ReadSeedMaterialFromOSEntropy@random_internal@absl@@YA_NV?$Span@I@2@@Z ?ReadSequenceLockedData@FlagImpl@flags_internal@absl@@AEBAXPEAX@Z - ?ReaderLock@Mutex@absl@@QEAAXXZ - ?ReaderTryLock@Mutex@absl@@QEAA_NXZ ?ReaderTryLockSlow@Mutex@absl@@AEAA_NXZ - ?ReaderUnlock@Mutex@absl@@QEAAXXZ ?Rebuild@CordRepBtree@cord_internal@absl@@CAXPEAPEAV123@PEAV123@_N@Z ?Rebuild@CordRepBtree@cord_internal@absl@@SAPEAV123@PEAV123@@Z ?RecordClearedReservationSlow@container_internal@absl@@YAXPEAUHashtablezInfo@12@@Z @@ -1089,6 +1086,7 @@ EXPORTS ?ShouldLogBacktraceAt@log_internal@absl@@YA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@H@Z ?ShouldPrependLogPrefix@absl@@YA_NXZ ?ShouldSymbolizeLogStackTrace@log_internal@absl@@YA_NXZ + ?SigSafeArena@base_internal@absl@@YAPEAUArena@LowLevelAlloc@12@XZ ?Signal@CondVar@absl@@QEAAXXZ ?SignalAll@CondVar@absl@@QEAAXXZ ?SimpleAtob@absl@@YA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEA_N@Z @@ -1208,7 +1206,6 @@ EXPORTS ?TrackCord@CordzInfo@cord_internal@absl@@SAXAEAVInlineData@23@W4MethodIdentifier@CordzUpdateTracker@23@_J@Z ?Trans@Mutex@absl@@AEAAXPEBUMuHowS@2@@Z ?Trunc@absl@@YA?AVDuration@1@V21@0@Z - ?TryLock@Mutex@absl@@QEAA_NXZ ?TryLockSlow@Mutex@absl@@AEAA_NXZ ?TryNewCRC32AcceleratedX86ARMCombined@crc_internal@absl@@YAPEAVCRCImpl@12@XZ ?TryParse@FlagImpl@flags_internal@absl@@AEBA?AV?$unique_ptr@XUDynValueDeleter@flags_internal@absl@@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@56@AEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@56@@Z @@ -1231,7 +1228,6 @@ EXPORTS ?UnimplementedError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?UnknownError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?Unlock@CordzInfo@cord_internal@absl@@QEAAXXZ - ?Unlock@Mutex@absl@@QEAAXXZ ?UnlockSlow@Mutex@absl@@AEAAXPEAUSynchWaitParams@2@@Z ?Unparse@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@F@Z ?Unparse@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@G@Z @@ -1311,7 +1307,6 @@ EXPORTS ?destroy@?$__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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__Cr@std@@AEAAXPEAV?$__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@@Z ?effective_impl@time_zone@cctz@time_internal@absl@@AEBAAEBVImpl@1234@XZ ?engines@?1??CrcAndCopy@CrcMemcpy@crc_internal@absl@@SA?AVcrc32c_t@4@PEIAXPEIBX_KV54@_N@Z@4UArchSpecificEngines@234@B - ?find_first_non_full@container_internal@absl@@YA?AUFindInfo@12@AEBVCommonFields@12@_K@Z ?fixed_time_zone@cctz@time_internal@absl@@YA?AVtime_zone@123@AEBV?$duration@_JV?$ratio@$00$00@__Cr@std@@@chrono@__Cr@std@@@Z ?format@detail@cctz@time_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBV567@AEBV?$time_point@Vsystem_clock@chrono@__Cr@std@@V?$duration@_JV?$ratio@$00$00@__Cr@std@@@234@@chrono@67@AEBV?$duration@_JV?$ratio@$00$0DINHOKEMGIAAA@@__Cr@std@@@967@AEBVtime_zone@234@@Z ?from_chars@absl@@YA?AUfrom_chars_result@1@PEBD0AEAMW4chars_format@1@@Z @@ -1321,6 +1316,8 @@ EXPORTS ?kDefaultIterControl@container_internal@absl@@3W4ctrl_t@12@A ?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 ?local_time_zone@cctz@time_internal@absl@@YA?AVtime_zone@123@XZ + ?lock@Mutex@absl@@QEAAXXZ + ?lock_shared@Mutex@absl@@QEAAXXZ ?lookup@time_zone@cctz@time_internal@absl@@QEBA?AUabsolute_lookup@1234@AEBV?$time_point@Vsystem_clock@chrono@__Cr@std@@V?$duration@_JV?$ratio@$00$00@__Cr@std@@@234@@chrono@__Cr@std@@@Z ?lookup@time_zone@cctz@time_internal@absl@@QEBA?AUcivil_lookup@1234@AEBV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@detail@234@@Z ?max@?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@detail@cctz@time_internal@absl@@SA?AV12345@XZ @@ -1360,6 +1357,10 @@ EXPORTS ?status@BadStatusOrAccess@absl@@QEBAAEBVStatus@2@XZ ?stream@OstreamView@LogMessage@log_internal@absl@@QEAAAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ ?transfer_unprobed_elements_to_next_capacity_fn@?$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@@CAXAEAVCommonFields@23@PEBW4ctrl_t@23@PEAX2P6AX2E_K3@Z@Z + ?try_lock@Mutex@absl@@QEAA_NXZ + ?try_lock_shared@Mutex@absl@@QEAA_NXZ + ?unlock@Mutex@absl@@QEAAXXZ + ?unlock_shared@Mutex@absl@@QEAAXXZ ?utc_time_zone@cctz@time_internal@absl@@YA?AVtime_zone@123@XZ ?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 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 0ecff835b5..80e31368a9 100644 --- a/naiveproxy/src/third_party/abseil-cpp/symbols_x64_dbg.def +++ b/naiveproxy/src/third_party/abseil-cpp/symbols_x64_dbg.def @@ -5,14 +5,14 @@ EXPORTS ??$?0$$CBUCordRep@cord_internal@absl@@@Hex@absl@@QEAA@PEBUCordRep@cord_internal@1@W4PadSpec@1@@Z ??$?0$$CBVFormatArgImpl@str_format_internal@absl@@$$CBV012@@?$Span@$$CBVFormatArgImpl@str_format_internal@absl@@@absl@@QEAA@V?$initializer_list@VFormatArgImpl@str_format_internal@absl@@@std@@@Z ??$?0$$CB_W$0A@@VoidPtr@str_format_internal@absl@@QEAA@PEB_W@Z - ??$?0$$QEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V$$Z$0A@$$Z$S@?$pair@$$CBV?$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@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@$$QEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@AEAV?$tuple@$$V@12@U?$__tuple_indices@$0A@@12@U?$__tuple_indices@$S@12@@Z + ??$?0$$QEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V$$Z$0A@$$Z$S@?$pair@$$CBV?$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@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@$$QEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@AEAV?$tuple@$$V@12@U?$__integer_sequence@_K$0A@@12@U?$__integer_sequence@_K$S@12@@Z ??$?0$$QEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V@?$pair@$$CBV?$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@@QEAA@Upiecewise_construct_t@12@V?$tuple@$$QEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@V?$tuple@$$V@12@@Z - ??$?0$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAV?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@U?$__tuple_indices@$0A@@12@3@Z - ??$?0$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$tuple@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@23@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAV?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@U?$__tuple_indices@$0A@@12@3@Z + ??$?0$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAV?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@U?$__integer_sequence@_K$0A@@12@3@Z + ??$?0$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$tuple@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@23@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAV?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@U?$__integer_sequence@_K$0A@@12@3@Z ??$?0$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@@?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@QEAA@Upiecewise_construct_t@12@V?$tuple@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@@Z ??$?0$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@@?$pair@V?$tuple@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@23@@__Cr@std@@QEAA@Upiecewise_construct_t@12@V?$tuple@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@@Z - ??$?0$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAV?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@U?$__tuple_indices@$0A@@12@3@Z - ??$?0$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@23@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAV?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@U?$__tuple_indices@$0A@@12@3@Z + ??$?0$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAV?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@U?$__integer_sequence@_K$0A@@12@3@Z + ??$?0$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@23@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAV?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@U?$__integer_sequence@_K$0A@@12@3@Z ??$?0$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@@?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@QEAA@Upiecewise_construct_t@12@V?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@@Z ??$?0$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QEAPEAVCommandLineFlag@absl@@@?$pair@V?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@23@@__Cr@std@@QEAA@Upiecewise_construct_t@12@V?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@12@@Z ??$?0$$T@?$Storage@PEAPEAUCordRep@cord_internal@absl@@$00U?$StorageTag@V?$allocator@PEAUCordRep@cord_internal@absl@@@__Cr@std@@PEAPEAUCordRep@cord_internal@absl@@@internal_compressed_tuple@container_internal@3@$0A@@internal_compressed_tuple@container_internal@absl@@QEAA@Uin_place_t@__Cr@std@@$$QEA$$T@Z @@ -55,10 +55,6 @@ EXPORTS ??$?0$00X@?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAA@PEAVZoneInfoSource@cctz@time_internal@absl@@@Z ??$?0$00X@?$unique_ptr@XUDynValueDeleter@flags_internal@absl@@@__Cr@std@@QEAA@$$T@Z ??$?0$00X@?$unique_ptr@XUDynValueDeleter@flags_internal@absl@@@__Cr@std@@QEAA@PEAX$$QEAUDynValueDeleter@flags_internal@absl@@@Z - ??$?0$0A@$$Z$$QEAPEAVCommandLineFlag@absl@@$$Z$S$$Z$$V$$ZPEAV01@@?$__tuple_impl@U?$__tuple_indices@$0A@@__Cr@std@@$$QEAPEAVCommandLineFlag@absl@@@__Cr@std@@QEAA@U?$__tuple_indices@$0A@@12@U?$__tuple_types@$$QEAPEAVCommandLineFlag@absl@@@12@U?$__tuple_indices@$S@12@U?$__tuple_types@$$V@12@$$QEAPEAVCommandLineFlag@absl@@@Z - ??$?0$0A@$$ZAEBQEAVCommandLineFlag@absl@@$$Z$S$$Z$$V$$ZAEBQEAV01@@?$__tuple_impl@U?$__tuple_indices@$0A@@__Cr@std@@AEBQEAVCommandLineFlag@absl@@@__Cr@std@@QEAA@U?$__tuple_indices@$0A@@12@U?$__tuple_types@AEBQEAVCommandLineFlag@absl@@@12@U?$__tuple_indices@$S@12@U?$__tuple_types@$$V@12@AEBQEAVCommandLineFlag@absl@@@Z - ??$?0$0A@$00$$ZAEAPEAVCommandLineFlag@absl@@AEA_N$$Z$S$$Z$$V$$ZAEAPEAV01@AEA_N@?$__tuple_impl@U?$__tuple_indices@$0A@$00@__Cr@std@@AEAPEAVCommandLineFlag@absl@@AEA_N@__Cr@std@@QEAA@U?$__tuple_indices@$0A@$00@12@U?$__tuple_types@AEAPEAVCommandLineFlag@absl@@AEA_N@12@U?$__tuple_indices@$S@12@U?$__tuple_types@$$V@12@AEAPEAVCommandLineFlag@absl@@AEA_N@Z - ??$?0$0A@$00$$ZPEAVCommandLineFlag@absl@@_N$$Z$S$$Z$$V$$ZAEAPEAV01@AEA_N@?$__tuple_impl@U?$__tuple_indices@$0A@$00@__Cr@std@@PEAVCommandLineFlag@absl@@_N@__Cr@std@@QEAA@U?$__tuple_indices@$0A@$00@12@U?$__tuple_types@PEAVCommandLineFlag@absl@@_N@12@U?$__tuple_indices@$S@12@U?$__tuple_types@$$V@12@AEAPEAVCommandLineFlag@absl@@AEA_N@Z ??$?0AEAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@AEAPEAPEAPEBV01234@$0A@@?$pair@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@@__Cr@std@@QEAA@AEAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@0@Z ??$?0AEAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV01234@$0A@@?$pair@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@@__Cr@std@@QEAA@AEAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@$$QEAPEAPEAPEBV34567@@Z ??$?0AEAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@AEAPEAPEAU0123@$0A@@?$pair@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU1234@@__Cr@std@@QEAA@AEAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@0@Z @@ -73,6 +69,8 @@ EXPORTS ??$?0AEAPEAVCommandLineFlag@absl@@$0A@@?$__tuple_leaf@$0A@AEAPEAVCommandLineFlag@absl@@$0A@@__Cr@std@@QEAA@AEAPEAVCommandLineFlag@absl@@@Z ??$?0AEAPEAVCommandLineFlag@absl@@$0A@@?$__tuple_leaf@$0A@PEAVCommandLineFlag@absl@@$0A@@__Cr@std@@QEAA@AEAPEAVCommandLineFlag@absl@@@Z ??$?0AEAPEAVCommandLineFlag@absl@@AEA_N$0A@@?$tuple@PEAVCommandLineFlag@absl@@_N@__Cr@std@@QEAA@AEAPEAVCommandLineFlag@absl@@AEA_N@Z + ??$?0AEAPEAVCommandLineFlag@absl@@AEA_N@?$__tuple_impl@U?$__integer_sequence@_K$0A@$00@__Cr@std@@AEAPEAVCommandLineFlag@absl@@AEA_N@__Cr@std@@QEAA@U__forward_args@12@AEAPEAVCommandLineFlag@absl@@AEA_N@Z + ??$?0AEAPEAVCommandLineFlag@absl@@AEA_N@?$__tuple_impl@U?$__integer_sequence@_K$0A@$00@__Cr@std@@PEAVCommandLineFlag@absl@@_N@__Cr@std@@QEAA@U__forward_args@12@AEAPEAVCommandLineFlag@absl@@AEA_N@Z ??$?0AEAPEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEAU0123@$0A@@?$pair@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@@__Cr@std@@QEAA@AEAPEBUPrefixCrc@CrcCordState@crc_internal@absl@@$$QEAPEAU3456@@Z ??$?0AEAUraw_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@@AEBV234@@Z@@?$__temp_value@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@@QEAA@AEAV?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAUraw_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@@12@AEBV678@@Z@@Z ??$?0AEAV?$__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@@12@$0A@@?$pair@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@@__Cr@std@@QEAA@AEAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@12@$$QEAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@12@@Z @@ -93,6 +91,7 @@ EXPORTS ??$?0AEA_KAEBV?$allocator@D@__Cr@std@@$00@?$CompressedTuple@_KV?$allocator@D@__Cr@std@@@container_internal@absl@@QEAA@AEA_KAEBV?$allocator@D@__Cr@std@@@Z ??$?0AEA_KAEBV?$allocator@D@__Cr@std@@@?$CompressedTupleImpl@V?$CompressedTuple@_KV?$allocator@D@__Cr@std@@@container_internal@absl@@U?$integer_sequence@_K$0A@$00@__Cr@std@@$00@internal_compressed_tuple@container_internal@absl@@QEAA@Uin_place_t@__Cr@std@@AEA_KAEBV?$allocator@D@56@@Z ??$?0AEBQEAVCommandLineFlag@absl@@$0A@@?$__tuple_leaf@$0A@AEBQEAVCommandLineFlag@absl@@$0A@@__Cr@std@@QEAA@AEBQEAVCommandLineFlag@absl@@@Z + ??$?0AEBQEAVCommandLineFlag@absl@@@?$__tuple_impl@U?$__integer_sequence@_K$0A@@__Cr@std@@AEBQEAVCommandLineFlag@absl@@@__Cr@std@@QEAA@U__forward_args@12@AEBQEAVCommandLineFlag@absl@@@Z ??$?0AEBV?$allocator@D@__Cr@std@@@?$Storage@V?$allocator@D@__Cr@std@@$00U?$StorageTag@_KV?$allocator@D@__Cr@std@@@internal_compressed_tuple@container_internal@absl@@$00@internal_compressed_tuple@container_internal@absl@@QEAA@Uin_place_t@__Cr@std@@AEBV?$allocator@D@56@@Z ??$?0AEBV?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@?$Storage@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@$0A@U?$StorageTag@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@_K@internal_compressed_tuple@container_internal@absl@@$00@internal_compressed_tuple@container_internal@absl@@QEAA@Uin_place_t@__Cr@std@@AEBV?$allocator@UPayload@status_internal@absl@@@56@@Z ??$?0AEBV?$allocator@UPayload@status_internal@absl@@@__Cr@std@@I$00@?$CompressedTuple@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@_K@container_internal@absl@@QEAA@AEBV?$allocator@UPayload@status_internal@absl@@@__Cr@std@@$$QEAI@Z @@ -100,11 +99,11 @@ EXPORTS ??$?0AEBV?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@@?$Storage@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@$0A@U?$StorageTag@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@_K@internal_compressed_tuple@container_internal@absl@@$00@internal_compressed_tuple@container_internal@absl@@QEAA@Uin_place_t@__Cr@std@@AEBV?$allocator@VFormatArgImpl@str_format_internal@absl@@@56@@Z ??$?0AEBV?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@I$00@?$CompressedTuple@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@_K@container_internal@absl@@QEAA@AEBV?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@$$QEAI@Z ??$?0AEBV?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@I@?$CompressedTupleImpl@V?$CompressedTuple@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@_K@container_internal@absl@@U?$integer_sequence@_K$0A@$00@__Cr@std@@$00@internal_compressed_tuple@container_internal@absl@@QEAA@Uin_place_t@__Cr@std@@AEBV?$allocator@VFormatArgImpl@str_format_internal@absl@@@56@$$QEAI@Z - ??$?0AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V$$Z$0A@$$Z$S@?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@AEAV?$tuple@$$V@12@U?$__tuple_indices@$0A@@12@U?$__tuple_indices@$S@12@@Z - ??$?0AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V$$Z$0A@$$Z$S@?$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@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@AEAV?$tuple@$$V@12@U?$__tuple_indices@$0A@@12@U?$__tuple_indices@$S@12@@Z + ??$?0AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V$$Z$0A@$$Z$S@?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@AEAV?$tuple@$$V@12@U?$__integer_sequence@_K$0A@@12@U?$__integer_sequence@_K$S@12@@Z + ??$?0AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V$$Z$0A@$$Z$S@?$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@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@AEAV?$tuple@$$V@12@U?$__integer_sequence@_K$0A@@12@U?$__integer_sequence@_K$S@12@@Z ??$?0AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V@?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@QEAA@Upiecewise_construct_t@12@V?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@V?$tuple@$$V@12@@Z ??$?0AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V@?$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@@QEAA@Upiecewise_construct_t@12@V?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@V?$tuple@$$V@12@@Z - ??$?0AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$ZAEBQEAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$tuple@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@AEBQEAVCommandLineFlag@absl@@@23@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAV?$tuple@AEBQEAVCommandLineFlag@absl@@@12@U?$__tuple_indices@$0A@@12@3@Z + ??$?0AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$ZAEBQEAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$tuple@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@AEBQEAVCommandLineFlag@absl@@@23@@__Cr@std@@AEAA@Upiecewise_construct_t@12@AEAV?$tuple@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AEAV?$tuple@AEBQEAVCommandLineFlag@absl@@@12@U?$__integer_sequence@_K$0A@@12@3@Z ??$?0AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$ZAEBQEAVCommandLineFlag@absl@@@?$pair@V?$tuple@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@AEBQEAVCommandLineFlag@absl@@@23@@__Cr@std@@QEAA@Upiecewise_construct_t@12@V?$tuple@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$tuple@AEBQEAVCommandLineFlag@absl@@@12@@Z ??$?0D@?$allocator@U?$AlignedType@$07@container_internal@absl@@@__Cr@std@@QEAA@AEBV?$allocator@D@12@@Z ??$?0D@?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@QEAA@AEBV?$allocator@D@12@@Z @@ -130,6 +129,7 @@ EXPORTS ??$?0PEAUraw_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@@AEBV234@@Z@PEAU0?1???R1234@QEBA?AV567@0@Z@$0A@@?$pair@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@PEAU1?1???R2345@QEBA?AV678@0@Z@@__Cr@std@@QEAA@$$QEAPEAUraw_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@@12@AEBV567@@Z@1@Z ??$?0PEAVCommandLineFlag@absl@@$0A@@?$__tuple_leaf@$0A@$$QEAPEAVCommandLineFlag@absl@@$0A@@__Cr@std@@QEAA@$$QEAPEAVCommandLineFlag@absl@@@Z ??$?0PEAVCommandLineFlag@absl@@$0A@@?$tuple@$$QEAPEAVCommandLineFlag@absl@@@__Cr@std@@QEAA@$$QEAPEAVCommandLineFlag@absl@@@Z + ??$?0PEAVCommandLineFlag@absl@@@?$__tuple_impl@U?$__integer_sequence@_K$0A@@__Cr@std@@$$QEAPEAVCommandLineFlag@absl@@@__Cr@std@@QEAA@U__forward_args@12@$$QEAPEAVCommandLineFlag@absl@@@Z ??$?0PEAW4ctrl_t@container_internal@absl@@AEAPEAX$0A@@?$pair@PEAW4ctrl_t@container_internal@absl@@PEAX@__Cr@std@@QEAA@$$QEAPEAW4ctrl_t@container_internal@absl@@AEAPEAX@Z ??$?0PEAW4ctrl_t@container_internal@absl@@AEBQEAX$0A@@?$pair@PEAW4ctrl_t@container_internal@absl@@PEAX@__Cr@std@@QEAA@$$QEAPEAW4ctrl_t@container_internal@absl@@AEBQEAX@Z ??$?0PEAW4ctrl_t@container_internal@absl@@PEAX$0A@@?$pair@PEAW4ctrl_t@container_internal@absl@@PEAX@__Cr@std@@QEAA@$$QEAPEAW4ctrl_t@container_internal@absl@@$$QEAPEAX@Z @@ -190,9 +190,7 @@ EXPORTS ??$?0V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@X@?$function@$$A6AXAEAVCommandLineFlag@absl@@@Z@__Cr@std@@QEAA@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@@Z ??$?0V?$InlinedVector@VFormatArgImpl@str_format_internal@absl@@$03V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@@absl@@XV01@H@?$Span@$$CBVFormatArgImpl@str_format_internal@absl@@@absl@@QEAA@AEBV?$InlinedVector@VFormatArgImpl@str_format_internal@absl@@$03V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@@1@@Z ??$?0V?$Span@D@absl@@XV01@$0A@@?$Span@$$CBD@absl@@QEAA@AEBV?$Span@D@1@@Z - ??$?0V?$Span@D@absl@@XV01@$0A@@?$Span@D@absl@@QEAA@AEAV01@@Z ??$?0V?$Span@I@absl@@XV01@$0A@@?$Span@$$CBI@absl@@QEAA@AEBV?$Span@I@1@@Z - ??$?0V?$Span@I@absl@@XV01@$0A@@?$Span@I@absl@@QEAA@AEAV01@@Z ??$?0V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V012@$0A@@?$pair@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V123@@__Cr@std@@QEAA@$$QEAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@12@0@Z ??$?0V?$__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@@12@$0A@@?$pair@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@@__Cr@std@@QEAA@$$QEAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@12@$$QEAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@12@@Z ??$?0V?$__hash_iterator@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@AEA_N$0A@@?$pair@V?$__hash_iterator@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@_N@__Cr@std@@QEAA@$$QEAV?$__hash_iterator@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@12@AEA_N@Z @@ -539,8 +537,6 @@ EXPORTS ??$GetData@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@span_internal@absl@@YAPEBDAEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??$GetData@U?$array@D$0DKJI@@__Cr@std@@@span_internal@absl@@YAPEADAEAU?$array@D$0DKJI@@__Cr@std@@@Z ??$GetData@V?$InlinedVector@PEAVLogSink@absl@@$0BA@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@absl@@@span_internal@absl@@YAPEAPEAVLogSink@1@AEAV?$InlinedVector@PEAVLogSink@absl@@$0BA@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@1@@Z - ??$GetData@V?$Span@D@absl@@@span_internal@absl@@YAPEADAEAV?$Span@D@1@@Z - ??$GetData@V?$Span@I@absl@@@span_internal@absl@@YAPEAIAEAV?$Span@I@1@@Z ??$GetData@V?$vector@PEAVLogSink@absl@@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@__Cr@std@@@span_internal@absl@@YAPEAPEAVLogSink@1@AEAV?$vector@PEAVLogSink@absl@@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@__Cr@std@@@Z ??$GetDataImpl@$$CBV?$InlinedVector@VFormatArgImpl@str_format_internal@absl@@$03V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@@absl@@@span_internal@absl@@YAPEBVFormatArgImpl@str_format_internal@1@AEBV?$InlinedVector@VFormatArgImpl@str_format_internal@absl@@$03V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@@1@D@Z ??$GetDataImpl@$$CBV?$Span@D@absl@@@span_internal@absl@@YAPEADAEBV?$Span@D@1@D@Z @@ -548,8 +544,6 @@ EXPORTS ??$GetDataImpl@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@span_internal@absl@@YAPEBDAEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@D@Z ??$GetDataImpl@U?$array@D$0DKJI@@__Cr@std@@@span_internal@absl@@YAPEADAEAU?$array@D$0DKJI@@__Cr@std@@D@Z ??$GetDataImpl@V?$InlinedVector@PEAVLogSink@absl@@$0BA@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@absl@@@span_internal@absl@@YAPEAPEAVLogSink@1@AEAV?$InlinedVector@PEAVLogSink@absl@@$0BA@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@1@D@Z - ??$GetDataImpl@V?$Span@D@absl@@@span_internal@absl@@YAPEADAEAV?$Span@D@1@D@Z - ??$GetDataImpl@V?$Span@I@absl@@@span_internal@absl@@YAPEAIAEAV?$Span@I@1@D@Z ??$GetDataImpl@V?$vector@PEAVLogSink@absl@@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@__Cr@std@@@span_internal@absl@@YAPEAPEAVLogSink@1@AEAV?$vector@PEAVLogSink@absl@@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@__Cr@std@@D@Z ??$GetFlag@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@@@absl@@YA?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@@AEBV?$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@0@@Z ??$GrowSooTableToNextCapacityAndPrepareInsert@$00$00@container_internal@absl@@YA_KAEAVCommonFields@01@AEBUPolicyFunctions@01@V?$FunctionRef@$$A6A_K_K@Z@1@_N@Z @@ -846,8 +840,8 @@ EXPORTS ??$__at@P6A_K$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@Z$03$$V@__base@__visitation@__variant_detail@__Cr@std@@CA$$QEA_PAEBU?$__farray@P6A_K$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@Z$03@34@_K@Z ??$__at@P6A_K$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@Z@__base@__visitation@__variant_detail@__Cr@std@@CAAEBQ6A_K$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@1234@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@234@@ZAEBQ6A_K01@Z@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 - ??$__call_impl@V?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@$$A6AXAEAVCommandLineFlag@5@@Z@__function@__Cr@std@@@?$__policy_invoker@$$A6AXAEAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@CAXPEBT__policy_storage@123@AEAVCommandLineFlag@absl@@@Z - ??$__choose_policy@V?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@$$A6AXAEAVCommandLineFlag@5@@Z@__function@__Cr@std@@@__policy@__function@__Cr@std@@CAPEBU0123@U?$integral_constant@_N$00@23@@Z + ??$__call_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@@?$__policy_func@$$A6AXAEAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@CAXPEBT__policy_storage@123@AEAVCommandLineFlag@absl@@@Z + ??$__choose_policy@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@@__policy@__function@__Cr@std@@CAPEBU0123@U?$integral_constant@_N$00@23@@Z ??$__constexpr_memmove@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEBV12345@@__Cr@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@0W4__element_count@01@@Z ??$__constexpr_memmove@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@@__Cr@std@@YAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU2345@0W4__element_count@01@@Z ??$__constexpr_memmove@PEAVLogSink@absl@@PEAV12@@__Cr@std@@YAPEAPEAVLogSink@absl@@PEAPEAV23@0W4__element_count@01@@Z @@ -907,7 +901,7 @@ EXPORTS ??$__construct_node@AEBUpiecewise_construct_t@__Cr@std@@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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AEAA?AV?$unique_ptr@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@@V?$__tree_node_destructor@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@@@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 ??$__construct_node@AEBUpiecewise_construct_t@__Cr@std@@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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__Cr@std@@AEAA?AV?$unique_ptr@V?$__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@__Cr@std@@V?$__tree_node_destructor@V?$allocator@V?$__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@__Cr@std@@@__Cr@std@@@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 ??$__construct_node_hash@AEBQEBUCordRep@cord_internal@absl@@$$V@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@AEAA?AV?$unique_ptr@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@23@@12@_KAEBQEBUCordRep@cord_internal@absl@@@Z - ??$__construct_node_hash@AEBUpiecewise_construct_t@__Cr@std@@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@@AEAA?AV?$unique_ptr@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@@V?$__hash_node_destructor@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@@@23@@12@_KAEBUpiecewise_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 + ??$__construct_node_hash@AEBUpiecewise_construct_t@__Cr@std@@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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AEAA?AV?$unique_ptr@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@@V?$__hash_node_destructor@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@@@23@@12@_KAEBUpiecewise_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 ??$__copy@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@PEAU1234@@__Cr@std@@YA?AU?$pair@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@@01@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@0PEAU3456@@Z ??$__copy@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@@__Cr@std@@YA?AU?$pair@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@@01@PEBUPrefixCrc@CrcCordState@crc_internal@absl@@0V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@01@@Z ??$__copy@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V123@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@__Cr@std@@YA?AU?$pair@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@@01@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@01@0V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@01@@Z @@ -933,14 +927,15 @@ EXPORTS ??$__copy_trivial_impl@PEAVLogSink@absl@@PEAV12@@__Cr@std@@YA?AU?$pair@PEAPEAVLogSink@absl@@PEAPEAV12@@01@PEAPEAVLogSink@absl@@00@Z ??$__copy_trivial_impl@UTransition@cctz@time_internal@absl@@U1234@@__Cr@std@@YA?AU?$pair@PEAUTransition@cctz@time_internal@absl@@PEAU1234@@01@PEAUTransition@cctz@time_internal@absl@@00@Z ??$__copy_trivial_impl@UTransitionType@cctz@time_internal@absl@@U1234@@__Cr@std@@YA?AU?$pair@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@01@PEAUTransitionType@cctz@time_internal@absl@@00@Z - ??$__create@V?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@$$A6AXAEAVCommandLineFlag@5@@Z@__function@__Cr@std@@@?$__policy_invoker@$$A6AXAEAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@SA?AU0123@XZ - ??$__create@V?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@$$A6AXAEAVCommandLineFlag@5@@Z@__function@__Cr@std@@@__policy@__function@__Cr@std@@SAPEBU0123@XZ + ??$__create@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@@__policy@__function@__Cr@std@@SAPEBU0123@XZ + ??$__cxx_atomic_compare_exchange_strong@PEAUArena@LowLevelAlloc@base_internal@absl@@@__Cr@std@@YA_NPEAU?$__cxx_atomic_base_impl@PEAUArena@LowLevelAlloc@base_internal@absl@@@01@PEAPEAUArena@LowLevelAlloc@base_internal@absl@@PEAU3456@W4memory_order@01@3@Z ??$__cxx_atomic_compare_exchange_strong@PEAVTimeZone@absl@@@__Cr@std@@YA_NPEAU?$__cxx_atomic_base_impl@PEAVTimeZone@absl@@@01@PEAPEAVTimeZone@absl@@PEAV34@W4memory_order@01@3@Z ??$__cxx_atomic_compare_exchange_strong@PEAVVLogSite@log_internal@absl@@@__Cr@std@@YA_NPEAU?$__cxx_atomic_base_impl@PEAVVLogSite@log_internal@absl@@@01@PEAPEAVVLogSite@log_internal@absl@@PEAV345@W4memory_order@01@3@Z ??$__cxx_atomic_compare_exchange_weak@PEAUHashtablezInfo@container_internal@absl@@@__Cr@std@@YA_NPEAU?$__cxx_atomic_base_impl@PEAUHashtablezInfo@container_internal@absl@@@01@PEAPEAUHashtablezInfo@container_internal@absl@@PEAU345@W4memory_order@01@3@Z ??$__cxx_atomic_compare_exchange_weak@PEAVVLogSite@log_internal@absl@@@__Cr@std@@YA_NPEAU?$__cxx_atomic_base_impl@PEAVVLogSite@log_internal@absl@@@01@PEAPEAVVLogSite@log_internal@absl@@PEAV345@W4memory_order@01@3@Z ??$__cxx_atomic_exchange@PEAVVLogSite@log_internal@absl@@@__Cr@std@@YAPEAVVLogSite@log_internal@absl@@PEAU?$__cxx_atomic_base_impl@PEAVVLogSite@log_internal@absl@@@01@PEAV234@W4memory_order@01@@Z ??$__cxx_atomic_load@P6AXAEBUHashtablezInfo@container_internal@absl@@@Z@__Cr@std@@YAP6AXAEBUHashtablezInfo@container_internal@absl@@@ZPEBU?$__cxx_atomic_base_impl@P6AXAEBUHashtablezInfo@container_internal@absl@@@Z@01@W4memory_order@01@@Z + ??$__cxx_atomic_load@PEAUArena@LowLevelAlloc@base_internal@absl@@@__Cr@std@@YAPEAUArena@LowLevelAlloc@base_internal@absl@@PEBU?$__cxx_atomic_base_impl@PEAUArena@LowLevelAlloc@base_internal@absl@@@01@W4memory_order@01@@Z ??$__cxx_atomic_load@PEAUHashtablezInfo@container_internal@absl@@@__Cr@std@@YAPEAUHashtablezInfo@container_internal@absl@@PEBU?$__cxx_atomic_base_impl@PEAUHashtablezInfo@container_internal@absl@@@01@W4memory_order@01@@Z ??$__cxx_atomic_load@PEAVCordzHandle@cord_internal@absl@@@__Cr@std@@YAPEAVCordzHandle@cord_internal@absl@@PEBU?$__cxx_atomic_base_impl@PEAVCordzHandle@cord_internal@absl@@@01@W4memory_order@01@@Z ??$__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 @@ -997,7 +992,7 @@ EXPORTS ??$__distance@V?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YA_JV?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@01@0Urandom_access_iterator_tag@01@@Z ??$__distance@V?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YA_JV?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@0Urandom_access_iterator_tag@01@@Z ??$__do_rehash@$00@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@AEAAX_K@Z - ??$__do_rehash@$00@?$__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@@AEAAX_K@Z + ??$__do_rehash@$00@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AEAAX_K@Z ??$__emplace_back_assume_capacity@$$V@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXXZ ??$__emplace_back_assume_capacity@$$V@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXXZ ??$__emplace_back_assume_capacity@AEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@AEBV123@AEA_K@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXAEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@12@AEBV312@AEA_K@Z @@ -1024,9 +1019,11 @@ EXPORTS ??$__emplace_back_slow_path@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@?$vector@UConversionItem@ParsedFormatBase@str_format_internal@absl@@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAPEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@$$QEAU3456@@Z ??$__emplace_back_slow_path@V?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@@?$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@@AEAAPEAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@12@$$QEAV312@@Z ??$__emplace_back_slow_path@W4Source@UnrecognizedFlag@absl@@AEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$vector@UUnrecognizedFlag@absl@@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@@__Cr@std@@AEAAPEAUUnrecognizedFlag@absl@@$$QEAW4Source@34@AEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@12@@Z + ??$__emplace_unique@AEBQEBUCordRep@cord_internal@absl@@@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAA?AU?$pair@V?$__hash_iterator@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@_N@12@AEBQEBUCordRep@cord_internal@absl@@@Z + ??$__emplace_unique_extract_key@AEBQEBUCordRep@cord_internal@absl@@@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAA?AU?$pair@V?$__hash_iterator@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@_N@12@AEBQEBUCordRep@cord_internal@absl@@U__extract_key_self_tag@12@@Z ??$__emplace_unique_key_args@PEBUCordRep@cord_internal@absl@@AEBQEBU123@@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAA?AU?$pair@V?$__hash_iterator@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@_N@12@AEBQEBUCordRep@cord_internal@absl@@0@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@$$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEAAAEAPEAV?$__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 @@ -1068,13 +1065,6 @@ EXPORTS ??$__invoke_r@XAEAV@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@AEAVCommandLineFlag@5@@__Cr@std@@YAXAEAV@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@AEAVCommandLineFlag@6@@Z ??$__iter_move@AEAPEAPEAVCommandLineFlag@absl@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QEAPEAVCommandLineFlag@absl@@AEAPEAPEAV34@@Z ??$__iter_move@AEAPEAPEBVCommandLineFlag@absl@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QEAPEBVCommandLineFlag@absl@@AEAPEAPEBV34@@Z - ??$__launder@$$CBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YAPEBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@01@PEBU201@@Z - ??$__launder@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YAPEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@01@PEAU201@@Z - ??$__launder@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@YAPEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@01@PEAU201@@Z - ??$__launder@URefcountedRep@CrcCordState@crc_internal@absl@@@__Cr@std@@YAPEAURefcountedRep@CrcCordState@crc_internal@absl@@PEAU2345@@Z - ??$__launder@V?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@absl@@@__Cr@std@@YAPEAV?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@absl@@PEAV234@@Z - ??$__launder@VFlagRegistry@flags_internal@absl@@@__Cr@std@@YAPEAVFlagRegistry@flags_internal@absl@@PEAV234@@Z - ??$__launder@VMutex@absl@@@__Cr@std@@YAPEAVMutex@absl@@PEAV23@@Z ??$__libcpp_allocate@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@W4__element_count@01@_K@Z ??$__libcpp_allocate@PEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@YAPEAPEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@01@W4__element_count@01@_K@Z ??$__libcpp_allocate@PEAU?$__hash_node_base@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@@@__Cr@std@@YAPEAPEAU?$__hash_node_base@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@@@01@W4__element_count@01@_K@Z @@ -1127,63 +1117,11 @@ EXPORTS ??$__libcpp_deallocate@V?$__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@__Cr@std@@@__Cr@std@@YAXPEAV?$__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@01@W4__element_count@01@_K@Z ??$__libcpp_deallocate@V?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@@__Cr@std@@YAXPEAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@01@W4__element_count@01@_K@Z ??$__libcpp_deallocate@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@YAXPEAVFormatArgImpl@str_format_internal@absl@@W4__element_count@01@_K@Z - ??$__libcpp_operator_delete@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@YAXPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAPEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@YAXPEAPEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@01@@Z - ??$__libcpp_operator_delete@PEAPEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@W4align_val_t@3@@__Cr@std@@YAXPEAPEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@01@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAPEAU?$__hash_node_base@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@@@__Cr@std@@YAXPEAPEAU?$__hash_node_base@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@@@01@@Z - ??$__libcpp_operator_delete@PEAPEAU?$__hash_node_base@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@@W4align_val_t@3@@__Cr@std@@YAXPEAPEAU?$__hash_node_base@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@@@01@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAPEAUCordRep@cord_internal@absl@@@__Cr@std@@YAXPEAPEAUCordRep@cord_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAPEAUCordRep@cord_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAPEAUCordRep@cord_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@YAXPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAPEAVCommandLineFlag@absl@@@__Cr@std@@YAXPEAPEAVCommandLineFlag@absl@@@Z - ??$__libcpp_operator_delete@PEAPEAVCommandLineFlag@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAPEAVCommandLineFlag@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@YAXPEAPEAVCordzHandle@cord_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAPEAVCordzHandle@cord_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAPEAVCordzHandle@cord_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAPEAVLogSink@absl@@@__Cr@std@@YAXPEAPEAVLogSink@absl@@@Z - ??$__libcpp_operator_delete@PEAPEAVLogSink@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAPEAVLogSink@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAPEBVCommandLineFlag@absl@@@__Cr@std@@YAXPEAPEBVCommandLineFlag@absl@@@Z - ??$__libcpp_operator_delete@PEAPEBVCommandLineFlag@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAPEBVCommandLineFlag@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAPEBVCordzHandle@cord_internal@absl@@@__Cr@std@@YAXPEAPEBVCordzHandle@cord_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAPEBVCordzHandle@cord_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAPEBVCordzHandle@cord_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@YAXPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAPEBVImpl@time_zone@cctz@time_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAU?$AlignedType@$07@container_internal@absl@@@__Cr@std@@YAXPEAU?$AlignedType@$07@container_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAU?$AlignedType@$07@container_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAU?$AlignedType@$07@container_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@YAXPEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@01@@Z - ??$__libcpp_operator_delete@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@W4align_val_t@3@@__Cr@std@@YAXPEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@01@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@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@@YAXPEAU?$__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@01@@Z - ??$__libcpp_operator_delete@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@@W4align_val_t@3@@__Cr@std@@YAXPEAU?$__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@01@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@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@23@PEBXPEAX2@Z@@__Cr@std@@YAXPEAUAlignedSpace@?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@34@PEBXPEAX2@Z@@Z - ??$__libcpp_operator_delete@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@23@PEBXPEAX2@Z@W4align_val_t@std@@@__Cr@std@@YAXPEAUAlignedSpace@?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@34@PEBXPEAX2@Z@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@YAXPEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAUPayload@status_internal@absl@@@__Cr@std@@YAXPEAUPayload@status_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAUPayload@status_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAUPayload@status_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@YAXPEAUPrefixCrc@CrcCordState@crc_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAUPrefixCrc@CrcCordState@crc_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@YAXPEAUTransition@cctz@time_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAUTransition@cctz@time_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAUTransition@cctz@time_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@YAXPEAUTransitionType@cctz@time_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAUTransitionType@cctz@time_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAUTransitionType@cctz@time_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAUUnrecognizedFlag@absl@@@__Cr@std@@YAXPEAUUnrecognizedFlag@absl@@@Z - ??$__libcpp_operator_delete@PEAUUnrecognizedFlag@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAUUnrecognizedFlag@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAUViableSubstitution@strings_internal@absl@@@__Cr@std@@YAXPEAUViableSubstitution@strings_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAUViableSubstitution@strings_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAUViableSubstitution@strings_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@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@__Cr@std@@@__Cr@std@@YAXPEAV?$__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@01@@Z - ??$__libcpp_operator_delete@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@__Cr@std@@W4align_val_t@3@@__Cr@std@@YAXPEAV?$__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@01@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@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@__Cr@std@@@__Cr@std@@YAXPEAV?$__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@01@@Z - ??$__libcpp_operator_delete@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@__Cr@std@@W4align_val_t@3@@__Cr@std@@YAXPEAV?$__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@01@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@@__Cr@std@@YAXPEAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@01@@Z - ??$__libcpp_operator_delete@PEAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@W4align_val_t@3@@__Cr@std@@YAXPEAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@01@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PEAVFormatArgImpl@str_format_internal@absl@@@__Cr@std@@YAXPEAVFormatArgImpl@str_format_internal@absl@@@Z - ??$__libcpp_operator_delete@PEAVFormatArgImpl@str_format_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPEAVFormatArgImpl@str_format_internal@absl@@W4align_val_t@1@@Z ??$__lower_bound@U_ClassicAlgPolicy@__Cr@std@@PEBUTransition@cctz@time_internal@absl@@PEBU4567@U4567@U__identity@23@UByUnixTime@4567@@__Cr@std@@YAPEBUTransition@cctz@time_internal@absl@@PEBU2345@0AEBU2345@AEAUByUnixTime@2345@AEAU__identity@01@@Z ??$__lower_bound_bisecting@U_ClassicAlgPolicy@__Cr@std@@PEBUTransition@cctz@time_internal@absl@@U4567@U__identity@23@UByUnixTime@4567@@__Cr@std@@YAPEBUTransition@cctz@time_internal@absl@@PEBU2345@AEBU2345@_JAEAUByUnixTime@2345@AEAU__identity@01@@Z ??$__make_exception_guard@V?$_AllocatorDestroyRangeReverse@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@PEAUUnrecognizedFlag@absl@@@__Cr@std@@@__Cr@std@@YA?AU?$__exception_guard_noexceptions@V?$_AllocatorDestroyRangeReverse@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@PEAUUnrecognizedFlag@absl@@@__Cr@std@@@01@V?$_AllocatorDestroyRangeReverse@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@PEAUUnrecognizedFlag@absl@@@01@@Z ??$__make_value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@CA?A_P$$QEAUBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@78@@Z@@Z - ??$__memberwise_forward_assign@V?$tuple@AEAPEAVCommandLineFlag@absl@@AEA_N@__Cr@std@@V?$tuple@PEAVCommandLineFlag@absl@@_N@23@PEAVCommandLineFlag@absl@@_N$$Z$0A@$00@__Cr@std@@YAXAEAV?$tuple@AEAPEAVCommandLineFlag@absl@@AEA_N@01@$$QEAV?$tuple@PEAVCommandLineFlag@absl@@_N@01@U?$__tuple_types@PEAVCommandLineFlag@absl@@_N@01@U?$__tuple_indices@$0A@$00@01@@Z + ??$__memberwise_forward_assign@V?$tuple@AEAPEAVCommandLineFlag@absl@@AEA_N@__Cr@std@@V?$tuple@PEAVCommandLineFlag@absl@@_N@23@PEAVCommandLineFlag@absl@@_N$$Z$0A@$00@__Cr@std@@YAXAEAV?$tuple@AEAPEAVCommandLineFlag@absl@@AEA_N@01@$$QEAV?$tuple@PEAVCommandLineFlag@absl@@_N@01@U?$__tuple_types@PEAVCommandLineFlag@absl@@_N@01@U?$__integer_sequence@_K$0A@$00@01@@Z ??$__move@U_ClassicAlgPolicy@__Cr@std@@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV45678@PEAPEAPEBV45678@@__Cr@std@@YA?AU?$pair@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@@01@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@00@Z ??$__move@U_ClassicAlgPolicy@__Cr@std@@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU4567@PEAPEAU4567@@__Cr@std@@YA?AU?$pair@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU1234@@01@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@00@Z ??$__move@U_ClassicAlgPolicy@__Cr@std@@PEAPEAVLogSink@absl@@PEAPEAV45@PEAPEAV45@@__Cr@std@@YA?AU?$pair@PEAPEAVLogSink@absl@@PEAPEAV12@@01@PEAPEAVLogSink@absl@@00@Z @@ -1195,7 +1133,7 @@ EXPORTS ??$__move_backward@U_ClassicAlgPolicy@__Cr@std@@PEAUTransitionType@cctz@time_internal@absl@@PEAU4567@PEAU4567@@__Cr@std@@YA?AU?$pair@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@01@PEAUTransitionType@cctz@time_internal@absl@@00@Z ??$__not_null@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@@__function@__Cr@std@@YA_NAEBV@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@@Z ??$__rehash@$00@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@AEAAX_K@Z - ??$__rehash@$00@?$__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@@AEAAX_K@Z + ??$__rehash@$00@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AEAAX_K@Z ??$__rewrap_iter@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@U?$__unwrap_iter_impl@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@$00@__Cr@std@@@__Cr@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@0@Z ??$__rewrap_iter@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU1234@U?$__unwrap_iter_impl@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@$00@__Cr@std@@@__Cr@std@@YAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU2345@0@Z ??$__rewrap_iter@PEAPEAVLogSink@absl@@PEAPEAV12@U?$__unwrap_iter_impl@PEAPEAVLogSink@absl@@$00@__Cr@std@@@__Cr@std@@YAPEAPEAVLogSink@absl@@PEAPEAV23@0@Z @@ -1481,7 +1419,7 @@ EXPORTS ??$end@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 ??$end@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 ??$find@V?$__wrap_iter@PEAPEAVLogSink@absl@@@__Cr@std@@PEAVLogSink@absl@@@__Cr@std@@YA?AV?$__wrap_iter@PEAPEAVLogSink@absl@@@01@V201@0AEBQEAVLogSink@absl@@@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@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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@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@@QEAA?AViterator@012@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??$find@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@@QEBA?AVconst_iterator@012@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??$find_large@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?AViterator@012@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@_K@Z @@ -1549,8 +1487,6 @@ EXPORTS ??$iter_swap@PEAPEAVCommandLineFlag@absl@@PEAPEAV12@@__Cr@std@@YAXPEAPEAVCommandLineFlag@absl@@0@Z ??$iter_swap@PEAPEBVCommandLineFlag@absl@@PEAPEBV12@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAX$$QEAPEAPEBVCommandLineFlag@absl@@0@Z ??$iter_swap@PEAPEBVCommandLineFlag@absl@@PEAPEBV12@@__Cr@std@@YAXPEAPEBVCommandLineFlag@absl@@0@Z - ??$launder@$$CBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YAPEBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@01@PEBU201@@Z - ??$launder@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YAPEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@01@PEAU201@@Z ??$launder@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@YAPEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@01@PEAU201@@Z ??$launder@URefcountedRep@CrcCordState@crc_internal@absl@@@__Cr@std@@YAPEAURefcountedRep@CrcCordState@crc_internal@absl@@PEAU2345@@Z ??$launder@V?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@absl@@@__Cr@std@@YAPEAV?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@absl@@PEAV234@@Z @@ -1741,7 +1677,6 @@ EXPORTS ??0?$__cxx_atomic_impl@PEAUHashtablezInfo@container_internal@absl@@U?$__cxx_atomic_base_impl@PEAUHashtablezInfo@container_internal@absl@@@__Cr@std@@@__Cr@std@@QEAA@PEAUHashtablezInfo@container_internal@absl@@@Z ??0?$__cxx_atomic_impl@PEAVCordzHandle@cord_internal@absl@@U?$__cxx_atomic_base_impl@PEAVCordzHandle@cord_internal@absl@@@__Cr@std@@@__Cr@std@@QEAA@PEAVCordzHandle@cord_internal@absl@@@Z ??0?$__cxx_atomic_impl@PEAVCordzInfo@cord_internal@absl@@U?$__cxx_atomic_base_impl@PEAVCordzInfo@cord_internal@absl@@@__Cr@std@@@__Cr@std@@QEAA@PEAVCordzInfo@cord_internal@absl@@@Z - ??0?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@$$A6AXAEAVCommandLineFlag@5@@Z@__function@__Cr@std@@QEAA@$$QEAV@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@@Z ??0?$__deque_iterator@PEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEBV12345@AEAPEBV12345@PEAPEAPEBV12345@_J$0A@@__Cr@std@@AEAA@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEBV34567@@Z ??0?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@AEAA@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAU3456@@Z ??0?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@AEAA@PEBQEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBU3456@@Z @@ -1761,7 +1696,7 @@ EXPORTS ??0?$__hash_node_destructor@V?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@QEAA@AEAV?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@12@_N@Z ??0?$__hash_node_destructor@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@@QEAA@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@@@12@_N@Z ??0?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAA@XZ - ??0?$__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@XZ + ??0?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@XZ ??0?$__map_iterator@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@@@__Cr@std@@QEAA@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@12@@Z ??0?$__map_iterator@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@@@__Cr@std@@QEAA@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@12@@Z ??0?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@__Cr@std@@QEAA@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@@Z @@ -1800,12 +1735,6 @@ EXPORTS ??0?$__optional_move_assign_base@VCord@absl@@$0A@@__Cr@std@@QEAA@XZ ??0?$__optional_move_base@VCord@absl@@$0A@@__Cr@std@@QEAA@XZ ??0?$__optional_storage_base@VCord@absl@@$0A@@__Cr@std@@QEAA@XZ - ??0?$__policy_invoker@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@23@@Z@__function@__Cr@std@@AEAA@P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@23@PEBT__policy_storage@123@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@23@@Z@Z - ??0?$__policy_invoker@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@23@@Z@__function@__Cr@std@@QEAA@XZ - ??0?$__policy_invoker@$$A6AXAEAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@AEAA@P6AXPEBT__policy_storage@123@AEAVCommandLineFlag@absl@@@Z@Z - ??0?$__policy_invoker@$$A6AXAEAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@QEAA@XZ - ??0?$__policy_invoker@$$A6A_NAEBVCommandLineFlag@absl@@@Z@__function@__Cr@std@@AEAA@P6A_NPEBT__policy_storage@123@AEBVCommandLineFlag@absl@@@Z@Z - ??0?$__policy_invoker@$$A6A_NAEBVCommandLineFlag@absl@@@Z@__function@__Cr@std@@QEAA@XZ ??0?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@AEAV?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAA@_K0AEAV?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@12@@Z ??0?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAA@XZ ??0?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@AEAV?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAA@_K0AEAV?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@12@@Z @@ -1829,8 +1758,8 @@ EXPORTS ??0?$__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@@AEAA@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@12@@Z ??0?$__tree_node_destructor@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@@QEAA@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@@@12@_N@Z ??0?$__tree_node_destructor@V?$allocator@V?$__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@__Cr@std@@@__Cr@std@@@__Cr@std@@QEAA@AEAV?$allocator@V?$__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@__Cr@std@@@12@_N@Z - ??0?$__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@__Cr@std@@QEAA@XZ - ??0?$__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@__Cr@std@@QEAA@XZ + ??0?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@__Cr@std@@QEAA@XZ + ??0?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@__Cr@std@@QEAA@XZ ??0?$__wrap_iter@PEAPEAVCommandLineFlag@absl@@@__Cr@std@@AEAA@PEAPEAVCommandLineFlag@absl@@@Z ??0?$__wrap_iter@PEAPEAVCordzHandle@cord_internal@absl@@@__Cr@std@@AEAA@PEAPEAVCordzHandle@cord_internal@absl@@@Z ??0?$__wrap_iter@PEAPEAVLogSink@absl@@@__Cr@std@@AEAA@PEAPEAVLogSink@absl@@@Z @@ -2486,8 +2415,7 @@ EXPORTS ??Buint128@absl@@QEBA_WXZ ??C?$NoDestructor@URefcountedRep@CrcCordState@crc_internal@absl@@@absl@@QEAAPEAURefcountedRep@CrcCordState@crc_internal@1@XZ ??C?$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@@QEBAPEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ - ??C?$__hash_const_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@@QEBAPEBU?$__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@@@12@XZ - ??C?$__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@@QEBAPEAU?$__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@@@12@XZ + ??C?$__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@@QEBAPEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@12@XZ ??C?$__hash_map_const_iterator@V?$__hash_const_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@@@__Cr@std@@QEBAPEBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@12@XZ ??C?$__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@@QEBAPEAU?$pair@$$CBV?$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@@12@XZ ??C?$__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@@QEBAPEAU?$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@@12@XZ @@ -2513,6 +2441,8 @@ EXPORTS ??D?$__deque_iterator@PEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEBV12345@AEAPEBV12345@PEAPEAPEBV12345@_J$0A@@__Cr@std@@QEBAAEAPEBVImpl@time_zone@cctz@time_internal@absl@@XZ ??D?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@QEBAAEAUPrefixCrc@CrcCordState@crc_internal@absl@@XZ ??D?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@QEBAAEBUPrefixCrc@CrcCordState@crc_internal@absl@@XZ + ??D?$__hash_const_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@@QEBAAEBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@12@XZ + ??D?$__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@@QEBAAEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@12@XZ ??D?$__hash_map_iterator@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@@@__Cr@std@@QEBAAEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@12@XZ ??D?$__map_iterator@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@@@__Cr@std@@QEBAAEAU?$pair@$$CBV?$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@@12@XZ ??D?$__map_iterator@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@@@__Cr@std@@QEBAAEAU?$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@@12@XZ @@ -2679,7 +2609,6 @@ EXPORTS ??R?$__allocator_destructor@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXPEAUPrefixCrc@CrcCordState@crc_internal@absl@@@Z ??R?$__bucket_list_deallocator@V?$allocator@PEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@@__Cr@std@@QEAAXPEAPEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@12@@Z ??R?$__bucket_list_deallocator@V?$allocator@PEAU?$__hash_node_base@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@@@__Cr@std@@@__Cr@std@@QEAAXPEAPEAU?$__hash_node_base@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@@Z - ??R?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@$$A6AXAEAVCommandLineFlag@5@@Z@__function@__Cr@std@@QEAAXAEAVCommandLineFlag@absl@@@Z ??R?$__hash_node_destructor@V?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@QEAAXPEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@12@@Z ??R?$__hash_node_destructor@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@@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@12@@Z ??R?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@__Cr@std@@QEBA_NAEBU?$pair@$$CBV?$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@@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z @@ -2691,8 +2620,8 @@ EXPORTS ??R?$__policy_func@$$A6A_NAEBVCommandLineFlag@absl@@@Z@__function@__Cr@std@@QEBA_NAEBVCommandLineFlag@absl@@@Z ??R?$__tree_node_destructor@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@@QEAAXPEAV?$__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@12@@Z ??R?$__tree_node_destructor@V?$allocator@V?$__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@__Cr@std@@@__Cr@std@@@__Cr@std@@QEAAXPEAV?$__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@12@@Z - ??R?$__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@__Cr@std@@QEBA_NAEBU?$__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@@@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z - ??R?$__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@__Cr@std@@QEBA_KAEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z + ??R?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@__Cr@std@@QEBA_NAEBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z + ??R?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@__Cr@std@@QEBA_KAEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z ??R?$default_delete@$$CBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@QEBAXPEBVImpl@time_zone@cctz@time_internal@absl@@@Z ??R?$default_delete@ULogMessageData@LogMessage@log_internal@absl@@@__Cr@std@@QEBAXPEAULogMessageData@LogMessage@log_internal@absl@@@Z ??R?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@__Cr@std@@QEBAXPEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@Z @@ -3156,7 +3085,8 @@ EXPORTS ?EqualsImpl@Cord@absl@@AEBA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@_K@Z ?EquivTransitions@TimeZoneInfo@cctz@time_internal@absl@@AEBA_NEE@Z ?Erase@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAPEAUPayload@status_internal@3@PEBU453@0@Z - ?EraseMetaOnly@container_internal@absl@@YAXAEAVCommonFields@12@PEBW4ctrl_t@12@_K@Z + ?EraseMetaOnlyLarge@container_internal@absl@@YAXAEAVCommonFields@12@PEBW4ctrl_t@12@_K@Z + ?EraseMetaOnlySmall@container_internal@absl@@YAXAEAVCommonFields@12@_N_K@Z ?ErasePayload@StatusRep@status_internal@absl@@QEAA?AUEraseResult@123@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?ErrnoToStatus@absl@@YA?AVStatus@1@HV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?ErrnoToStatusCode@absl@@YA?AW4StatusCode@1@H@Z @@ -3483,6 +3413,7 @@ EXPORTS ?InitFrom@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAXAEBV123@@Z ?InitGrowthLeftNoDeleted@GrowthInfo@container_internal@absl@@QEAAX_K@Z ?InitInstance@CordRepBtree@cord_internal@absl@@AEAAXH_K0@Z + ?InitSigSafeArena@base_internal@absl@@YAXXZ ?InitTables@CRC32@crc_internal@absl@@UEAAXXZ ?InitTree@ChunkIterator@Cord@absl@@AEAAXPEAUCordRep@cord_internal@3@@Z ?InitWhat@BadStatusOrAccess@absl@@AEBAXXZ @@ -3583,7 +3514,6 @@ EXPORTS ?Lock@CordzInfo@cord_internal@absl@@QEAAXW4MethodIdentifier@CordzUpdateTracker@23@@Z ?Lock@FlagRegistry@flags_internal@absl@@QEAAXXZ ?Lock@Mutex@absl@@QEAAXXZ - ?Lock@SpinLock@base_internal@absl@@QEAAXXZ ?LockSlow@Mutex@absl@@AEAAXPEBUMuHowS@2@PEBVCondition@2@H@Z ?LockSlowLoop@Mutex@absl@@AEAAXPEAUSynchWaitParams@2@H@Z ?LockSlowWithDeadline@Mutex@absl@@AEAA_NPEBUMuHowS@2@PEBVCondition@2@VKernelTimeout@synchronization_internal@2@H@Z @@ -3607,6 +3537,7 @@ EXPORTS ?MakeAbsNanos@KernelTimeout@synchronization_internal@absl@@QEBA_JXZ ?MakeAbsTimespec@KernelTimeout@synchronization_internal@absl@@QEBA?AUtimespec@@XZ ?MakeCheckFailString@status_internal@absl@@YAPEBDPEBVStatus@2@PEBD@Z + ?MakeCheckOpUnprintableString@log_internal@absl@@YAXAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?MakeCheckOpValueString@log_internal@absl@@YAXAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@C@Z ?MakeCheckOpValueString@log_internal@absl@@YAXAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@D@Z ?MakeCheckOpValueString@log_internal@absl@@YAXAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@E@Z @@ -3634,7 +3565,6 @@ EXPORTS ?MaskEmptyOrDeleted@GroupSse2Impl@container_internal@absl@@QEBA?AV?$NonIterableBitMask@G$0BA@$0A@@23@XZ ?MaskFull@GroupPortableImpl@container_internal@absl@@QEBA@XZ ?MaskFull@GroupSse2Impl@container_internal@absl@@QEBA?AV?$BitMask@G$0BA@$0A@$0A@@23@XZ - ?MaskFullOrSentinel@GroupSse2Impl@container_internal@absl@@QEBA?AV?$NonIterableBitMask@G$0BA@$0A@@23@XZ ?MaskNonFull@GroupSse2Impl@container_internal@absl@@QEBA@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 @@ -3821,7 +3751,6 @@ EXPORTS ?ReadSeedMaterialFromOSEntropy@random_internal@absl@@YA_NV?$Span@I@2@@Z ?ReadSequenceLockedData@FlagImpl@flags_internal@absl@@AEBAXPEAX@Z ?ReaderLock@Mutex@absl@@QEAAXXZ - ?ReaderTryLock@Mutex@absl@@QEAA_NXZ ?ReaderTryLockSlow@Mutex@absl@@AEAA_NXZ ?ReaderUnlock@Mutex@absl@@QEAAXXZ ?Rebuild@CordRepBtree@cord_internal@absl@@CAXPEAPEAV123@PEAV123@_N@Z @@ -3857,6 +3786,7 @@ EXPORTS ?RegisterMutexProfiler@absl@@YAXP6AX_J@Z@Z ?RegisterMutexTracer@absl@@YAXP6AXPEBDPEBX_J@Z@Z ?RegisterSpinLockProfiler@base_internal@absl@@YAXP6AXPEBX_J@Z@Z + ?RegisterWithTsan@SpinLock@base_internal@absl@@AEAAXXZ ?Rehash@container_internal@absl@@YAXAEAVCommonFields@12@AEBUPolicyFunctions@12@_K@Z ?RehashProbabilityConstant@container_internal@absl@@YA_KXZ ?RelaxedCopyFromAtomic@SequenceLock@flags_internal@absl@@CAXPEAXPEBU?$atomic@_K@__Cr@std@@_K@Z @@ -3996,6 +3926,7 @@ EXPORTS ?ShouldPrependLogPrefix@absl@@YA_NXZ ?ShouldSampleNextTable@container_internal@absl@@YA_NXZ ?ShouldSymbolizeLogStackTrace@log_internal@absl@@YA_NXZ + ?SigSafeArena@base_internal@absl@@YAPEAUArena@LowLevelAlloc@12@XZ ?Signal@CondVar@absl@@QEAAXXZ ?SignalAll@CondVar@absl@@QEAAXXZ ?SignedAddResult@int128_internal@absl@@YA?AVint128@2@V32@0@Z @@ -4192,7 +4123,6 @@ EXPORTS ?TrailingZeros@?$NonIterableBitMask@G$0BA@$0A@@container_internal@absl@@QEBAIXZ ?Trans@Mutex@absl@@AEAAXPEBUMuHowS@2@@Z ?Trunc@absl@@YA?AVDuration@1@V21@0@Z - ?TryLock@Mutex@absl@@QEAA_NXZ ?TryLockImpl@SpinLock@base_internal@absl@@AEAA_NXZ ?TryLockInternal@SpinLock@base_internal@absl@@AEAAIII@Z ?TryLockSlow@Mutex@absl@@AEAA_NXZ @@ -4230,7 +4160,6 @@ EXPORTS ?Unlock@CordzInfo@cord_internal@absl@@QEAAXXZ ?Unlock@FlagRegistry@flags_internal@absl@@QEAAXXZ ?Unlock@Mutex@absl@@QEAAXXZ - ?Unlock@SpinLock@base_internal@absl@@QEAAXXZ ?UnlockSlow@Mutex@absl@@AEAAXPEAUSynchWaitParams@2@@Z ?Unparse@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@F@Z ?Unparse@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@G@Z @@ -4422,15 +4351,10 @@ EXPORTS ?__base_destruct_at_end@?$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@@AEAAXPEAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@23@@Z ?__begin@?$__segmented_iterator_traits@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@@__Cr@std@@SAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU4567@@Z ?__begin@?$__segmented_iterator_traits@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@@__Cr@std@@SAPEBUPrefixCrc@CrcCordState@crc_internal@absl@@PEBQEBU4567@@Z - ?__begin_node@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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_end_node@PEAV?$__tree_node_base@PEAX@__Cr@std@@@23@XZ - ?__begin_node@?$__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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__Cr@std@@AEAAAEAPEAV?$__tree_end_node@PEAV?$__tree_node_base@PEAX@__Cr@std@@@23@XZ ?__call@?$__to_address_helper@V?$__wrap_iter@PEAPEAVCommandLineFlag@absl@@@__Cr@std@@X@__Cr@std@@SAPEAPEAVCommandLineFlag@absl@@AEBV?$__wrap_iter@PEAPEAVCommandLineFlag@absl@@@23@@Z ?__call@?$__to_address_helper@V?$__wrap_iter@PEAPEAVLogSink@absl@@@__Cr@std@@X@__Cr@std@@SAPEAPEAVLogSink@absl@@AEBV?$__wrap_iter@PEAPEAVLogSink@absl@@@23@@Z ?__call@?$__to_address_helper@V?$__wrap_iter@PEAPEBVCommandLineFlag@absl@@@__Cr@std@@X@__Cr@std@@SAPEAPEBVCommandLineFlag@absl@@AEBV?$__wrap_iter@PEAPEBVCommandLineFlag@absl@@@23@@Z ?__call@?$__to_address_helper@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@@X@__Cr@std@@SAPEAUraw_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@@23@AEBV678@@Z@AEBV?$__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@@23@@Z - ?__call_empty@?$__policy_invoker@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@23@@Z@__function@__Cr@std@@CA?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@34@PEBT__policy_storage@234@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@34@@Z - ?__call_empty@?$__policy_invoker@$$A6AXAEAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@CAXPEBT__policy_storage@234@AEAVCommandLineFlag@absl@@@Z - ?__call_empty@?$__policy_invoker@$$A6A_NAEBVCommandLineFlag@absl@@@Z@__function@__Cr@std@@CA_NPEBT__policy_storage@234@AEBVCommandLineFlag@absl@@@Z ?__capacity@?$deque@PEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ ?__capacity@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ ?__complete@?$__exception_guard_noexceptions@V?$_AllocatorDestroyRangeReverse@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@PEAUUnrecognizedFlag@absl@@@__Cr@std@@@__Cr@std@@QEAAXXZ @@ -4442,7 +4366,7 @@ EXPORTS ?__copy_assign_alloc@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAXAEBV123@@Z ?__copy_assign_alloc@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAXAEBV123@U?$integral_constant@_N$0A@@23@@Z ?__deallocate_node@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@AEAAXPEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@23@@Z - ?__deallocate_node@?$__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@@AEAAXPEAU?$__hash_node_base@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@@@23@@Z + ?__deallocate_node@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AEAAXPEAU?$__hash_node_base@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@@@23@@Z ?__destruct_at_begin@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@Z ?__destruct_at_begin@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@U?$integral_constant@_N$00@23@@Z ?__destruct_at_begin@?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@@Z @@ -4488,20 +4412,14 @@ EXPORTS ?__erase_to_end@?$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@@23@@Z ?__front_spare@?$deque@PEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ ?__front_spare@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ - ?__get_key@?$__hash_key_value_types@PEBUCordRep@cord_internal@absl@@@__Cr@std@@SAAEBQEBUCordRep@cord_internal@absl@@AEBQEBU456@@Z ?__get_np@?$__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@@AEBAPEAV?$__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@XZ ?__get_np@?$__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@@AEBAPEAV?$__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@XZ - ?__get_ptr@?$__hash_key_value_types@PEBUCordRep@cord_internal@absl@@@__Cr@std@@SAPEAPEBUCordRep@cord_internal@absl@@AEAPEBU456@@Z - ?__get_ptr@?$__hash_key_value_types@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@@@__Cr@std@@SAPEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@AEAU?$__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@@Z ?__get_value@?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@QEAAAEAPEBUCordRep@cord_internal@absl@@XZ - ?__get_value@?$__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@@QEAAAEAU?$__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@XZ - ?__get_value@?$__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@@QEAAAEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@XZ - ?__get_value@?$__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@@QEBAAEBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@XZ + ?__get_value@?$__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@@QEAAAEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@XZ ?__hash@?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@QEBA_KXZ ?__hash@?$__hash_node_base@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@@QEBA_KXZ ?__insert_node_at@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEAAXPEAV?$__tree_end_node@PEAV?$__tree_node_base@PEAX@__Cr@std@@@23@AEAPEAV?$__tree_node_base@PEAX@23@PEAV523@@Z ?__insert_node_at@?$__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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__Cr@std@@QEAAXPEAV?$__tree_end_node@PEAV?$__tree_node_base@PEAX@__Cr@std@@@23@AEAPEAV?$__tree_node_base@PEAX@23@PEAV523@@Z - ?__insert_unique@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAA?AU?$pair@V?$__hash_iterator@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@_N@23@AEBQEBUCordRep@cord_internal@absl@@@Z ?__local@?$__segmented_iterator_traits@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@__Cr@std@@@__Cr@std@@SAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@Z ?__local@?$__segmented_iterator_traits@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@@__Cr@std@@SAPEBUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@23@@Z ?__make_iter@?$vector@PEAVCommandLineFlag@absl@@V?$allocator@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@AEAA?AV?$__wrap_iter@PEAPEAVCommandLineFlag@absl@@@23@PEAPEAVCommandLineFlag@absl@@@Z @@ -4519,7 +4437,7 @@ EXPORTS ?__move_range@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAXPEAUTransition@cctz@time_internal@absl@@00@Z ?__move_range@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAXPEAUTransitionType@cctz@time_internal@absl@@00@Z ?__node_alloc@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAAAEAV?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@23@XZ - ?__node_alloc@?$__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@@QEAAAEAV?$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@XZ + ?__node_alloc@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEAAAEAV?$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@XZ ?__node_alloc@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$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@XZ ?__node_alloc@?$__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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__Cr@std@@QEAAAEAV?$allocator@V?$__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@__Cr@std@@@23@XZ ?__ptr@?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@QEAAPEAU123@XZ @@ -4537,7 +4455,7 @@ EXPORTS ?__recommend@?$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@@AEBA_K_K@Z ?__recommend_blocks@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@SA_K_K@Z ?__rehash_unique@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAAX_K@Z - ?__rehash_unique@?$__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@@QEAAX_K@Z + ?__rehash_unique@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEAAX_K@Z ?__rewrap@?$__unwrap_iter_impl@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@$00@__Cr@std@@SAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV45678@0@Z ?__rewrap@?$__unwrap_iter_impl@PEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@$00@__Cr@std@@SAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@PEAPEAU4567@0@Z ?__rewrap@?$__unwrap_iter_impl@PEAPEAVLogSink@absl@@$00@__Cr@std@@SAPEAPEAVLogSink@absl@@PEAPEAV45@0@Z @@ -4677,6 +4595,7 @@ EXPORTS ?ascii_isxdigit@absl@@YA_NE@Z ?ascii_tolower@absl@@YADE@Z ?ascii_toupper@absl@@YADE@Z + ?assert_is_full@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@@AEBAXPEBD@Z ?at_end@?$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@@QEBA_NXZ ?back@?$InlinedVector@PEAUCordRep@cord_internal@absl@@$01V?$allocator@PEAUCordRep@cord_internal@absl@@@__Cr@std@@@absl@@QEAAAEAPEAUCordRep@cord_internal@2@XZ ?back@?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@AEAV?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAAEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@XZ @@ -4717,7 +4636,7 @@ EXPORTS ?begin@?$Splitter@VByAnyChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$SplitIterator@V?$Splitter@VByAnyChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@23@XZ ?begin@?$Splitter@VByAnyChar@absl@@USkipEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$SplitIterator@V?$Splitter@VByAnyChar@absl@@USkipEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@23@XZ ?begin@?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$SplitIterator@V?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@23@XZ - ?begin@?$__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@@@23@XZ + ?begin@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@@23@XZ ?begin@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@XZ ?begin@?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@XZ ?begin@?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEBAPEBQEAUPrefixCrc@CrcCordState@crc_internal@absl@@XZ @@ -4752,7 +4671,7 @@ EXPORTS ?btree@CordRepBtreeNavigator@cord_internal@absl@@QEBAPEAVCordRepBtree@23@XZ ?btree@CordRepBtreeReader@cord_internal@absl@@QEBAPEAVCordRepBtree@23@XZ ?bucket_count@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEBA_KXZ - ?bucket_count@?$__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@@QEBA_KXZ + ?bucket_count@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEBA_KXZ ?bytes_value@ProtoField@log_internal@absl@@QEBA?AV?$Span@$$CBD@3@XZ ?capacity@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@AEAV?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ ?capacity@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ @@ -4791,7 +4710,7 @@ EXPORTS ?chunk_begin@Cord@absl@@QEBA?AVChunkIterator@12@XZ ?chunk_end@Cord@absl@@QEBA?AVChunkIterator@12@XZ ?clear@?$InlinedVector@PEAVLogSink@absl@@$0BA@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@absl@@QEAAXXZ - ?clear@?$__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@@QEAAXXZ + ?clear@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEAAXXZ ?clear@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@AEAV?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXXZ ?clear@?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@AEAV?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXXZ ?clear@?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXXZ @@ -4827,6 +4746,7 @@ EXPORTS ?combine_raw@MixingHashState@hash_internal@absl@@CA?AV123@V123@_K@Z ?common@?$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@@AEAAAEAVCommonFields@23@XZ ?common@?$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@@AEBAAEBVCommonFields@23@XZ + ?compare_exchange_strong@?$__atomic_base@PEAUArena@LowLevelAlloc@base_internal@absl@@$0A@@__Cr@std@@QEAA_NAEAPEAUArena@LowLevelAlloc@base_internal@absl@@PEAU4567@W4memory_order@23@2@Z ?compare_exchange_strong@?$__atomic_base@PEAVTimeZone@absl@@$0A@@__Cr@std@@QEAA_NAEAPEAVTimeZone@absl@@PEAV45@W4memory_order@23@2@Z ?compare_exchange_strong@?$__atomic_base@PEAVVLogSite@log_internal@absl@@$0A@@__Cr@std@@QEAA_NAEAPEAVVLogSite@log_internal@absl@@PEAV456@W4memory_order@23@2@Z ?compare_exchange_weak@?$__atomic_base@PEAUHashtablezInfo@container_internal@absl@@$0A@@__Cr@std@@QEAA_NAEAPEAUHashtablezInfo@container_internal@absl@@PEAU456@W4memory_order@23@2@Z @@ -4990,7 +4910,7 @@ EXPORTS ?end@?$Splitter@VByAnyChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$SplitIterator@V?$Splitter@VByAnyChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@23@XZ ?end@?$Splitter@VByAnyChar@absl@@USkipEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$SplitIterator@V?$Splitter@VByAnyChar@absl@@USkipEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@23@XZ ?end@?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$SplitIterator@V?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@23@XZ - ?end@?$__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@@@23@XZ + ?end@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@@23@XZ ?end@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@XZ ?end@?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAPEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@XZ ?end@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?AV?$__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@23@XZ @@ -5026,7 +4946,6 @@ EXPORTS ?external@CordRep@cord_internal@absl@@QEBAPEBUCordRepExternal@23@XZ ?fetch_add_end@CordRepBtree@cord_internal@absl@@AEAA_K_K@Z ?find@?$unordered_map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@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@V?$allocator@U?$pair@$$CBV?$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_map_iterator@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@@@23@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@23@@Z - ?find_first_non_full@container_internal@absl@@YA?AUFindInfo@12@AEBVCommonFields@12@_K@Z ?fits_in_soo@?$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@@AEBA_N_K@Z ?fixed_time_zone@cctz@time_internal@absl@@YA?AVtime_zone@123@AEBV?$duration@_JV?$ratio@$00$00@__Cr@std@@@chrono@__Cr@std@@@Z ?flat@CordRep@cord_internal@absl@@QEAAPEAUCordRepFlat@23@XZ @@ -5135,7 +5054,7 @@ EXPORTS ?has_timeout@KernelTimeout@synchronization_internal@absl@@QEBA_NXZ ?has_zero_flag@FormatConversionSpecImpl@str_format_internal@absl@@QEBA_NXZ ?hash_function@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAAAEAU?$hash@PEBUCordRep@cord_internal@absl@@@23@XZ - ?hash_function@?$__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@@QEAAAEAV?$__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@XZ + ?hash_function@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEAAAEAV?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@XZ ?hash_ref@?$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@@AEAAAEAUStringHash@23@XZ ?hash_ref@?$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@@AEBAAEBUStringHash@23@XZ ?hash_with_seed@?$HashImpl@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@hash_internal@absl@@AEBA_KAEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@_K@Z @@ -5184,10 +5103,11 @@ EXPORTS ?iterator_at_ptr@?$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@@IEAA?AViterator@123@U?$pair@PEAW4ctrl_t@container_internal@absl@@PEAX@__Cr@std@@@Z ?kDefaultIterControl@container_internal@absl@@3W4ctrl_t@12@A ?key_eq@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAAAEAU?$equal_to@PEBUCordRep@cord_internal@absl@@@23@XZ - ?key_eq@?$__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@@QEAAAEAV?$__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@XZ + ?key_eq@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEAAAEAV?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@XZ ?length@CordRepBtreeReader@cord_internal@absl@@QEBA_KXZ ?length_mod@FormatConversionSpecImpl@str_format_internal@absl@@QEBA?AW4LengthMod@3@XZ ?load@?$__atomic_base@P6AXAEBUHashtablezInfo@container_internal@absl@@@Z$0A@@__Cr@std@@QEBAP6AXAEBUHashtablezInfo@container_internal@absl@@@ZW4memory_order@23@@Z + ?load@?$__atomic_base@PEAUArena@LowLevelAlloc@base_internal@absl@@$0A@@__Cr@std@@QEBAPEAUArena@LowLevelAlloc@base_internal@absl@@W4memory_order@23@@Z ?load@?$__atomic_base@PEAUHashtablezInfo@container_internal@absl@@$0A@@__Cr@std@@QEBAPEAUHashtablezInfo@container_internal@absl@@W4memory_order@23@@Z ?load@?$__atomic_base@PEAVCordzHandle@cord_internal@absl@@$0A@@__Cr@std@@QEBAPEAVCordzHandle@cord_internal@absl@@W4memory_order@23@@Z ?load@?$__atomic_base@PEAVCordzInfo@cord_internal@absl@@$0A@@__Cr@std@@QEBAPEAVCordzInfo@cord_internal@absl@@W4memory_order@23@@Z @@ -5198,6 +5118,9 @@ EXPORTS ?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 ?local_time_zone@cctz@time_internal@absl@@YA?AVtime_zone@123@XZ + ?lock@Mutex@absl@@QEAAXXZ + ?lock@SpinLock@base_internal@absl@@QEAAXXZ + ?lock_shared@Mutex@absl@@QEAAXXZ ?log_severity@LogEntry@absl@@QEBA?AW4LogSeverity@2@XZ ?lookup@time_zone@cctz@time_internal@absl@@QEBA?AUabsolute_lookup@1234@AEBV?$time_point@Vsystem_clock@chrono@__Cr@std@@V?$duration@_JV?$ratio@$00$00@__Cr@std@@@234@@chrono@__Cr@std@@@Z ?lookup@time_zone@cctz@time_internal@absl@@QEBA?AUcivil_lookup@1234@AEBV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@detail@234@@Z @@ -5208,7 +5131,7 @@ EXPORTS ?max@?$numeric_limits@Vint128@absl@@@__Cr@std@@SA?AVint128@absl@@XZ ?max@?$numeric_limits@Vuint128@absl@@@__Cr@std@@SA?AVuint128@absl@@XZ ?max_load_factor@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAAAEAMXZ - ?max_load_factor@?$__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@@QEAAAEAMXZ + ?max_load_factor@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEAAAEAMXZ ?max_size@?$vector@PEAVCommandLineFlag@absl@@V?$allocator@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ ?max_size@?$vector@PEAVCordzHandle@cord_internal@absl@@V?$allocator@PEAVCordzHandle@cord_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ ?max_size@?$vector@PEAVLogSink@absl@@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ @@ -5255,10 +5178,9 @@ EXPORTS ?parsed_conversion@UntypedFormatSpecImpl@str_format_internal@absl@@QEBAPEBVParsedFormatBase@23@XZ ?pointer_to@?$pointer_traits@PEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SAPEAU?$__hash_node_base@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@23@AEAU423@@Z ?pointer_to@?$pointer_traits@PEAU?$__hash_node_base@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@@@__Cr@std@@SAPEAU?$__hash_node_base@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@@@23@AEAU423@@Z - ?pointer_to@?$pointer_traits@PEAU?$__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@@@__Cr@std@@SAPEAU?$__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@AEAU423@@Z + ?pointer_to@?$pointer_traits@PEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@SAPEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@AEAU423@@Z ?pointer_to@?$pointer_traits@PEAU?$pair@$$CBV?$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@@@__Cr@std@@SAPEAU?$pair@$$CBV?$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@AEAU423@@Z ?pointer_to@?$pointer_traits@PEAU?$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@@@__Cr@std@@SAPEAU?$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@@23@AEAU423@@Z - ?pointer_to@?$pointer_traits@PEBU?$__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@@@__Cr@std@@SAPEBU?$__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@AEBU423@@Z ?pointer_to@?$pointer_traits@PEBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@SAPEBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@AEBU423@@Z ?poison@InlineData@cord_internal@absl@@QEAAXXZ ?poison_this@InlineData@cord_internal@absl@@QEAAXXZ @@ -5375,6 +5297,7 @@ EXPORTS ?set_cordz_mean_interval@cord_internal@absl@@YAXH@Z ?set_data@InlineRep@Cord@absl@@QEAAPEAD_K@Z ?set_data@InlineRep@Cord@absl@@QEAAXPEBD_K@Z + ?set_empty_soo@CommonFields@container_internal@absl@@QEAAXXZ ?set_end@CordRepBtree@cord_internal@absl@@AEAAX_K@Z ?set_from_arg@InputValue@UnboundConversion@str_format_internal@absl@@QEAAXH@Z ?set_full_soo@CommonFields@container_internal@absl@@QEAAXXZ @@ -5426,12 +5349,10 @@ EXPORTS ?size@?$__bucket_list_deallocator@V?$allocator@PEAU?$__hash_node_base@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@@@__Cr@std@@@__Cr@std@@QEAAAEA_KXZ ?size@?$__bucket_list_deallocator@V?$allocator@PEAU?$__hash_node_base@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@@@__Cr@std@@@__Cr@std@@QEBA_KXZ ?size@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@AEAAAEA_KXZ - ?size@?$__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@@AEAAAEA_KXZ + ?size@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AEAAAEA_KXZ ?size@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ ?size@?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ - ?size@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AEAAAEA_KXZ - ?size@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEBAAEB_KXZ - ?size@?$__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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__Cr@std@@AEAAAEA_KXZ + ?size@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QEBA_KXZ ?size@?$array@Uraw_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@$0BA@@__Cr@std@@QEBA_KXZ ?size@?$deque@PEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ ?size@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_KXZ @@ -5508,8 +5429,13 @@ EXPORTS ?transfer_unprobed_elements_to_next_capacity_fn@?$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@@CAXAEAVCommonFields@23@PEBW4ctrl_t@23@PEAX2P6AX2E_K3@Z@Z ?tree@InlineRep@Cord@absl@@QEBAPEAUCordRep@cord_internal@3@XZ ?tree@Rep@InlineData@cord_internal@absl@@QEBAPEAUCordRep@34@XZ + ?try_lock@Mutex@absl@@QEAA_NXZ + ?try_lock_shared@Mutex@absl@@QEAA_NXZ ?type@ProtoField@log_internal@absl@@QEBA?AW4WireType@23@XZ ?unchecked_deref@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@@AEBAAEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@XZ + ?unlock@Mutex@absl@@QEAAXXZ + ?unlock@SpinLock@base_internal@absl@@QEAAXXZ + ?unlock_shared@Mutex@absl@@QEAAXXZ ?unpoison@InlineData@cord_internal@absl@@QEAAXXZ ?utc_time_zone@cctz@time_internal@absl@@YA?AVtime_zone@123@XZ ?value@ConvertibleToStringView@strings_internal@absl@@QEBA?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ 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 78820d2deb..2dc59db82f 100644 --- a/naiveproxy/src/third_party/abseil-cpp/symbols_x64_rel.def +++ b/naiveproxy/src/third_party/abseil-cpp/symbols_x64_rel.def @@ -153,18 +153,18 @@ EXPORTS ??$UnparseFloatingPointVal@N@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@N@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_impl@V?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@$$A6AXAEAVCommandLineFlag@5@@Z@__function@__Cr@std@@@?$__policy_invoker@$$A6AXAEAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@CAXPEBT__policy_storage@123@AEAVCommandLineFlag@absl@@@Z + ??$__call_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@@?$__policy_func@$$A6AXAEAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@CAXPEBT__policy_storage@123@AEAVCommandLineFlag@absl@@@Z ??$__dispatch@$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@?$__dispatcher@$00@__base@__visitation@__variant_detail@__Cr@std@@SA?A_T$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@2345@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@345@@Z ??$__dispatch@$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@?$__dispatcher@$01@__base@__visitation@__variant_detail@__Cr@std@@SA?A_T$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@2345@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@345@@Z ??$__dispatch@$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@?$__dispatcher@$02@__base@__visitation@__variant_detail@__Cr@std@@SA?A_T$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@2345@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@345@@Z ??$__dispatch@$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@?$__dispatcher@$0A@@__base@__visitation@__variant_detail@__Cr@std@@SA?A_T$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@2345@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@345@@Z ??$__do_rehash@$00@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@AEAAX_K@Z - ??$__do_rehash@$00@?$__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@@AEAAX_K@Z + ??$__do_rehash@$00@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AEAAX_K@Z ??$__emplace_back_slow_path@AEBUUnrecognizedFlag@absl@@@?$vector@UUnrecognizedFlag@absl@@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@@__Cr@std@@AEAAPEAUUnrecognizedFlag@absl@@AEBU34@@Z ??$__emplace_back_slow_path@W4Source@UnrecognizedFlag@absl@@AEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$vector@UUnrecognizedFlag@absl@@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@@__Cr@std@@AEAAPEAUUnrecognizedFlag@absl@@$$QEAW4Source@34@AEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@12@@Z ??$__emplace_unique_key_args@PEBUCordRep@cord_internal@absl@@AEBQEBU123@@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAA?AU?$pair@V?$__hash_iterator@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@_N@12@AEBQEBUCordRep@cord_internal@absl@@0@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@$$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__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 ??$__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@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@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 @@ -193,7 +193,7 @@ EXPORTS ??$emplace_front@AEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@@?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@AEAV?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXAEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@@Z ??$emplace_front@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAX$$QEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@Z ??$emplace_front@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@?$__split_buffer@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAX$$QEAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@@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@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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@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@@QEAA?AViterator@012@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??$find_or_prepare_insert@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@@IEAA?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 ??$find_or_prepare_insert_large@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 @@ -256,7 +256,6 @@ EXPORTS ??0Randen@random_internal@absl@@QEAA@XZ ??0ScopedMinLogLevel@log_internal@absl@@QEAA@W4LogSeverityAtLeast@2@@Z ??0ScopedStderrThreshold@absl@@QEAA@W4LogSeverityAtLeast@1@@Z - ??0SpinLock@base_internal@absl@@QEAA@W4SchedulingMode@12@@Z ??0Status@absl@@QEAA@W4StatusCode@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??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 @@ -333,7 +332,6 @@ EXPORTS ??ACord@absl@@QEBAD_K@Z ??BCord@absl@@QEBA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@XZ ??Bint128@absl@@QEBANXZ - ??Eiterator@?$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@@QEAAAEAV0123@XZ ??Gdetail@cctz@time_internal@absl@@YA?AV?$civil_time@Uday_tag@detail@cctz@time_internal@absl@@@0123@V40123@_J@Z ??Gdetail@cctz@time_internal@absl@@YA?AV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@0123@V40123@_J@Z ??Gdetail@cctz@time_internal@absl@@YA_JV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@0123@0@Z @@ -585,7 +583,8 @@ EXPORTS ?EqualsImpl@Cord@absl@@AEBA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@_K@Z ?EquivTransitions@TimeZoneInfo@cctz@time_internal@absl@@AEBA_NEE@Z ?Erase@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAPEAUPayload@status_internal@3@PEBU453@0@Z - ?EraseMetaOnly@container_internal@absl@@YAXAEAVCommonFields@12@PEBW4ctrl_t@12@_K@Z + ?EraseMetaOnlyLarge@container_internal@absl@@YAXAEAVCommonFields@12@PEBW4ctrl_t@12@_K@Z + ?EraseMetaOnlySmall@container_internal@absl@@YAXAEAVCommonFields@12@_N_K@Z ?ErasePayload@StatusRep@status_internal@absl@@QEAA?AUEraseResult@123@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?ErrnoToStatus@absl@@YA?AVStatus@1@HV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?ErrnoToStatusCode@absl@@YA?AW4StatusCode@1@H@Z @@ -779,6 +778,7 @@ EXPORTS ?Init@FlagImpl@flags_internal@absl@@AEAAXXZ ?InitDiscreteDistribution@random_internal@absl@@YA?AV?$vector@U?$pair@N_K@__Cr@std@@V?$allocator@U?$pair@N_K@__Cr@std@@@23@@__Cr@std@@PEAV?$vector@NV?$allocator@N@__Cr@std@@@45@@Z ?InitFrom@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAXAEBV123@@Z + ?InitSigSafeArena@base_internal@absl@@YAXXZ ?InitTables@CRC32@crc_internal@absl@@UEAAXXZ ?InitTree@ChunkIterator@Cord@absl@@AEAAXPEAUCordRep@cord_internal@3@@Z ?InitWhat@BadStatusOrAccess@absl@@AEBAXXZ @@ -834,7 +834,6 @@ EXPORTS ?LocalTime@TimeZoneInfo@cctz@time_internal@absl@@AEBA?AUabsolute_lookup@time_zone@234@_JAEBUTransition@234@@Z ?LocalTime@TimeZoneInfo@cctz@time_internal@absl@@AEBA?AUabsolute_lookup@time_zone@234@_JAEBUTransitionType@234@@Z ?Lock@CordzInfo@cord_internal@absl@@QEAAXW4MethodIdentifier@CordzUpdateTracker@23@@Z - ?Lock@Mutex@absl@@QEAAXXZ ?LockSlow@Mutex@absl@@AEAAXPEBUMuHowS@2@PEBVCondition@2@H@Z ?LockSlowLoop@Mutex@absl@@AEAAXPEAUSynchWaitParams@2@H@Z ?LockSlowWithDeadline@Mutex@absl@@AEAA_NPEBUMuHowS@2@PEBVCondition@2@VKernelTimeout@synchronization_internal@2@H@Z @@ -848,6 +847,7 @@ EXPORTS ?MakeAbsNanos@KernelTimeout@synchronization_internal@absl@@QEBA_JXZ ?MakeAbsTimespec@KernelTimeout@synchronization_internal@absl@@QEBA?AUtimespec@@XZ ?MakeCheckFailString@status_internal@absl@@YAPEBDPEBVStatus@2@PEBD@Z + ?MakeCheckOpUnprintableString@log_internal@absl@@YAXAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?MakeCheckOpValueString@log_internal@absl@@YAXAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@C@Z ?MakeCheckOpValueString@log_internal@absl@@YAXAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@D@Z ?MakeCheckOpValueString@log_internal@absl@@YAXAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@E@Z @@ -983,10 +983,7 @@ EXPORTS ?ReadOneWord@FlagImpl@flags_internal@absl@@QEBA_JXZ ?ReadSeedMaterialFromOSEntropy@random_internal@absl@@YA_NV?$Span@I@2@@Z ?ReadSequenceLockedData@FlagImpl@flags_internal@absl@@AEBAXPEAX@Z - ?ReaderLock@Mutex@absl@@QEAAXXZ - ?ReaderTryLock@Mutex@absl@@QEAA_NXZ ?ReaderTryLockSlow@Mutex@absl@@AEAA_NXZ - ?ReaderUnlock@Mutex@absl@@QEAAXXZ ?Rebuild@CordRepBtree@cord_internal@absl@@CAXPEAPEAV123@PEAV123@_N@Z ?Rebuild@CordRepBtree@cord_internal@absl@@SAPEAV123@PEAV123@@Z ?RecordClearedReservationSlow@container_internal@absl@@YAXPEAUHashtablezInfo@12@@Z @@ -1088,6 +1085,7 @@ EXPORTS ?ShouldLogBacktraceAt@log_internal@absl@@YA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@H@Z ?ShouldPrependLogPrefix@absl@@YA_NXZ ?ShouldSymbolizeLogStackTrace@log_internal@absl@@YA_NXZ + ?SigSafeArena@base_internal@absl@@YAPEAUArena@LowLevelAlloc@12@XZ ?Signal@CondVar@absl@@QEAAXXZ ?SignalAll@CondVar@absl@@QEAAXXZ ?SimpleAtob@absl@@YA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEA_N@Z @@ -1207,7 +1205,6 @@ EXPORTS ?TrackCord@CordzInfo@cord_internal@absl@@SAXAEAVInlineData@23@W4MethodIdentifier@CordzUpdateTracker@23@_J@Z ?Trans@Mutex@absl@@AEAAXPEBUMuHowS@2@@Z ?Trunc@absl@@YA?AVDuration@1@V21@0@Z - ?TryLock@Mutex@absl@@QEAA_NXZ ?TryLockSlow@Mutex@absl@@AEAA_NXZ ?TryNewCRC32AcceleratedX86ARMCombined@crc_internal@absl@@YAPEAVCRCImpl@12@XZ ?TryParse@FlagImpl@flags_internal@absl@@AEBA?AV?$unique_ptr@XUDynValueDeleter@flags_internal@absl@@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@56@AEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@56@@Z @@ -1230,7 +1227,6 @@ EXPORTS ?UnimplementedError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?UnknownError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?Unlock@CordzInfo@cord_internal@absl@@QEAAXXZ - ?Unlock@Mutex@absl@@QEAAXXZ ?UnlockSlow@Mutex@absl@@AEAAXPEAUSynchWaitParams@2@@Z ?Unparse@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@F@Z ?Unparse@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@G@Z @@ -1311,7 +1307,6 @@ EXPORTS ?destroy@?$__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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__Cr@std@@AEAAXPEAV?$__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@@Z ?effective_impl@time_zone@cctz@time_internal@absl@@AEBAAEBVImpl@1234@XZ ?engines@?1??CrcAndCopy@CrcMemcpy@crc_internal@absl@@SA?AVcrc32c_t@4@PEIAXPEIBX_KV54@_N@Z@4UArchSpecificEngines@234@B - ?find_first_non_full@container_internal@absl@@YA?AUFindInfo@12@AEBVCommonFields@12@_K@Z ?fixed_time_zone@cctz@time_internal@absl@@YA?AVtime_zone@123@AEBV?$duration@_JV?$ratio@$00$00@__Cr@std@@@chrono@__Cr@std@@@Z ?format@detail@cctz@time_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBV567@AEBV?$time_point@Vsystem_clock@chrono@__Cr@std@@V?$duration@_JV?$ratio@$00$00@__Cr@std@@@234@@chrono@67@AEBV?$duration@_JV?$ratio@$00$0DINHOKEMGIAAA@@__Cr@std@@@967@AEBVtime_zone@234@@Z ?from_chars@absl@@YA?AUfrom_chars_result@1@PEBD0AEAMW4chars_format@1@@Z @@ -1321,6 +1316,8 @@ EXPORTS ?kDefaultIterControl@container_internal@absl@@3W4ctrl_t@12@A ?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 ?local_time_zone@cctz@time_internal@absl@@YA?AVtime_zone@123@XZ + ?lock@Mutex@absl@@QEAAXXZ + ?lock_shared@Mutex@absl@@QEAAXXZ ?lookup@time_zone@cctz@time_internal@absl@@QEBA?AUabsolute_lookup@1234@AEBV?$time_point@Vsystem_clock@chrono@__Cr@std@@V?$duration@_JV?$ratio@$00$00@__Cr@std@@@234@@chrono@__Cr@std@@@Z ?lookup@time_zone@cctz@time_internal@absl@@QEBA?AUcivil_lookup@1234@AEBV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@detail@234@@Z ?memcasecmp@strings_internal@absl@@YAHPEBD0_K@Z @@ -1359,6 +1356,10 @@ EXPORTS ?status@BadStatusOrAccess@absl@@QEBAAEBVStatus@2@XZ ?stream@OstreamView@LogMessage@log_internal@absl@@QEAAAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ ?transfer_unprobed_elements_to_next_capacity_fn@?$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@@CAXAEAVCommonFields@23@PEBW4ctrl_t@23@PEAX2P6AX2E_K3@Z@Z + ?try_lock@Mutex@absl@@QEAA_NXZ + ?try_lock_shared@Mutex@absl@@QEAA_NXZ + ?unlock@Mutex@absl@@QEAAXXZ + ?unlock_shared@Mutex@absl@@QEAAXXZ ?utc_time_zone@cctz@time_internal@absl@@YA?AVtime_zone@123@XZ ?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 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 f98cabc0b6..f74227d2db 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 @@ -158,14 +158,14 @@ EXPORTS ??$__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 - ??$__call_impl@V?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@$$A6AXAEAVCommandLineFlag@5@@Z@__function@__Cr@std@@@?$__policy_invoker@$$A6AXAEAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@CAXPEBT__policy_storage@123@AEAVCommandLineFlag@absl@@@Z + ??$__call_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@@?$__policy_func@$$A6AXAEAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@CAXPEBT__policy_storage@123@AEAVCommandLineFlag@absl@@@Z ??$__construct_at_end@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@@AEAAXV?$__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@0_K@Z ??$__dispatch@$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@?$__dispatcher@$00@__base@__visitation@__variant_detail@__Cr@std@@SA?A_T$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@2345@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@345@@Z ??$__dispatch@$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@?$__dispatcher@$01@__base@__visitation@__variant_detail@__Cr@std@@SA?A_T$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@2345@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@345@@Z ??$__dispatch@$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@?$__dispatcher@$02@__base@__visitation@__variant_detail@__Cr@std@@SA?A_T$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@2345@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@345@@Z ??$__dispatch@$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@?$__dispatcher@$0A@@__base@__visitation@__variant_detail@__Cr@std@@SA?A_T$$QEAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YA_KUStructuredProtoField@34@@Z@@__variant@2345@AEAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@345@@Z ??$__do_rehash@$00@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@AEAAX_K@Z - ??$__do_rehash@$00@?$__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@@AEAAX_K@Z + ??$__do_rehash@$00@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AEAAX_K@Z ??$__emplace_back_slow_path@AEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@AEBV123@AEA_K@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAPEAUViableSubstitution@strings_internal@absl@@AEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@12@AEBV612@AEA_K@Z ??$__emplace_back_slow_path@AEBQEAVCommandLineFlag@absl@@@?$vector@PEAVCommandLineFlag@absl@@V?$allocator@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@AEAAPEAPEAVCommandLineFlag@absl@@AEBQEAV34@@Z ??$__emplace_back_slow_path@AEBQEAVCordzHandle@cord_internal@absl@@@?$vector@PEAVCordzHandle@cord_internal@absl@@V?$allocator@PEAVCordzHandle@cord_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAPEAPEAVCordzHandle@cord_internal@absl@@AEBQEAV345@@Z @@ -180,7 +180,7 @@ EXPORTS ??$__emplace_back_slow_path@W4Source@UnrecognizedFlag@absl@@AEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$vector@UUnrecognizedFlag@absl@@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@@__Cr@std@@AEAAPEAUUnrecognizedFlag@absl@@$$QEAW4Source@34@AEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@12@@Z ??$__emplace_unique_key_args@PEBUCordRep@cord_internal@absl@@AEBQEBU123@@?$__hash_table@PEBUCordRep@cord_internal@absl@@U?$hash@PEBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PEBUCordRep@cord_internal@absl@@@56@V?$allocator@PEBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QEAA?AU?$pair@V?$__hash_iterator@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@_N@12@AEBQEBUCordRep@cord_internal@absl@@0@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@$$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__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 ??$__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@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@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 @@ -267,7 +267,6 @@ EXPORTS ??0Randen@random_internal@absl@@QEAA@XZ ??0ScopedMinLogLevel@log_internal@absl@@QEAA@W4LogSeverityAtLeast@2@@Z ??0ScopedStderrThreshold@absl@@QEAA@W4LogSeverityAtLeast@1@@Z - ??0SpinLock@base_internal@absl@@QEAA@W4SchedulingMode@12@@Z ??0Status@absl@@QEAA@W4StatusCode@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??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 @@ -348,9 +347,6 @@ EXPORTS ??ACord@absl@@QEBAD_K@Z ??BCord@absl@@QEBA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@XZ ??Bint128@absl@@QEBANXZ - ??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 - ??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 - ??Eiterator@?$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@@QEAAAEAV0123@XZ ??Gdetail@cctz@time_internal@absl@@YA?AV?$civil_time@Uday_tag@detail@cctz@time_internal@absl@@@0123@V40123@_J@Z ??Gdetail@cctz@time_internal@absl@@YA?AV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@0123@V40123@_J@Z ??Gdetail@cctz@time_internal@absl@@YA_JV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@0123@0@Z @@ -613,7 +609,8 @@ EXPORTS ?EqualsImpl@Cord@absl@@AEBA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@_K@Z ?EquivTransitions@TimeZoneInfo@cctz@time_internal@absl@@AEBA_NEE@Z ?Erase@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAPEAUPayload@status_internal@3@PEBU453@0@Z - ?EraseMetaOnly@container_internal@absl@@YAXAEAVCommonFields@12@PEBW4ctrl_t@12@_K@Z + ?EraseMetaOnlyLarge@container_internal@absl@@YAXAEAVCommonFields@12@PEBW4ctrl_t@12@_K@Z + ?EraseMetaOnlySmall@container_internal@absl@@YAXAEAVCommonFields@12@_N_K@Z ?ErasePayload@StatusRep@status_internal@absl@@QEAA?AUEraseResult@123@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?ErrnoToStatus@absl@@YA?AVStatus@1@HV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?ErrnoToStatusCode@absl@@YA?AW4StatusCode@1@H@Z @@ -808,6 +805,7 @@ EXPORTS ?Init@FlagImpl@flags_internal@absl@@AEAAXXZ ?InitDiscreteDistribution@random_internal@absl@@YA?AV?$vector@U?$pair@N_K@__Cr@std@@V?$allocator@U?$pair@N_K@__Cr@std@@@23@@__Cr@std@@PEAV?$vector@NV?$allocator@N@__Cr@std@@@45@@Z ?InitFrom@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAXAEBV123@@Z + ?InitSigSafeArena@base_internal@absl@@YAXXZ ?InitTables@CRC32@crc_internal@absl@@UEAAXXZ ?InitTree@ChunkIterator@Cord@absl@@AEAAXPEAUCordRep@cord_internal@3@@Z ?InitWhat@BadStatusOrAccess@absl@@AEBAXXZ @@ -864,7 +862,6 @@ EXPORTS ?LocalTime@TimeZoneInfo@cctz@time_internal@absl@@AEBA?AUabsolute_lookup@time_zone@234@_JAEBUTransition@234@@Z ?LocalTime@TimeZoneInfo@cctz@time_internal@absl@@AEBA?AUabsolute_lookup@time_zone@234@_JAEBUTransitionType@234@@Z ?Lock@CordzInfo@cord_internal@absl@@QEAAXW4MethodIdentifier@CordzUpdateTracker@23@@Z - ?Lock@Mutex@absl@@QEAAXXZ ?LockSlow@Mutex@absl@@AEAAXPEBUMuHowS@2@PEBVCondition@2@H@Z ?LockSlowLoop@Mutex@absl@@AEAAXPEAUSynchWaitParams@2@H@Z ?LockSlowWithDeadline@Mutex@absl@@AEAA_NPEBUMuHowS@2@PEBVCondition@2@VKernelTimeout@synchronization_internal@2@H@Z @@ -878,6 +875,7 @@ EXPORTS ?MakeAbsNanos@KernelTimeout@synchronization_internal@absl@@QEBA_JXZ ?MakeAbsTimespec@KernelTimeout@synchronization_internal@absl@@QEBA?AUtimespec@@XZ ?MakeCheckFailString@status_internal@absl@@YAPEBDPEBVStatus@2@PEBD@Z + ?MakeCheckOpUnprintableString@log_internal@absl@@YAXAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?MakeCheckOpValueString@log_internal@absl@@YAXAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@C@Z ?MakeCheckOpValueString@log_internal@absl@@YAXAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@D@Z ?MakeCheckOpValueString@log_internal@absl@@YAXAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@E@Z @@ -1014,10 +1012,7 @@ EXPORTS ?ReadOneWord@FlagImpl@flags_internal@absl@@QEBA_JXZ ?ReadSeedMaterialFromOSEntropy@random_internal@absl@@YA_NV?$Span@I@2@@Z ?ReadSequenceLockedData@FlagImpl@flags_internal@absl@@AEBAXPEAX@Z - ?ReaderLock@Mutex@absl@@QEAAXXZ - ?ReaderTryLock@Mutex@absl@@QEAA_NXZ ?ReaderTryLockSlow@Mutex@absl@@AEAA_NXZ - ?ReaderUnlock@Mutex@absl@@QEAAXXZ ?Rebuild@CordRepBtree@cord_internal@absl@@CAXPEAPEAV123@PEAV123@_N@Z ?Rebuild@CordRepBtree@cord_internal@absl@@SAPEAV123@PEAV123@@Z ?RecordClearedReservationSlow@container_internal@absl@@YAXPEAUHashtablezInfo@12@@Z @@ -1123,6 +1118,7 @@ EXPORTS ?ShouldLogBacktraceAt@log_internal@absl@@YA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@H@Z ?ShouldPrependLogPrefix@absl@@YA_NXZ ?ShouldSymbolizeLogStackTrace@log_internal@absl@@YA_NXZ + ?SigSafeArena@base_internal@absl@@YAPEAUArena@LowLevelAlloc@12@XZ ?Signal@CondVar@absl@@QEAAXXZ ?SignalAll@CondVar@absl@@QEAAXXZ ?SimpleAtob@absl@@YA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEA_N@Z @@ -1242,7 +1238,6 @@ EXPORTS ?TrackCord@CordzInfo@cord_internal@absl@@SAXAEAVInlineData@23@W4MethodIdentifier@CordzUpdateTracker@23@_J@Z ?Trans@Mutex@absl@@AEAAXPEBUMuHowS@2@@Z ?Trunc@absl@@YA?AVDuration@1@V21@0@Z - ?TryLock@Mutex@absl@@QEAA_NXZ ?TryLockSlow@Mutex@absl@@AEAA_NXZ ?TryNewCRC32AcceleratedX86ARMCombined@crc_internal@absl@@YAPEAVCRCImpl@12@XZ ?TryParse@FlagImpl@flags_internal@absl@@AEBA?AV?$unique_ptr@XUDynValueDeleter@flags_internal@absl@@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@56@AEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@56@@Z @@ -1265,7 +1260,6 @@ EXPORTS ?UnimplementedError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?UnknownError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?Unlock@CordzInfo@cord_internal@absl@@QEAAXXZ - ?Unlock@Mutex@absl@@QEAAXXZ ?UnlockSlow@Mutex@absl@@AEAAXPEAUSynchWaitParams@2@@Z ?Unparse@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@F@Z ?Unparse@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@G@Z @@ -1344,6 +1338,7 @@ EXPORTS ?__throw_length_error@?$vector@UUnrecognizedFlag@absl@@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@@__Cr@std@@CAXXZ ?__throw_length_error@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@__Cr@std@@CAXXZ ?__throw_length_error@?$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@@CAXXZ + ?assert_is_full@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@@AEBAXPEBD@Z ?begin@?$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@@QEAA?AViterator@123@XZ ?clear@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXXZ ?clear@?$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@@QEAAXXZ @@ -1356,7 +1351,6 @@ EXPORTS ?effective_impl@time_zone@cctz@time_internal@absl@@AEBAAEBVImpl@1234@XZ ?end@?$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@@QEAA?AViterator@123@XZ ?engines@?1??CrcAndCopy@CrcMemcpy@crc_internal@absl@@SA?AVcrc32c_t@4@PEIAXPEIBX_KV54@_N@Z@4UArchSpecificEngines@234@B - ?find_first_non_full@container_internal@absl@@YA?AUFindInfo@12@AEBVCommonFields@12@_K@Z ?fixed_time_zone@cctz@time_internal@absl@@YA?AVtime_zone@123@AEBV?$duration@_JV?$ratio@$00$00@__Cr@std@@@chrono@__Cr@std@@@Z ?format@detail@cctz@time_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBV567@AEBV?$time_point@Vsystem_clock@chrono@__Cr@std@@V?$duration@_JV?$ratio@$00$00@__Cr@std@@@234@@chrono@67@AEBV?$duration@_JV?$ratio@$00$0DINHOKEMGIAAA@@__Cr@std@@@967@AEBVtime_zone@234@@Z ?from_chars@absl@@YA?AUfrom_chars_result@1@PEBD0AEAMW4chars_format@1@@Z @@ -1366,6 +1360,8 @@ EXPORTS ?kDefaultIterControl@container_internal@absl@@3W4ctrl_t@12@A ?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 ?local_time_zone@cctz@time_internal@absl@@YA?AVtime_zone@123@XZ + ?lock@Mutex@absl@@QEAAXXZ + ?lock_shared@Mutex@absl@@QEAAXXZ ?lookup@time_zone@cctz@time_internal@absl@@QEBA?AUabsolute_lookup@1234@AEBV?$time_point@Vsystem_clock@chrono@__Cr@std@@V?$duration@_JV?$ratio@$00$00@__Cr@std@@@234@@chrono@__Cr@std@@@Z ?lookup@time_zone@cctz@time_internal@absl@@QEBA?AUcivil_lookup@1234@AEBV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@detail@234@@Z ?memcasecmp@strings_internal@absl@@YAHPEBD0_K@Z @@ -1412,6 +1408,10 @@ EXPORTS ?stream@OstreamView@LogMessage@log_internal@absl@@QEAAAEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ ?tag@Rep@InlineData@cord_internal@absl@@QEBACXZ ?transfer_unprobed_elements_to_next_capacity_fn@?$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@@CAXAEAVCommonFields@23@PEBW4ctrl_t@23@PEAX2P6AX2E_K3@Z@Z + ?try_lock@Mutex@absl@@QEAA_NXZ + ?try_lock_shared@Mutex@absl@@QEAA_NXZ + ?unlock@Mutex@absl@@QEAAXXZ + ?unlock_shared@Mutex@absl@@QEAAXXZ ?utc_time_zone@cctz@time_internal@absl@@YA?AVtime_zone@123@XZ ?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 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 dd92e30de9..11b95e8a21 100644 --- a/naiveproxy/src/third_party/abseil-cpp/symbols_x86_dbg.def +++ b/naiveproxy/src/third_party/abseil-cpp/symbols_x86_dbg.def @@ -5,14 +5,14 @@ EXPORTS ??$?0$$CBUCordRep@cord_internal@absl@@@Hex@absl@@QAE@PBUCordRep@cord_internal@1@W4PadSpec@1@@Z ??$?0$$CBVFormatArgImpl@str_format_internal@absl@@$$CBV012@@?$Span@$$CBVFormatArgImpl@str_format_internal@absl@@@absl@@QAE@V?$initializer_list@VFormatArgImpl@str_format_internal@absl@@@std@@@Z ??$?0$$CB_W$0A@@VoidPtr@str_format_internal@absl@@QAE@PB_W@Z - ??$?0$$QAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V$$Z$0A@$$Z$S@?$pair@$$CBV?$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@@AAE@Upiecewise_construct_t@12@AAV?$tuple@$$QAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@AAV?$tuple@$$V@12@U?$__tuple_indices@$0A@@12@U?$__tuple_indices@$S@12@@Z + ??$?0$$QAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V$$Z$0A@$$Z$S@?$pair@$$CBV?$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@@AAE@Upiecewise_construct_t@12@AAV?$tuple@$$QAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@AAV?$tuple@$$V@12@U?$__integer_sequence@I$0A@@12@U?$__integer_sequence@I$S@12@@Z ??$?0$$QAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V@?$pair@$$CBV?$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@@QAE@Upiecewise_construct_t@12@V?$tuple@$$QAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@V?$tuple@$$V@12@@Z - ??$?0$$QAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QAPAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@AAE@Upiecewise_construct_t@12@AAV?$tuple@$$QAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AAV?$tuple@$$QAPAVCommandLineFlag@absl@@@12@U?$__tuple_indices@$0A@@12@3@Z - ??$?0$$QAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QAPAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$tuple@$$QAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QAPAVCommandLineFlag@absl@@@23@@__Cr@std@@AAE@Upiecewise_construct_t@12@AAV?$tuple@$$QAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AAV?$tuple@$$QAPAVCommandLineFlag@absl@@@12@U?$__tuple_indices@$0A@@12@3@Z + ??$?0$$QAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QAPAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@AAE@Upiecewise_construct_t@12@AAV?$tuple@$$QAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AAV?$tuple@$$QAPAVCommandLineFlag@absl@@@12@U?$__integer_sequence@I$0A@@12@3@Z + ??$?0$$QAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QAPAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$tuple@$$QAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QAPAVCommandLineFlag@absl@@@23@@__Cr@std@@AAE@Upiecewise_construct_t@12@AAV?$tuple@$$QAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AAV?$tuple@$$QAPAVCommandLineFlag@absl@@@12@U?$__integer_sequence@I$0A@@12@3@Z ??$?0$$QAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QAPAVCommandLineFlag@absl@@@?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@QAE@Upiecewise_construct_t@12@V?$tuple@$$QAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$tuple@$$QAPAVCommandLineFlag@absl@@@12@@Z ??$?0$$QAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QAPAVCommandLineFlag@absl@@@?$pair@V?$tuple@$$QAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QAPAVCommandLineFlag@absl@@@23@@__Cr@std@@QAE@Upiecewise_construct_t@12@V?$tuple@$$QAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$tuple@$$QAPAVCommandLineFlag@absl@@@12@@Z - ??$?0$$QBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QAPAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@AAE@Upiecewise_construct_t@12@AAV?$tuple@$$QBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AAV?$tuple@$$QAPAVCommandLineFlag@absl@@@12@U?$__tuple_indices@$0A@@12@3@Z - ??$?0$$QBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QAPAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$tuple@$$QBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QAPAVCommandLineFlag@absl@@@23@@__Cr@std@@AAE@Upiecewise_construct_t@12@AAV?$tuple@$$QBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AAV?$tuple@$$QAPAVCommandLineFlag@absl@@@12@U?$__tuple_indices@$0A@@12@3@Z + ??$?0$$QBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QAPAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@AAE@Upiecewise_construct_t@12@AAV?$tuple@$$QBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AAV?$tuple@$$QAPAVCommandLineFlag@absl@@@12@U?$__integer_sequence@I$0A@@12@3@Z + ??$?0$$QBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QAPAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$tuple@$$QBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QAPAVCommandLineFlag@absl@@@23@@__Cr@std@@AAE@Upiecewise_construct_t@12@AAV?$tuple@$$QBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AAV?$tuple@$$QAPAVCommandLineFlag@absl@@@12@U?$__integer_sequence@I$0A@@12@3@Z ??$?0$$QBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QAPAVCommandLineFlag@absl@@@?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@QAE@Upiecewise_construct_t@12@V?$tuple@$$QBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$tuple@$$QAPAVCommandLineFlag@absl@@@12@@Z ??$?0$$QBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$Z$$QAPAVCommandLineFlag@absl@@@?$pair@V?$tuple@$$QBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QAPAVCommandLineFlag@absl@@@23@@__Cr@std@@QAE@Upiecewise_construct_t@12@V?$tuple@$$QBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$tuple@$$QAPAVCommandLineFlag@absl@@@12@@Z ??$?0$$T@?$Storage@PAPAUCordRep@cord_internal@absl@@$00U?$StorageTag@V?$allocator@PAUCordRep@cord_internal@absl@@@__Cr@std@@PAPAUCordRep@cord_internal@absl@@@internal_compressed_tuple@container_internal@3@$0A@@internal_compressed_tuple@container_internal@absl@@QAE@Uin_place_t@__Cr@std@@$$QA$$T@Z @@ -55,10 +55,6 @@ EXPORTS ??$?0$00X@?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QAE@PAVZoneInfoSource@cctz@time_internal@absl@@@Z ??$?0$00X@?$unique_ptr@XUDynValueDeleter@flags_internal@absl@@@__Cr@std@@QAE@$$T@Z ??$?0$00X@?$unique_ptr@XUDynValueDeleter@flags_internal@absl@@@__Cr@std@@QAE@PAX$$QAUDynValueDeleter@flags_internal@absl@@@Z - ??$?0$0A@$$Z$$QAPAVCommandLineFlag@absl@@$$Z$S$$Z$$V$$ZPAV01@@?$__tuple_impl@U?$__tuple_indices@$0A@@__Cr@std@@$$QAPAVCommandLineFlag@absl@@@__Cr@std@@QAE@U?$__tuple_indices@$0A@@12@U?$__tuple_types@$$QAPAVCommandLineFlag@absl@@@12@U?$__tuple_indices@$S@12@U?$__tuple_types@$$V@12@$$QAPAVCommandLineFlag@absl@@@Z - ??$?0$0A@$$ZABQAVCommandLineFlag@absl@@$$Z$S$$Z$$V$$ZABQAV01@@?$__tuple_impl@U?$__tuple_indices@$0A@@__Cr@std@@ABQAVCommandLineFlag@absl@@@__Cr@std@@QAE@U?$__tuple_indices@$0A@@12@U?$__tuple_types@ABQAVCommandLineFlag@absl@@@12@U?$__tuple_indices@$S@12@U?$__tuple_types@$$V@12@ABQAVCommandLineFlag@absl@@@Z - ??$?0$0A@$00$$ZAAPAVCommandLineFlag@absl@@AA_N$$Z$S$$Z$$V$$ZAAPAV01@AA_N@?$__tuple_impl@U?$__tuple_indices@$0A@$00@__Cr@std@@AAPAVCommandLineFlag@absl@@AA_N@__Cr@std@@QAE@U?$__tuple_indices@$0A@$00@12@U?$__tuple_types@AAPAVCommandLineFlag@absl@@AA_N@12@U?$__tuple_indices@$S@12@U?$__tuple_types@$$V@12@AAPAVCommandLineFlag@absl@@AA_N@Z - ??$?0$0A@$00$$ZPAVCommandLineFlag@absl@@_N$$Z$S$$Z$$V$$ZAAPAV01@AA_N@?$__tuple_impl@U?$__tuple_indices@$0A@$00@__Cr@std@@PAVCommandLineFlag@absl@@_N@__Cr@std@@QAE@U?$__tuple_indices@$0A@$00@12@U?$__tuple_types@PAVCommandLineFlag@absl@@_N@12@U?$__tuple_indices@$S@12@U?$__tuple_types@$$V@12@AAPAVCommandLineFlag@absl@@AA_N@Z ??$?0AAI@?$Storage@I$0A@U?$StorageTag@IV?$allocator@D@__Cr@std@@@internal_compressed_tuple@container_internal@absl@@$0A@@internal_compressed_tuple@container_internal@absl@@QAE@Uin_place_t@__Cr@std@@AAI@Z ??$?0AAIABV?$allocator@D@__Cr@std@@$00@?$CompressedTuple@IV?$allocator@D@__Cr@std@@@container_internal@absl@@QAE@AAIABV?$allocator@D@__Cr@std@@@Z ??$?0AAIABV?$allocator@D@__Cr@std@@@?$CompressedTupleImpl@V?$CompressedTuple@IV?$allocator@D@__Cr@std@@@container_internal@absl@@U?$integer_sequence@I$0A@$00@__Cr@std@@$00@internal_compressed_tuple@container_internal@absl@@QAE@Uin_place_t@__Cr@std@@AAIABV?$allocator@D@56@@Z @@ -76,6 +72,8 @@ EXPORTS ??$?0AAPAVCommandLineFlag@absl@@$0A@@?$__tuple_leaf@$0A@AAPAVCommandLineFlag@absl@@$0A@@__Cr@std@@QAE@AAPAVCommandLineFlag@absl@@@Z ??$?0AAPAVCommandLineFlag@absl@@$0A@@?$__tuple_leaf@$0A@PAVCommandLineFlag@absl@@$0A@@__Cr@std@@QAE@AAPAVCommandLineFlag@absl@@@Z ??$?0AAPAVCommandLineFlag@absl@@AA_N$0A@@?$tuple@PAVCommandLineFlag@absl@@_N@__Cr@std@@QAE@AAPAVCommandLineFlag@absl@@AA_N@Z + ??$?0AAPAVCommandLineFlag@absl@@AA_N@?$__tuple_impl@U?$__integer_sequence@I$0A@$00@__Cr@std@@AAPAVCommandLineFlag@absl@@AA_N@__Cr@std@@QAE@U__forward_args@12@AAPAVCommandLineFlag@absl@@AA_N@Z + ??$?0AAPAVCommandLineFlag@absl@@AA_N@?$__tuple_impl@U?$__integer_sequence@I$0A@$00@__Cr@std@@PAVCommandLineFlag@absl@@_N@__Cr@std@@QAE@U__forward_args@12@AAPAVCommandLineFlag@absl@@AA_N@Z ??$?0AAPBUPrefixCrc@CrcCordState@crc_internal@absl@@PAU0123@$0A@@?$pair@PBUPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@@__Cr@std@@QAE@AAPBUPrefixCrc@CrcCordState@crc_internal@absl@@$$QAPAU3456@@Z ??$?0AAUraw_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@@ABV234@@Z@@?$__temp_value@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@@QAE@AAV?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AAUraw_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@@12@ABV678@@Z@@Z ??$?0AAV?$__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@@12@$0A@@?$pair@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@@__Cr@std@@QAE@AAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@12@$$QAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@12@@Z @@ -93,6 +91,7 @@ EXPORTS ??$?0AAY0BM@$$CBD$0A@@?$NoDestructor@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@absl@@QAE@AAY0BM@$$CBD@Z ??$?0AAY0BM@$$CBD@PlacementImpl@?$NoDestructor@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@absl@@QAE@AAY0BM@$$CBD@Z ??$?0ABQAVCommandLineFlag@absl@@$0A@@?$__tuple_leaf@$0A@ABQAVCommandLineFlag@absl@@$0A@@__Cr@std@@QAE@ABQAVCommandLineFlag@absl@@@Z + ??$?0ABQAVCommandLineFlag@absl@@@?$__tuple_impl@U?$__integer_sequence@I$0A@@__Cr@std@@ABQAVCommandLineFlag@absl@@@__Cr@std@@QAE@U__forward_args@12@ABQAVCommandLineFlag@absl@@@Z ??$?0ABV?$allocator@D@__Cr@std@@@?$Storage@V?$allocator@D@__Cr@std@@$00U?$StorageTag@IV?$allocator@D@__Cr@std@@@internal_compressed_tuple@container_internal@absl@@$00@internal_compressed_tuple@container_internal@absl@@QAE@Uin_place_t@__Cr@std@@ABV?$allocator@D@56@@Z ??$?0ABV?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@?$Storage@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@$0A@U?$StorageTag@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@I@internal_compressed_tuple@container_internal@absl@@$00@internal_compressed_tuple@container_internal@absl@@QAE@Uin_place_t@__Cr@std@@ABV?$allocator@UPayload@status_internal@absl@@@56@@Z ??$?0ABV?$allocator@UPayload@status_internal@absl@@@__Cr@std@@I$00@?$CompressedTuple@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@I@container_internal@absl@@QAE@ABV?$allocator@UPayload@status_internal@absl@@@__Cr@std@@$$QAI@Z @@ -100,11 +99,11 @@ EXPORTS ??$?0ABV?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@@?$Storage@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@$0A@U?$StorageTag@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@I@internal_compressed_tuple@container_internal@absl@@$00@internal_compressed_tuple@container_internal@absl@@QAE@Uin_place_t@__Cr@std@@ABV?$allocator@VFormatArgImpl@str_format_internal@absl@@@56@@Z ??$?0ABV?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@I$00@?$CompressedTuple@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@I@container_internal@absl@@QAE@ABV?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@$$QAI@Z ??$?0ABV?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@I@?$CompressedTupleImpl@V?$CompressedTuple@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@I@container_internal@absl@@U?$integer_sequence@I$0A@$00@__Cr@std@@$00@internal_compressed_tuple@container_internal@absl@@QAE@Uin_place_t@__Cr@std@@ABV?$allocator@VFormatArgImpl@str_format_internal@absl@@@56@$$QAI@Z - ??$?0ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V$$Z$0A@$$Z$S@?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@AAE@Upiecewise_construct_t@12@AAV?$tuple@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@AAV?$tuple@$$V@12@U?$__tuple_indices@$0A@@12@U?$__tuple_indices@$S@12@@Z - ??$?0ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V$$Z$0A@$$Z$S@?$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@@AAE@Upiecewise_construct_t@12@AAV?$tuple@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@AAV?$tuple@$$V@12@U?$__tuple_indices@$0A@@12@U?$__tuple_indices@$S@12@@Z + ??$?0ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V$$Z$0A@$$Z$S@?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@AAE@Upiecewise_construct_t@12@AAV?$tuple@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@AAV?$tuple@$$V@12@U?$__integer_sequence@I$0A@@12@U?$__integer_sequence@I$S@12@@Z + ??$?0ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V$$Z$0A@$$Z$S@?$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@@AAE@Upiecewise_construct_t@12@AAV?$tuple@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@AAV?$tuple@$$V@12@U?$__integer_sequence@I$0A@@12@U?$__integer_sequence@I$S@12@@Z ??$?0ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V@?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@QAE@Upiecewise_construct_t@12@V?$tuple@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@V?$tuple@$$V@12@@Z ??$?0ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@$$Z$$V@?$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@@QAE@Upiecewise_construct_t@12@V?$tuple@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@V?$tuple@$$V@12@@Z - ??$?0ABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$ZABQAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$tuple@ABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@ABQAVCommandLineFlag@absl@@@23@@__Cr@std@@AAE@Upiecewise_construct_t@12@AAV?$tuple@ABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AAV?$tuple@ABQAVCommandLineFlag@absl@@@12@U?$__tuple_indices@$0A@@12@3@Z + ??$?0ABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$ZABQAVCommandLineFlag@absl@@$$Z$0A@$$Z$0A@@?$pair@V?$tuple@ABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@ABQAVCommandLineFlag@absl@@@23@@__Cr@std@@AAE@Upiecewise_construct_t@12@AAV?$tuple@ABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@AAV?$tuple@ABQAVCommandLineFlag@absl@@@12@U?$__integer_sequence@I$0A@@12@3@Z ??$?0ABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@$$ZABQAVCommandLineFlag@absl@@@?$pair@V?$tuple@ABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@ABQAVCommandLineFlag@absl@@@23@@__Cr@std@@QAE@Upiecewise_construct_t@12@V?$tuple@ABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$tuple@ABQAVCommandLineFlag@absl@@@12@@Z ??$?0D@?$allocator@U?$AlignedType@$03@container_internal@absl@@@__Cr@std@@QAE@ABV?$allocator@D@12@@Z ??$?0D@?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@QAE@ABV?$allocator@D@12@@Z @@ -130,6 +129,7 @@ EXPORTS ??$?0PAUraw_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@@ABV234@@Z@PAU0?1???R1234@QBE?AV567@0@Z@$0A@@?$pair@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@PAU1?1???R2345@QBE?AV678@0@Z@@__Cr@std@@QAE@$$QAPAUraw_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@@12@ABV567@@Z@1@Z ??$?0PAVCommandLineFlag@absl@@$0A@@?$__tuple_leaf@$0A@$$QAPAVCommandLineFlag@absl@@$0A@@__Cr@std@@QAE@$$QAPAVCommandLineFlag@absl@@@Z ??$?0PAVCommandLineFlag@absl@@$0A@@?$tuple@$$QAPAVCommandLineFlag@absl@@@__Cr@std@@QAE@$$QAPAVCommandLineFlag@absl@@@Z + ??$?0PAVCommandLineFlag@absl@@@?$__tuple_impl@U?$__integer_sequence@I$0A@@__Cr@std@@$$QAPAVCommandLineFlag@absl@@@__Cr@std@@QAE@U__forward_args@12@$$QAPAVCommandLineFlag@absl@@@Z ??$?0PAW4ctrl_t@container_internal@absl@@AAPAX$0A@@?$pair@PAW4ctrl_t@container_internal@absl@@PAX@__Cr@std@@QAE@$$QAPAW4ctrl_t@container_internal@absl@@AAPAX@Z ??$?0PAW4ctrl_t@container_internal@absl@@ABQAX$0A@@?$pair@PAW4ctrl_t@container_internal@absl@@PAX@__Cr@std@@QAE@$$QAPAW4ctrl_t@container_internal@absl@@ABQAX@Z ??$?0PAW4ctrl_t@container_internal@absl@@PAX$0A@@?$pair@PAW4ctrl_t@container_internal@absl@@PAX@__Cr@std@@QAE@$$QAPAW4ctrl_t@container_internal@absl@@$$QAPAX@Z @@ -190,9 +190,7 @@ EXPORTS ??$?0V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QAEXXZ@X@?$function@$$A6AXAAVCommandLineFlag@absl@@@Z@__Cr@std@@QAE@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QAEXXZ@@Z ??$?0V?$InlinedVector@VFormatArgImpl@str_format_internal@absl@@$03V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@@absl@@XV01@H@?$Span@$$CBVFormatArgImpl@str_format_internal@absl@@@absl@@QAE@ABV?$InlinedVector@VFormatArgImpl@str_format_internal@absl@@$03V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@@1@@Z ??$?0V?$Span@D@absl@@XV01@$0A@@?$Span@$$CBD@absl@@QAE@ABV?$Span@D@1@@Z - ??$?0V?$Span@D@absl@@XV01@$0A@@?$Span@D@absl@@QAE@AAV01@@Z ??$?0V?$Span@I@absl@@XV01@$0A@@?$Span@$$CBI@absl@@QAE@ABV?$Span@I@1@@Z - ??$?0V?$Span@I@absl@@XV01@$0A@@?$Span@I@absl@@QAE@AAV01@@Z ??$?0V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@V012@$0A@@?$pair@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@V123@@__Cr@std@@QAE@$$QAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@12@0@Z ??$?0V?$__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@@12@$0A@@?$pair@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@@__Cr@std@@QAE@$$QAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@12@$$QAV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@12@@Z ??$?0V?$__hash_iterator@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@AA_N$0A@@?$pair@V?$__hash_iterator@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@_N@__Cr@std@@QAE@$$QAV?$__hash_iterator@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@12@AA_N@Z @@ -539,8 +537,6 @@ EXPORTS ??$GetData@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@span_internal@absl@@YAPBDABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??$GetData@U?$array@D$0DKJI@@__Cr@std@@@span_internal@absl@@YAPADAAU?$array@D$0DKJI@@__Cr@std@@@Z ??$GetData@V?$InlinedVector@PAVLogSink@absl@@$0BA@V?$allocator@PAVLogSink@absl@@@__Cr@std@@@absl@@@span_internal@absl@@YAPAPAVLogSink@1@AAV?$InlinedVector@PAVLogSink@absl@@$0BA@V?$allocator@PAVLogSink@absl@@@__Cr@std@@@1@@Z - ??$GetData@V?$Span@D@absl@@@span_internal@absl@@YAPADAAV?$Span@D@1@@Z - ??$GetData@V?$Span@I@absl@@@span_internal@absl@@YAPAIAAV?$Span@I@1@@Z ??$GetData@V?$vector@PAVLogSink@absl@@V?$allocator@PAVLogSink@absl@@@__Cr@std@@@__Cr@std@@@span_internal@absl@@YAPAPAVLogSink@1@AAV?$vector@PAVLogSink@absl@@V?$allocator@PAVLogSink@absl@@@__Cr@std@@@__Cr@std@@@Z ??$GetDataImpl@$$CBV?$InlinedVector@VFormatArgImpl@str_format_internal@absl@@$03V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@@absl@@@span_internal@absl@@YAPBVFormatArgImpl@str_format_internal@1@ABV?$InlinedVector@VFormatArgImpl@str_format_internal@absl@@$03V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@@1@D@Z ??$GetDataImpl@$$CBV?$Span@D@absl@@@span_internal@absl@@YAPADABV?$Span@D@1@D@Z @@ -548,8 +544,6 @@ EXPORTS ??$GetDataImpl@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@span_internal@absl@@YAPBDABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@D@Z ??$GetDataImpl@U?$array@D$0DKJI@@__Cr@std@@@span_internal@absl@@YAPADAAU?$array@D$0DKJI@@__Cr@std@@D@Z ??$GetDataImpl@V?$InlinedVector@PAVLogSink@absl@@$0BA@V?$allocator@PAVLogSink@absl@@@__Cr@std@@@absl@@@span_internal@absl@@YAPAPAVLogSink@1@AAV?$InlinedVector@PAVLogSink@absl@@$0BA@V?$allocator@PAVLogSink@absl@@@__Cr@std@@@1@D@Z - ??$GetDataImpl@V?$Span@D@absl@@@span_internal@absl@@YAPADAAV?$Span@D@1@D@Z - ??$GetDataImpl@V?$Span@I@absl@@@span_internal@absl@@YAPAIAAV?$Span@I@1@D@Z ??$GetDataImpl@V?$vector@PAVLogSink@absl@@V?$allocator@PAVLogSink@absl@@@__Cr@std@@@__Cr@std@@@span_internal@absl@@YAPAPAVLogSink@1@AAV?$vector@PAVLogSink@absl@@V?$allocator@PAVLogSink@absl@@@__Cr@std@@@__Cr@std@@D@Z ??$GetFlag@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@@@absl@@YA?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@@ABV?$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@0@@Z ??$GrowSooTableToNextCapacityAndPrepareInsert@$00$00@container_internal@absl@@YAIAAVCommonFields@01@ABUPolicyFunctions@01@V?$FunctionRef@$$A6AII@Z@1@_N@Z @@ -844,8 +838,8 @@ EXPORTS ??$__at@P6AI$$QAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YAIUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@Z$03$$V@__base@__visitation@__variant_detail@__Cr@std@@CA$$QA_PABU?$__farray@P6AI$$QAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YAIUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@Z$03@34@I@Z ??$__at@P6AI$$QAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YAIUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@Z@__base@__visitation@__variant_detail@__Cr@std@@CAABQ6AI$$QAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YAIUStructuredProtoField@34@@Z@@__variant@1234@AAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@234@@ZABQ6AI01@Z@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 - ??$__call_impl@V?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QAEXXZ@$$A6AXAAVCommandLineFlag@5@@Z@__function@__Cr@std@@@?$__policy_invoker@$$A6AXAAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@CAXPBT__policy_storage@123@AAVCommandLineFlag@absl@@@Z - ??$__choose_policy@V?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QAEXXZ@$$A6AXAAVCommandLineFlag@5@@Z@__function@__Cr@std@@@__policy@__function@__Cr@std@@CAPBU0123@U?$integral_constant@_N$00@23@@Z + ??$__call_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QAEXXZ@@?$__policy_func@$$A6AXAAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@CAXPBT__policy_storage@123@AAVCommandLineFlag@absl@@@Z + ??$__choose_policy@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QAEXXZ@@__policy@__function@__Cr@std@@CAPBU0123@U?$integral_constant@_N$00@23@@Z ??$__constexpr_memmove@PAPBVImpl@time_zone@cctz@time_internal@absl@@PAPBV12345@@__Cr@std@@YAPAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV23456@0W4__element_count@01@@Z ??$__constexpr_memmove@PAUPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@@__Cr@std@@YAPAPAUPrefixCrc@CrcCordState@crc_internal@absl@@PAPAU2345@0W4__element_count@01@@Z ??$__constexpr_memmove@PAVLogSink@absl@@PAV12@@__Cr@std@@YAPAPAVLogSink@absl@@PAPAV23@0W4__element_count@01@@Z @@ -905,7 +899,7 @@ EXPORTS ??$__construct_node@ABUpiecewise_construct_t@__Cr@std@@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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AAE?AV?$unique_ptr@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@@V?$__tree_node_destructor@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@@@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 ??$__construct_node@ABUpiecewise_construct_t@__Cr@std@@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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__Cr@std@@AAE?AV?$unique_ptr@V?$__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@__Cr@std@@V?$__tree_node_destructor@V?$allocator@V?$__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@__Cr@std@@@__Cr@std@@@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 ??$__construct_node_hash@ABQBUCordRep@cord_internal@absl@@$$V@?$__hash_table@PBUCordRep@cord_internal@absl@@U?$hash@PBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PBUCordRep@cord_internal@absl@@@56@V?$allocator@PBUCordRep@cord_internal@absl@@@56@@__Cr@std@@AAE?AV?$unique_ptr@U?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@@23@@12@IABQBUCordRep@cord_internal@absl@@@Z - ??$__construct_node_hash@ABUpiecewise_construct_t@__Cr@std@@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@@AAE?AV?$unique_ptr@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@@V?$__hash_node_destructor@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@@@23@@12@IABUpiecewise_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 + ??$__construct_node_hash@ABUpiecewise_construct_t@__Cr@std@@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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AAE?AV?$unique_ptr@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@@V?$__hash_node_destructor@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@@@23@@12@IABUpiecewise_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 ??$__copy@PBUPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@PAU1234@@__Cr@std@@YA?AU?$pair@PBUPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@@01@PBUPrefixCrc@CrcCordState@crc_internal@absl@@0PAU3456@@Z ??$__copy@PBUPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@__Cr@std@@@__Cr@std@@YA?AU?$pair@PBUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@__Cr@std@@@01@PBUPrefixCrc@CrcCordState@crc_internal@absl@@0V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@01@@Z ??$__copy@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@V123@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@23@@__Cr@std@@YA?AU?$pair@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@@01@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@01@0V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@01@@Z @@ -931,14 +925,15 @@ EXPORTS ??$__copy_trivial_impl@PAVLogSink@absl@@PAV12@@__Cr@std@@YA?AU?$pair@PAPAVLogSink@absl@@PAPAV12@@01@PAPAVLogSink@absl@@00@Z ??$__copy_trivial_impl@UTransition@cctz@time_internal@absl@@U1234@@__Cr@std@@YA?AU?$pair@PAUTransition@cctz@time_internal@absl@@PAU1234@@01@PAUTransition@cctz@time_internal@absl@@00@Z ??$__copy_trivial_impl@UTransitionType@cctz@time_internal@absl@@U1234@@__Cr@std@@YA?AU?$pair@PAUTransitionType@cctz@time_internal@absl@@PAU1234@@01@PAUTransitionType@cctz@time_internal@absl@@00@Z - ??$__create@V?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QAEXXZ@$$A6AXAAVCommandLineFlag@5@@Z@__function@__Cr@std@@@?$__policy_invoker@$$A6AXAAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@SA?AU0123@XZ - ??$__create@V?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QAEXXZ@$$A6AXAAVCommandLineFlag@5@@Z@__function@__Cr@std@@@__policy@__function@__Cr@std@@SAPBU0123@XZ + ??$__create@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QAEXXZ@@__policy@__function@__Cr@std@@SAPBU0123@XZ + ??$__cxx_atomic_compare_exchange_strong@PAUArena@LowLevelAlloc@base_internal@absl@@@__Cr@std@@YA_NPAU?$__cxx_atomic_base_impl@PAUArena@LowLevelAlloc@base_internal@absl@@@01@PAPAUArena@LowLevelAlloc@base_internal@absl@@PAU3456@W4memory_order@01@3@Z ??$__cxx_atomic_compare_exchange_strong@PAVTimeZone@absl@@@__Cr@std@@YA_NPAU?$__cxx_atomic_base_impl@PAVTimeZone@absl@@@01@PAPAVTimeZone@absl@@PAV34@W4memory_order@01@3@Z ??$__cxx_atomic_compare_exchange_strong@PAVVLogSite@log_internal@absl@@@__Cr@std@@YA_NPAU?$__cxx_atomic_base_impl@PAVVLogSite@log_internal@absl@@@01@PAPAVVLogSite@log_internal@absl@@PAV345@W4memory_order@01@3@Z ??$__cxx_atomic_compare_exchange_weak@PAUHashtablezInfo@container_internal@absl@@@__Cr@std@@YA_NPAU?$__cxx_atomic_base_impl@PAUHashtablezInfo@container_internal@absl@@@01@PAPAUHashtablezInfo@container_internal@absl@@PAU345@W4memory_order@01@3@Z ??$__cxx_atomic_compare_exchange_weak@PAVVLogSite@log_internal@absl@@@__Cr@std@@YA_NPAU?$__cxx_atomic_base_impl@PAVVLogSite@log_internal@absl@@@01@PAPAVVLogSite@log_internal@absl@@PAV345@W4memory_order@01@3@Z ??$__cxx_atomic_exchange@PAVVLogSite@log_internal@absl@@@__Cr@std@@YAPAVVLogSite@log_internal@absl@@PAU?$__cxx_atomic_base_impl@PAVVLogSite@log_internal@absl@@@01@PAV234@W4memory_order@01@@Z ??$__cxx_atomic_load@P6AXABUHashtablezInfo@container_internal@absl@@@Z@__Cr@std@@YAP6AXABUHashtablezInfo@container_internal@absl@@@ZPBU?$__cxx_atomic_base_impl@P6AXABUHashtablezInfo@container_internal@absl@@@Z@01@W4memory_order@01@@Z + ??$__cxx_atomic_load@PAUArena@LowLevelAlloc@base_internal@absl@@@__Cr@std@@YAPAUArena@LowLevelAlloc@base_internal@absl@@PBU?$__cxx_atomic_base_impl@PAUArena@LowLevelAlloc@base_internal@absl@@@01@W4memory_order@01@@Z ??$__cxx_atomic_load@PAUHashtablezInfo@container_internal@absl@@@__Cr@std@@YAPAUHashtablezInfo@container_internal@absl@@PBU?$__cxx_atomic_base_impl@PAUHashtablezInfo@container_internal@absl@@@01@W4memory_order@01@@Z ??$__cxx_atomic_load@PAVCordzHandle@cord_internal@absl@@@__Cr@std@@YAPAVCordzHandle@cord_internal@absl@@PBU?$__cxx_atomic_base_impl@PAVCordzHandle@cord_internal@absl@@@01@W4memory_order@01@@Z ??$__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 @@ -995,7 +990,7 @@ EXPORTS ??$__distance@V?$move_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YAHV?$move_iterator@PAUTransition@cctz@time_internal@absl@@@01@0Urandom_access_iterator_tag@01@@Z ??$__distance@V?$move_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YAHV?$move_iterator@PAUTransitionType@cctz@time_internal@absl@@@01@0Urandom_access_iterator_tag@01@@Z ??$__do_rehash@$00@?$__hash_table@PBUCordRep@cord_internal@absl@@U?$hash@PBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PBUCordRep@cord_internal@absl@@@56@V?$allocator@PBUCordRep@cord_internal@absl@@@56@@__Cr@std@@AAEXI@Z - ??$__do_rehash@$00@?$__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@@AAEXI@Z + ??$__do_rehash@$00@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AAEXI@Z ??$__emplace_back_assume_capacity@$$V@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QAEXXZ ??$__emplace_back_assume_capacity@$$V@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QAEXXZ ??$__emplace_back_assume_capacity@AAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@ABV123@AAI@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@__Cr@std@@QAEXAAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@12@ABV312@AAI@Z @@ -1022,9 +1017,11 @@ EXPORTS ??$__emplace_back_slow_path@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@?$vector@UConversionItem@ParsedFormatBase@str_format_internal@absl@@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@@__Cr@std@@AAEPAUConversionItem@ParsedFormatBase@str_format_internal@absl@@$$QAU3456@@Z ??$__emplace_back_slow_path@V?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@@?$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@@AAEPAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@12@$$QAV312@@Z ??$__emplace_back_slow_path@W4Source@UnrecognizedFlag@absl@@AAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$vector@UUnrecognizedFlag@absl@@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@@__Cr@std@@AAEPAUUnrecognizedFlag@absl@@$$QAW4Source@34@AAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@12@@Z + ??$__emplace_unique@ABQBUCordRep@cord_internal@absl@@@?$__hash_table@PBUCordRep@cord_internal@absl@@U?$hash@PBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PBUCordRep@cord_internal@absl@@@56@V?$allocator@PBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QAE?AU?$pair@V?$__hash_iterator@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@_N@12@ABQBUCordRep@cord_internal@absl@@@Z + ??$__emplace_unique_extract_key@ABQBUCordRep@cord_internal@absl@@@?$__hash_table@PBUCordRep@cord_internal@absl@@U?$hash@PBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PBUCordRep@cord_internal@absl@@@56@V?$allocator@PBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QAE?AU?$pair@V?$__hash_iterator@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@_N@12@ABQBUCordRep@cord_internal@absl@@U__extract_key_self_tag@12@@Z ??$__emplace_unique_key_args@PBUCordRep@cord_internal@absl@@ABQBU123@@?$__hash_table@PBUCordRep@cord_internal@absl@@U?$hash@PBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PBUCordRep@cord_internal@absl@@@56@V?$allocator@PBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QAE?AU?$pair@V?$__hash_iterator@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@_N@12@ABQBUCordRep@cord_internal@absl@@0@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@$$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QAEAAPAV?$__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 @@ -1066,13 +1063,6 @@ EXPORTS ??$__invoke_r@XAAV@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QAEXXZ@AAVCommandLineFlag@5@@__Cr@std@@YAXAAV@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QAEXXZ@AAVCommandLineFlag@6@@Z ??$__iter_move@AAPAPAVCommandLineFlag@absl@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QAPAVCommandLineFlag@absl@@AAPAPAV34@@Z ??$__iter_move@AAPAPBVCommandLineFlag@absl@@$0A@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SA$$QAPBVCommandLineFlag@absl@@AAPAPBV34@@Z - ??$__launder@$$CBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YAPBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@01@PBU201@@Z - ??$__launder@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YAPAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@01@PAU201@@Z - ??$__launder@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@YAPAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@01@PAU201@@Z - ??$__launder@URefcountedRep@CrcCordState@crc_internal@absl@@@__Cr@std@@YAPAURefcountedRep@CrcCordState@crc_internal@absl@@PAU2345@@Z - ??$__launder@V?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@absl@@@__Cr@std@@YAPAV?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@absl@@PAV234@@Z - ??$__launder@VFlagRegistry@flags_internal@absl@@@__Cr@std@@YAPAVFlagRegistry@flags_internal@absl@@PAV234@@Z - ??$__launder@VMutex@absl@@@__Cr@std@@YAPAVMutex@absl@@PAV23@@Z ??$__libcpp_allocate@PAPBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@YAPAPAPBVImpl@time_zone@cctz@time_internal@absl@@W4__element_count@01@I@Z ??$__libcpp_allocate@PAU?$__hash_node_base@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@@__Cr@std@@YAPAPAU?$__hash_node_base@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@01@W4__element_count@01@I@Z ??$__libcpp_allocate@PAU?$__hash_node_base@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@@@__Cr@std@@YAPAPAU?$__hash_node_base@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@@@01@W4__element_count@01@I@Z @@ -1125,63 +1115,11 @@ EXPORTS ??$__libcpp_deallocate@V?$__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@__Cr@std@@@__Cr@std@@YAXPAV?$__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@01@W4__element_count@01@I@Z ??$__libcpp_deallocate@V?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@@__Cr@std@@YAXPAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@01@W4__element_count@01@I@Z ??$__libcpp_deallocate@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@YAXPAVFormatArgImpl@str_format_internal@absl@@W4__element_count@01@I@Z - ??$__libcpp_operator_delete@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@YAXPAPAPBVImpl@time_zone@cctz@time_internal@absl@@@Z - ??$__libcpp_operator_delete@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPAPAPBVImpl@time_zone@cctz@time_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PAPAU?$__hash_node_base@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@@__Cr@std@@YAXPAPAU?$__hash_node_base@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@01@@Z - ??$__libcpp_operator_delete@PAPAU?$__hash_node_base@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@W4align_val_t@3@@__Cr@std@@YAXPAPAU?$__hash_node_base@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@01@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PAPAU?$__hash_node_base@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@@@__Cr@std@@YAXPAPAU?$__hash_node_base@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@@@01@@Z - ??$__libcpp_operator_delete@PAPAU?$__hash_node_base@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@@W4align_val_t@3@@__Cr@std@@YAXPAPAU?$__hash_node_base@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@@@01@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PAPAUCordRep@cord_internal@absl@@@__Cr@std@@YAXPAPAUCordRep@cord_internal@absl@@@Z - ??$__libcpp_operator_delete@PAPAUCordRep@cord_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPAPAUCordRep@cord_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@YAXPAPAUPrefixCrc@CrcCordState@crc_internal@absl@@@Z - ??$__libcpp_operator_delete@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPAPAUPrefixCrc@CrcCordState@crc_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PAPAVCommandLineFlag@absl@@@__Cr@std@@YAXPAPAVCommandLineFlag@absl@@@Z - ??$__libcpp_operator_delete@PAPAVCommandLineFlag@absl@@W4align_val_t@std@@@__Cr@std@@YAXPAPAVCommandLineFlag@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@YAXPAPAVCordzHandle@cord_internal@absl@@@Z - ??$__libcpp_operator_delete@PAPAVCordzHandle@cord_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPAPAVCordzHandle@cord_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PAPAVLogSink@absl@@@__Cr@std@@YAXPAPAVLogSink@absl@@@Z - ??$__libcpp_operator_delete@PAPAVLogSink@absl@@W4align_val_t@std@@@__Cr@std@@YAXPAPAVLogSink@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PAPBVCommandLineFlag@absl@@@__Cr@std@@YAXPAPBVCommandLineFlag@absl@@@Z - ??$__libcpp_operator_delete@PAPBVCommandLineFlag@absl@@W4align_val_t@std@@@__Cr@std@@YAXPAPBVCommandLineFlag@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PAPBVCordzHandle@cord_internal@absl@@@__Cr@std@@YAXPAPBVCordzHandle@cord_internal@absl@@@Z - ??$__libcpp_operator_delete@PAPBVCordzHandle@cord_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPAPBVCordzHandle@cord_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PAPBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@YAXPAPBVImpl@time_zone@cctz@time_internal@absl@@@Z - ??$__libcpp_operator_delete@PAPBVImpl@time_zone@cctz@time_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPAPBVImpl@time_zone@cctz@time_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PAU?$AlignedType@$03@container_internal@absl@@@__Cr@std@@YAXPAU?$AlignedType@$03@container_internal@absl@@@Z - ??$__libcpp_operator_delete@PAU?$AlignedType@$03@container_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPAU?$AlignedType@$03@container_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@YAXPAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@01@@Z - ??$__libcpp_operator_delete@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@W4align_val_t@3@@__Cr@std@@YAXPAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@01@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@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@@YAXPAU?$__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@01@@Z - ??$__libcpp_operator_delete@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@@W4align_val_t@3@@__Cr@std@@YAXPAU?$__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@01@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@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@23@PBXPAX2@Z@@__Cr@std@@YAXPAUAlignedSpace@?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@34@PBXPAX2@Z@@Z - ??$__libcpp_operator_delete@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@23@PBXPAX2@Z@W4align_val_t@std@@@__Cr@std@@YAXPAUAlignedSpace@?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@34@PBXPAX2@Z@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@YAXPAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@Z - ??$__libcpp_operator_delete@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPAUConversionItem@ParsedFormatBase@str_format_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PAUPayload@status_internal@absl@@@__Cr@std@@YAXPAUPayload@status_internal@absl@@@Z - ??$__libcpp_operator_delete@PAUPayload@status_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPAUPayload@status_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@YAXPAUPrefixCrc@CrcCordState@crc_internal@absl@@@Z - ??$__libcpp_operator_delete@PAUPrefixCrc@CrcCordState@crc_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPAUPrefixCrc@CrcCordState@crc_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@YAXPAUTransition@cctz@time_internal@absl@@@Z - ??$__libcpp_operator_delete@PAUTransition@cctz@time_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPAUTransition@cctz@time_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@YAXPAUTransitionType@cctz@time_internal@absl@@@Z - ??$__libcpp_operator_delete@PAUTransitionType@cctz@time_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPAUTransitionType@cctz@time_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PAUUnrecognizedFlag@absl@@@__Cr@std@@YAXPAUUnrecognizedFlag@absl@@@Z - ??$__libcpp_operator_delete@PAUUnrecognizedFlag@absl@@W4align_val_t@std@@@__Cr@std@@YAXPAUUnrecognizedFlag@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PAUViableSubstitution@strings_internal@absl@@@__Cr@std@@YAXPAUViableSubstitution@strings_internal@absl@@@Z - ??$__libcpp_operator_delete@PAUViableSubstitution@strings_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPAUViableSubstitution@strings_internal@absl@@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@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@__Cr@std@@@__Cr@std@@YAXPAV?$__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@01@@Z - ??$__libcpp_operator_delete@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@__Cr@std@@W4align_val_t@3@@__Cr@std@@YAXPAV?$__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@01@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@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@__Cr@std@@@__Cr@std@@YAXPAV?$__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@01@@Z - ??$__libcpp_operator_delete@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@__Cr@std@@W4align_val_t@3@@__Cr@std@@YAXPAV?$__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@01@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@@__Cr@std@@YAXPAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@01@@Z - ??$__libcpp_operator_delete@PAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@W4align_val_t@3@@__Cr@std@@YAXPAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@01@W4align_val_t@1@@Z - ??$__libcpp_operator_delete@PAVFormatArgImpl@str_format_internal@absl@@@__Cr@std@@YAXPAVFormatArgImpl@str_format_internal@absl@@@Z - ??$__libcpp_operator_delete@PAVFormatArgImpl@str_format_internal@absl@@W4align_val_t@std@@@__Cr@std@@YAXPAVFormatArgImpl@str_format_internal@absl@@W4align_val_t@1@@Z ??$__lower_bound@U_ClassicAlgPolicy@__Cr@std@@PBUTransition@cctz@time_internal@absl@@PBU4567@U4567@U__identity@23@UByUnixTime@4567@@__Cr@std@@YAPBUTransition@cctz@time_internal@absl@@PBU2345@0ABU2345@AAUByUnixTime@2345@AAU__identity@01@@Z ??$__lower_bound_bisecting@U_ClassicAlgPolicy@__Cr@std@@PBUTransition@cctz@time_internal@absl@@U4567@U__identity@23@UByUnixTime@4567@@__Cr@std@@YAPBUTransition@cctz@time_internal@absl@@PBU2345@ABU2345@HAAUByUnixTime@2345@AAU__identity@01@@Z ??$__make_exception_guard@V?$_AllocatorDestroyRangeReverse@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@PAUUnrecognizedFlag@absl@@@__Cr@std@@@__Cr@std@@YA?AU?$__exception_guard_noexceptions@V?$_AllocatorDestroyRangeReverse@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@PAUUnrecognizedFlag@absl@@@__Cr@std@@@01@V?$_AllocatorDestroyRangeReverse@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@PAUUnrecognizedFlag@absl@@@01@@Z ??$__make_value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YAIUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@CA?A_P$$QAUBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YAIUStructuredProtoField@78@@Z@@Z - ??$__memberwise_forward_assign@V?$tuple@AAPAVCommandLineFlag@absl@@AA_N@__Cr@std@@V?$tuple@PAVCommandLineFlag@absl@@_N@23@PAVCommandLineFlag@absl@@_N$$Z$0A@$00@__Cr@std@@YAXAAV?$tuple@AAPAVCommandLineFlag@absl@@AA_N@01@$$QAV?$tuple@PAVCommandLineFlag@absl@@_N@01@U?$__tuple_types@PAVCommandLineFlag@absl@@_N@01@U?$__tuple_indices@$0A@$00@01@@Z + ??$__memberwise_forward_assign@V?$tuple@AAPAVCommandLineFlag@absl@@AA_N@__Cr@std@@V?$tuple@PAVCommandLineFlag@absl@@_N@23@PAVCommandLineFlag@absl@@_N$$Z$0A@$00@__Cr@std@@YAXAAV?$tuple@AAPAVCommandLineFlag@absl@@AA_N@01@$$QAV?$tuple@PAVCommandLineFlag@absl@@_N@01@U?$__tuple_types@PAVCommandLineFlag@absl@@_N@01@U?$__integer_sequence@I$0A@$00@01@@Z ??$__move@U_ClassicAlgPolicy@__Cr@std@@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV45678@PAPAPBV45678@@__Cr@std@@YA?AU?$pair@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV12345@@01@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@00@Z ??$__move@U_ClassicAlgPolicy@__Cr@std@@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@PAPAU4567@PAPAU4567@@__Cr@std@@YA?AU?$pair@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@PAPAU1234@@01@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@00@Z ??$__move@U_ClassicAlgPolicy@__Cr@std@@PAPAVLogSink@absl@@PAPAV45@PAPAV45@@__Cr@std@@YA?AU?$pair@PAPAVLogSink@absl@@PAPAV12@@01@PAPAVLogSink@absl@@00@Z @@ -1193,7 +1131,7 @@ EXPORTS ??$__move_backward@U_ClassicAlgPolicy@__Cr@std@@PAUTransitionType@cctz@time_internal@absl@@PAU4567@PAU4567@@__Cr@std@@YA?AU?$pair@PAUTransitionType@cctz@time_internal@absl@@PAU1234@@01@PAUTransitionType@cctz@time_internal@absl@@00@Z ??$__not_null@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QAEXXZ@@__function@__Cr@std@@YA_NABV@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QAEXXZ@@Z ??$__rehash@$00@?$__hash_table@PBUCordRep@cord_internal@absl@@U?$hash@PBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PBUCordRep@cord_internal@absl@@@56@V?$allocator@PBUCordRep@cord_internal@absl@@@56@@__Cr@std@@AAEXI@Z - ??$__rehash@$00@?$__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@@AAEXI@Z + ??$__rehash@$00@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AAEXI@Z ??$__rewrap_iter@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV12345@U?$__unwrap_iter_impl@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@$00@__Cr@std@@@__Cr@std@@YAPAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV23456@0@Z ??$__rewrap_iter@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@PAPAU1234@U?$__unwrap_iter_impl@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@$00@__Cr@std@@@__Cr@std@@YAPAPAUPrefixCrc@CrcCordState@crc_internal@absl@@PAPAU2345@0@Z ??$__rewrap_iter@PAPAVLogSink@absl@@PAPAV12@U?$__unwrap_iter_impl@PAPAVLogSink@absl@@$00@__Cr@std@@@__Cr@std@@YAPAPAVLogSink@absl@@PAPAV23@0@Z @@ -1479,7 +1417,7 @@ EXPORTS ??$end@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 ??$end@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 ??$find@V?$__wrap_iter@PAPAVLogSink@absl@@@__Cr@std@@PAVLogSink@absl@@@__Cr@std@@YA?AV?$__wrap_iter@PAPAVLogSink@absl@@@01@V201@0ABQAVLogSink@absl@@@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@@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?AV?$__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@@@12@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@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@@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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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?AV?$__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@@@12@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z ??$find@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@@QAE?AViterator@012@ABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??$find@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@@QBE?AVconst_iterator@012@ABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??$find_large@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@@AAE?AViterator@012@ABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@I@Z @@ -1547,8 +1485,6 @@ EXPORTS ??$iter_swap@PAPAVCommandLineFlag@absl@@PAPAV12@@__Cr@std@@YAXPAPAVCommandLineFlag@absl@@0@Z ??$iter_swap@PAPBVCommandLineFlag@absl@@PAPBV12@@?$_IterOps@U_ClassicAlgPolicy@__Cr@std@@@__Cr@std@@SAX$$QAPAPBVCommandLineFlag@absl@@0@Z ??$iter_swap@PAPBVCommandLineFlag@absl@@PAPBV12@@__Cr@std@@YAXPAPBVCommandLineFlag@absl@@0@Z - ??$launder@$$CBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YAPBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@01@PBU201@@Z - ??$launder@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@YAPAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@01@PAU201@@Z ??$launder@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@YAPAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@01@PAU201@@Z ??$launder@URefcountedRep@CrcCordState@crc_internal@absl@@@__Cr@std@@YAPAURefcountedRep@CrcCordState@crc_internal@absl@@PAU2345@@Z ??$launder@V?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@absl@@@__Cr@std@@YAPAV?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@absl@@PAV234@@Z @@ -1739,7 +1675,6 @@ EXPORTS ??0?$__cxx_atomic_impl@PAUHashtablezInfo@container_internal@absl@@U?$__cxx_atomic_base_impl@PAUHashtablezInfo@container_internal@absl@@@__Cr@std@@@__Cr@std@@QAE@PAUHashtablezInfo@container_internal@absl@@@Z ??0?$__cxx_atomic_impl@PAVCordzHandle@cord_internal@absl@@U?$__cxx_atomic_base_impl@PAVCordzHandle@cord_internal@absl@@@__Cr@std@@@__Cr@std@@QAE@PAVCordzHandle@cord_internal@absl@@@Z ??0?$__cxx_atomic_impl@PAVCordzInfo@cord_internal@absl@@U?$__cxx_atomic_base_impl@PAVCordzInfo@cord_internal@absl@@@__Cr@std@@@__Cr@std@@QAE@PAVCordzInfo@cord_internal@absl@@@Z - ??0?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QAEXXZ@$$A6AXAAVCommandLineFlag@5@@Z@__function@__Cr@std@@QAE@$$QAV@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QAEXXZ@@Z ??0?$__deque_iterator@PBVImpl@time_zone@cctz@time_internal@absl@@PAPBV12345@AAPBV12345@PAPAPBV12345@H$0A@@__Cr@std@@AAE@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPBV34567@@Z ??0?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@__Cr@std@@AAE@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@PAU3456@@Z ??0?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@AAE@PBQBUPrefixCrc@CrcCordState@crc_internal@absl@@PBU3456@@Z @@ -1759,7 +1694,7 @@ EXPORTS ??0?$__hash_node_destructor@V?$allocator@U?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@@__Cr@std@@QAE@AAV?$allocator@U?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@12@_N@Z ??0?$__hash_node_destructor@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@@QAE@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@@@12@_N@Z ??0?$__hash_table@PBUCordRep@cord_internal@absl@@U?$hash@PBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PBUCordRep@cord_internal@absl@@@56@V?$allocator@PBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QAE@XZ - ??0?$__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@XZ + ??0?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@XZ ??0?$__map_iterator@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@@@__Cr@std@@QAE@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@12@@Z ??0?$__map_iterator@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@@@__Cr@std@@QAE@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@12@@Z ??0?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@__Cr@std@@QAE@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@@Z @@ -1798,12 +1733,6 @@ EXPORTS ??0?$__optional_move_assign_base@VCord@absl@@$0A@@__Cr@std@@QAE@XZ ??0?$__optional_move_base@VCord@absl@@$0A@@__Cr@std@@QAE@XZ ??0?$__optional_storage_base@VCord@absl@@$0A@@__Cr@std@@QAE@XZ - ??0?$__policy_invoker@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@23@@Z@__function@__Cr@std@@AAE@P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@23@PBT__policy_storage@123@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@23@@Z@Z - ??0?$__policy_invoker@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@23@@Z@__function@__Cr@std@@QAE@XZ - ??0?$__policy_invoker@$$A6AXAAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@AAE@P6AXPBT__policy_storage@123@AAVCommandLineFlag@absl@@@Z@Z - ??0?$__policy_invoker@$$A6AXAAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@QAE@XZ - ??0?$__policy_invoker@$$A6A_NABVCommandLineFlag@absl@@@Z@__function@__Cr@std@@AAE@P6A_NPBT__policy_storage@123@ABVCommandLineFlag@absl@@@Z@Z - ??0?$__policy_invoker@$$A6A_NABVCommandLineFlag@absl@@@Z@__function@__Cr@std@@QAE@XZ ??0?$__split_buffer@PAPBVImpl@time_zone@cctz@time_internal@absl@@AAV?$allocator@PAPBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QAE@IIAAV?$allocator@PAPBVImpl@time_zone@cctz@time_internal@absl@@@12@@Z ??0?$__split_buffer@PAPBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PAPBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QAE@XZ ??0?$__split_buffer@PAUPrefixCrc@CrcCordState@crc_internal@absl@@AAV?$allocator@PAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QAE@IIAAV?$allocator@PAUPrefixCrc@CrcCordState@crc_internal@absl@@@12@@Z @@ -1827,8 +1756,8 @@ EXPORTS ??0?$__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@@AAE@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@12@@Z ??0?$__tree_node_destructor@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@@QAE@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@@@12@_N@Z ??0?$__tree_node_destructor@V?$allocator@V?$__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@__Cr@std@@@__Cr@std@@@__Cr@std@@QAE@AAV?$allocator@V?$__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@__Cr@std@@@12@_N@Z - ??0?$__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@__Cr@std@@QAE@XZ - ??0?$__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@__Cr@std@@QAE@XZ + ??0?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@__Cr@std@@QAE@XZ + ??0?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@__Cr@std@@QAE@XZ ??0?$__wrap_iter@PAPAVCommandLineFlag@absl@@@__Cr@std@@AAE@PAPAVCommandLineFlag@absl@@@Z ??0?$__wrap_iter@PAPAVCordzHandle@cord_internal@absl@@@__Cr@std@@AAE@PAPAVCordzHandle@cord_internal@absl@@@Z ??0?$__wrap_iter@PAPAVLogSink@absl@@@__Cr@std@@AAE@PAPAVLogSink@absl@@@Z @@ -2484,8 +2413,7 @@ EXPORTS ??Buint128@absl@@QBE_WXZ ??C?$NoDestructor@URefcountedRep@CrcCordState@crc_internal@absl@@@absl@@QAEPAURefcountedRep@CrcCordState@crc_internal@1@XZ ??C?$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@@QBEPBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ - ??C?$__hash_const_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@@QBEPBU?$__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@@@12@XZ - ??C?$__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@@QBEPAU?$__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@@@12@XZ + ??C?$__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@@QBEPAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@12@XZ ??C?$__hash_map_const_iterator@V?$__hash_const_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@@@__Cr@std@@QBEPBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@12@XZ ??C?$__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@@QBEPAU?$pair@$$CBV?$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@@12@XZ ??C?$__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@@QBEPAU?$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@@12@XZ @@ -2511,6 +2439,8 @@ EXPORTS ??D?$__deque_iterator@PBVImpl@time_zone@cctz@time_internal@absl@@PAPBV12345@AAPBV12345@PAPAPBV12345@H$0A@@__Cr@std@@QBEAAPBVImpl@time_zone@cctz@time_internal@absl@@XZ ??D?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@__Cr@std@@QBEAAUPrefixCrc@CrcCordState@crc_internal@absl@@XZ ??D?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@QBEABUPrefixCrc@CrcCordState@crc_internal@absl@@XZ + ??D?$__hash_const_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@@QBEABU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@12@XZ + ??D?$__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@@QBEAAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@12@XZ ??D?$__hash_map_iterator@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@@@__Cr@std@@QBEAAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@12@XZ ??D?$__map_iterator@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@@@__Cr@std@@QBEAAU?$pair@$$CBV?$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@@12@XZ ??D?$__map_iterator@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@@@__Cr@std@@QBEAAU?$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@@12@XZ @@ -2677,7 +2607,6 @@ EXPORTS ??R?$__allocator_destructor@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QAEXPAUPrefixCrc@CrcCordState@crc_internal@absl@@@Z ??R?$__bucket_list_deallocator@V?$allocator@PAU?$__hash_node_base@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@@__Cr@std@@@__Cr@std@@QAEXPAPAU?$__hash_node_base@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@12@@Z ??R?$__bucket_list_deallocator@V?$allocator@PAU?$__hash_node_base@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@@@__Cr@std@@@__Cr@std@@QAEXPAPAU?$__hash_node_base@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@@@12@@Z - ??R?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QAEXXZ@$$A6AXAAVCommandLineFlag@5@@Z@__function@__Cr@std@@QAEXAAVCommandLineFlag@absl@@@Z ??R?$__hash_node_destructor@V?$allocator@U?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@@__Cr@std@@QAEXPAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@12@@Z ??R?$__hash_node_destructor@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@@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@12@@Z ??R?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@__Cr@std@@QBE_NABU?$pair@$$CBV?$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@@12@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z @@ -2689,8 +2618,8 @@ EXPORTS ??R?$__policy_func@$$A6A_NABVCommandLineFlag@absl@@@Z@__function@__Cr@std@@QBE_NABVCommandLineFlag@absl@@@Z ??R?$__tree_node_destructor@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@@QAEXPAV?$__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@12@@Z ??R?$__tree_node_destructor@V?$allocator@V?$__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@__Cr@std@@@__Cr@std@@@__Cr@std@@QAEXPAV?$__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@12@@Z - ??R?$__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@__Cr@std@@QBE_NABU?$__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@@@12@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z - ??R?$__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@__Cr@std@@QBEIABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z + ??R?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@__Cr@std@@QBE_NABU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@12@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z + ??R?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@__Cr@std@@QBEIABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z ??R?$default_delete@$$CBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@QBEXPBVImpl@time_zone@cctz@time_internal@absl@@@Z ??R?$default_delete@ULogMessageData@LogMessage@log_internal@absl@@@__Cr@std@@QBEXPAULogMessageData@LogMessage@log_internal@absl@@@Z ??R?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@__Cr@std@@QBEXPAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@@Z @@ -3154,7 +3083,8 @@ EXPORTS ?EqualsImpl@Cord@absl@@ABE_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@I@Z ?EquivTransitions@TimeZoneInfo@cctz@time_internal@absl@@ABE_NEE@Z ?Erase@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QAEPAUPayload@status_internal@3@PBU453@0@Z - ?EraseMetaOnly@container_internal@absl@@YAXAAVCommonFields@12@PBW4ctrl_t@12@I@Z + ?EraseMetaOnlyLarge@container_internal@absl@@YAXAAVCommonFields@12@PBW4ctrl_t@12@I@Z + ?EraseMetaOnlySmall@container_internal@absl@@YAXAAVCommonFields@12@_NI@Z ?ErasePayload@StatusRep@status_internal@absl@@QAE?AUEraseResult@123@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?ErrnoToStatus@absl@@YA?AVStatus@1@HV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?ErrnoToStatusCode@absl@@YA?AW4StatusCode@1@H@Z @@ -3481,6 +3411,7 @@ EXPORTS ?InitFrom@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QAEXABV123@@Z ?InitGrowthLeftNoDeleted@GrowthInfo@container_internal@absl@@QAEXI@Z ?InitInstance@CordRepBtree@cord_internal@absl@@AAEXHII@Z + ?InitSigSafeArena@base_internal@absl@@YAXXZ ?InitTables@CRC32@crc_internal@absl@@UAEXXZ ?InitTree@ChunkIterator@Cord@absl@@AAEXPAUCordRep@cord_internal@3@@Z ?InitWhat@BadStatusOrAccess@absl@@ABEXXZ @@ -3581,7 +3512,6 @@ EXPORTS ?Lock@CordzInfo@cord_internal@absl@@QAEXW4MethodIdentifier@CordzUpdateTracker@23@@Z ?Lock@FlagRegistry@flags_internal@absl@@QAEXXZ ?Lock@Mutex@absl@@QAEXXZ - ?Lock@SpinLock@base_internal@absl@@QAEXXZ ?LockSlow@Mutex@absl@@AAEXPBUMuHowS@2@PBVCondition@2@H@Z ?LockSlowLoop@Mutex@absl@@AAEXPAUSynchWaitParams@2@H@Z ?LockSlowWithDeadline@Mutex@absl@@AAE_NPBUMuHowS@2@PBVCondition@2@VKernelTimeout@synchronization_internal@2@H@Z @@ -3605,6 +3535,7 @@ EXPORTS ?MakeAbsNanos@KernelTimeout@synchronization_internal@absl@@QBE_JXZ ?MakeAbsTimespec@KernelTimeout@synchronization_internal@absl@@QBE?AUtimespec@@XZ ?MakeCheckFailString@status_internal@absl@@YAPBDPBVStatus@2@PBD@Z + ?MakeCheckOpUnprintableString@log_internal@absl@@YAXAAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?MakeCheckOpValueString@log_internal@absl@@YAXAAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@C@Z ?MakeCheckOpValueString@log_internal@absl@@YAXAAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@D@Z ?MakeCheckOpValueString@log_internal@absl@@YAXAAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@E@Z @@ -3632,7 +3563,6 @@ EXPORTS ?MaskEmptyOrDeleted@GroupSse2Impl@container_internal@absl@@QBE?AV?$NonIterableBitMask@G$0BA@$0A@@23@XZ ?MaskFull@GroupPortableImpl@container_internal@absl@@QBE@XZ ?MaskFull@GroupSse2Impl@container_internal@absl@@QBE?AV?$BitMask@G$0BA@$0A@$0A@@23@XZ - ?MaskFullOrSentinel@GroupSse2Impl@container_internal@absl@@QBE?AV?$NonIterableBitMask@G$0BA@$0A@@23@XZ ?MaskNonFull@GroupSse2Impl@container_internal@absl@@QBE@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 @@ -3819,7 +3749,6 @@ EXPORTS ?ReadSeedMaterialFromOSEntropy@random_internal@absl@@YA_NV?$Span@I@2@@Z ?ReadSequenceLockedData@FlagImpl@flags_internal@absl@@ABEXPAX@Z ?ReaderLock@Mutex@absl@@QAEXXZ - ?ReaderTryLock@Mutex@absl@@QAE_NXZ ?ReaderTryLockSlow@Mutex@absl@@AAE_NXZ ?ReaderUnlock@Mutex@absl@@QAEXXZ ?Rebuild@CordRepBtree@cord_internal@absl@@CAXPAPAV123@PAV123@_N@Z @@ -3855,6 +3784,7 @@ EXPORTS ?RegisterMutexProfiler@absl@@YAXP6AX_J@Z@Z ?RegisterMutexTracer@absl@@YAXP6AXPBDPBX_J@Z@Z ?RegisterSpinLockProfiler@base_internal@absl@@YAXP6AXPBX_J@Z@Z + ?RegisterWithTsan@SpinLock@base_internal@absl@@AAEXXZ ?Rehash@container_internal@absl@@YAXAAVCommonFields@12@ABUPolicyFunctions@12@I@Z ?RehashProbabilityConstant@container_internal@absl@@YAIXZ ?RelaxedCopyFromAtomic@SequenceLock@flags_internal@absl@@CAXPAXPBU?$atomic@_K@__Cr@std@@I@Z @@ -3994,6 +3924,7 @@ EXPORTS ?ShouldPrependLogPrefix@absl@@YA_NXZ ?ShouldSampleNextTable@container_internal@absl@@YA_NXZ ?ShouldSymbolizeLogStackTrace@log_internal@absl@@YA_NXZ + ?SigSafeArena@base_internal@absl@@YAPAUArena@LowLevelAlloc@12@XZ ?Signal@CondVar@absl@@QAEXXZ ?SignalAll@CondVar@absl@@QAEXXZ ?SignedAddResult@int128_internal@absl@@YA?AVint128@2@V32@0@Z @@ -4190,7 +4121,6 @@ EXPORTS ?TrailingZeros@?$NonIterableBitMask@G$0BA@$0A@@container_internal@absl@@QBEIXZ ?Trans@Mutex@absl@@AAEXPBUMuHowS@2@@Z ?Trunc@absl@@YA?AVDuration@1@V21@0@Z - ?TryLock@Mutex@absl@@QAE_NXZ ?TryLockImpl@SpinLock@base_internal@absl@@AAE_NXZ ?TryLockInternal@SpinLock@base_internal@absl@@AAEIII@Z ?TryLockSlow@Mutex@absl@@AAE_NXZ @@ -4228,7 +4158,6 @@ EXPORTS ?Unlock@CordzInfo@cord_internal@absl@@QAEXXZ ?Unlock@FlagRegistry@flags_internal@absl@@QAEXXZ ?Unlock@Mutex@absl@@QAEXXZ - ?Unlock@SpinLock@base_internal@absl@@QAEXXZ ?UnlockSlow@Mutex@absl@@AAEXPAUSynchWaitParams@2@@Z ?Unparse@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@F@Z ?Unparse@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@G@Z @@ -4420,15 +4349,10 @@ EXPORTS ?__base_destruct_at_end@?$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@@AAEXPAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@23@@Z ?__begin@?$__segmented_iterator_traits@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@__Cr@std@@@__Cr@std@@SAPAUPrefixCrc@CrcCordState@crc_internal@absl@@PAPAU4567@@Z ?__begin@?$__segmented_iterator_traits@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@@__Cr@std@@SAPBUPrefixCrc@CrcCordState@crc_internal@absl@@PBQBU4567@@Z - ?__begin_node@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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_end_node@PAV?$__tree_node_base@PAX@__Cr@std@@@23@XZ - ?__begin_node@?$__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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__Cr@std@@AAEAAPAV?$__tree_end_node@PAV?$__tree_node_base@PAX@__Cr@std@@@23@XZ ?__call@?$__to_address_helper@V?$__wrap_iter@PAPAVCommandLineFlag@absl@@@__Cr@std@@X@__Cr@std@@SAPAPAVCommandLineFlag@absl@@ABV?$__wrap_iter@PAPAVCommandLineFlag@absl@@@23@@Z ?__call@?$__to_address_helper@V?$__wrap_iter@PAPAVLogSink@absl@@@__Cr@std@@X@__Cr@std@@SAPAPAVLogSink@absl@@ABV?$__wrap_iter@PAPAVLogSink@absl@@@23@@Z ?__call@?$__to_address_helper@V?$__wrap_iter@PAPBVCommandLineFlag@absl@@@__Cr@std@@X@__Cr@std@@SAPAPBVCommandLineFlag@absl@@ABV?$__wrap_iter@PAPBVCommandLineFlag@absl@@@23@@Z ?__call@?$__to_address_helper@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@@X@__Cr@std@@SAPAUraw_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@@23@ABV678@@Z@ABV?$__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@@23@@Z - ?__call_empty@?$__policy_invoker@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@23@@Z@__function@__Cr@std@@CA?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@__Cr@std@@@34@PBT__policy_storage@234@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@34@@Z - ?__call_empty@?$__policy_invoker@$$A6AXAAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@CAXPBT__policy_storage@234@AAVCommandLineFlag@absl@@@Z - ?__call_empty@?$__policy_invoker@$$A6A_NABVCommandLineFlag@absl@@@Z@__function@__Cr@std@@CA_NPBT__policy_storage@234@ABVCommandLineFlag@absl@@@Z ?__capacity@?$deque@PBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QBEIXZ ?__capacity@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QBEIXZ ?__complete@?$__exception_guard_noexceptions@V?$_AllocatorDestroyRangeReverse@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@PAUUnrecognizedFlag@absl@@@__Cr@std@@@__Cr@std@@QAEXXZ @@ -4440,7 +4364,7 @@ EXPORTS ?__copy_assign_alloc@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@AAEXABV123@@Z ?__copy_assign_alloc@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@AAEXABV123@U?$integral_constant@_N$0A@@23@@Z ?__deallocate_node@?$__hash_table@PBUCordRep@cord_internal@absl@@U?$hash@PBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PBUCordRep@cord_internal@absl@@@56@V?$allocator@PBUCordRep@cord_internal@absl@@@56@@__Cr@std@@AAEXPAU?$__hash_node_base@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@23@@Z - ?__deallocate_node@?$__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@@AAEXPAU?$__hash_node_base@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@@@23@@Z + ?__deallocate_node@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AAEXPAU?$__hash_node_base@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@@@23@@Z ?__destruct_at_begin@?$__split_buffer@PAPBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PAPBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QAEXPAPAPBVImpl@time_zone@cctz@time_internal@absl@@@Z ?__destruct_at_begin@?$__split_buffer@PAPBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PAPBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QAEXPAPAPBVImpl@time_zone@cctz@time_internal@absl@@U?$integral_constant@_N$00@23@@Z ?__destruct_at_begin@?$__split_buffer@PAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QAEXPAPAUPrefixCrc@CrcCordState@crc_internal@absl@@@Z @@ -4486,20 +4410,14 @@ EXPORTS ?__erase_to_end@?$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@@23@@Z ?__front_spare@?$deque@PBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QBEIXZ ?__front_spare@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QBEIXZ - ?__get_key@?$__hash_key_value_types@PBUCordRep@cord_internal@absl@@@__Cr@std@@SAABQBUCordRep@cord_internal@absl@@ABQBU456@@Z ?__get_np@?$__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@@ABEPAV?$__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@XZ ?__get_np@?$__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@@ABEPAV?$__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@XZ - ?__get_ptr@?$__hash_key_value_types@PBUCordRep@cord_internal@absl@@@__Cr@std@@SAPAPBUCordRep@cord_internal@absl@@AAPBU456@@Z - ?__get_ptr@?$__hash_key_value_types@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@@@__Cr@std@@SAPAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@AAU?$__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@@Z ?__get_value@?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@QAEAAPBUCordRep@cord_internal@absl@@XZ - ?__get_value@?$__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@@QAEAAU?$__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@XZ - ?__get_value@?$__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@@QAEAAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@XZ - ?__get_value@?$__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@@QBEABU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@XZ + ?__get_value@?$__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@@QAEAAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@XZ ?__hash@?$__hash_node_base@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@QBEIXZ ?__hash@?$__hash_node_base@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@@QBEIXZ ?__insert_node_at@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QAEXPAV?$__tree_end_node@PAV?$__tree_node_base@PAX@__Cr@std@@@23@AAPAV?$__tree_node_base@PAX@23@PAV523@@Z ?__insert_node_at@?$__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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__Cr@std@@QAEXPAV?$__tree_end_node@PAV?$__tree_node_base@PAX@__Cr@std@@@23@AAPAV?$__tree_node_base@PAX@23@PAV523@@Z - ?__insert_unique@?$__hash_table@PBUCordRep@cord_internal@absl@@U?$hash@PBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PBUCordRep@cord_internal@absl@@@56@V?$allocator@PBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QAE?AU?$pair@V?$__hash_iterator@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@_N@23@ABQBUCordRep@cord_internal@absl@@@Z ?__local@?$__segmented_iterator_traits@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@__Cr@std@@@__Cr@std@@SAPAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@23@@Z ?__local@?$__segmented_iterator_traits@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@@__Cr@std@@SAPBUPrefixCrc@CrcCordState@crc_internal@absl@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@23@@Z ?__make_iter@?$vector@PAVCommandLineFlag@absl@@V?$allocator@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@AAE?AV?$__wrap_iter@PAPAVCommandLineFlag@absl@@@23@PAPAVCommandLineFlag@absl@@@Z @@ -4517,7 +4435,7 @@ EXPORTS ?__move_range@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@AAEXPAUTransition@cctz@time_internal@absl@@00@Z ?__move_range@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@AAEXPAUTransitionType@cctz@time_internal@absl@@00@Z ?__node_alloc@?$__hash_table@PBUCordRep@cord_internal@absl@@U?$hash@PBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PBUCordRep@cord_internal@absl@@@56@V?$allocator@PBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QAEAAV?$allocator@U?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@23@XZ - ?__node_alloc@?$__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@@QAEAAV?$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@XZ + ?__node_alloc@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QAEAAV?$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@XZ ?__node_alloc@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$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@XZ ?__node_alloc@?$__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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__Cr@std@@QAEAAV?$allocator@V?$__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@__Cr@std@@@23@XZ ?__ptr@?$__hash_node_base@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@QAEPAU123@XZ @@ -4535,7 +4453,7 @@ EXPORTS ?__recommend@?$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@@ABEII@Z ?__recommend_blocks@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@SAII@Z ?__rehash_unique@?$__hash_table@PBUCordRep@cord_internal@absl@@U?$hash@PBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PBUCordRep@cord_internal@absl@@@56@V?$allocator@PBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QAEXI@Z - ?__rehash_unique@?$__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@@QAEXI@Z + ?__rehash_unique@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QAEXI@Z ?__rewrap@?$__unwrap_iter_impl@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@$00@__Cr@std@@SAPAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV45678@0@Z ?__rewrap@?$__unwrap_iter_impl@PAPAUPrefixCrc@CrcCordState@crc_internal@absl@@$00@__Cr@std@@SAPAPAUPrefixCrc@CrcCordState@crc_internal@absl@@PAPAU4567@0@Z ?__rewrap@?$__unwrap_iter_impl@PAPAVLogSink@absl@@$00@__Cr@std@@SAPAPAVLogSink@absl@@PAPAV45@0@Z @@ -4675,6 +4593,7 @@ EXPORTS ?ascii_isxdigit@absl@@YA_NE@Z ?ascii_tolower@absl@@YADE@Z ?ascii_toupper@absl@@YADE@Z + ?assert_is_full@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@@ABEXPBD@Z ?at_end@?$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@@QBE_NXZ ?back@?$InlinedVector@PAUCordRep@cord_internal@absl@@$01V?$allocator@PAUCordRep@cord_internal@absl@@@__Cr@std@@@absl@@QAEAAPAUCordRep@cord_internal@2@XZ ?back@?$__split_buffer@PAUPrefixCrc@CrcCordState@crc_internal@absl@@AAV?$allocator@PAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QAEAAPAUPrefixCrc@CrcCordState@crc_internal@absl@@XZ @@ -4715,7 +4634,7 @@ EXPORTS ?begin@?$Splitter@VByAnyChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QBE?AV?$SplitIterator@V?$Splitter@VByAnyChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@23@XZ ?begin@?$Splitter@VByAnyChar@absl@@USkipEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QBE?AV?$SplitIterator@V?$Splitter@VByAnyChar@absl@@USkipEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@23@XZ ?begin@?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QBE?AV?$SplitIterator@V?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@23@XZ - ?begin@?$__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?AV?$__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@@@23@XZ + ?begin@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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?AV?$__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@@@23@XZ ?begin@?$__split_buffer@PAPBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PAPBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QAEPAPAPBVImpl@time_zone@cctz@time_internal@absl@@XZ ?begin@?$__split_buffer@PAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QAEPAPAUPrefixCrc@CrcCordState@crc_internal@absl@@XZ ?begin@?$__split_buffer@PAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QBEPBQAUPrefixCrc@CrcCordState@crc_internal@absl@@XZ @@ -4750,7 +4669,7 @@ EXPORTS ?btree@CordRepBtreeNavigator@cord_internal@absl@@QBEPAVCordRepBtree@23@XZ ?btree@CordRepBtreeReader@cord_internal@absl@@QBEPAVCordRepBtree@23@XZ ?bucket_count@?$__hash_table@PBUCordRep@cord_internal@absl@@U?$hash@PBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PBUCordRep@cord_internal@absl@@@56@V?$allocator@PBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QBEIXZ - ?bucket_count@?$__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@@QBEIXZ + ?bucket_count@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QBEIXZ ?bytes_value@ProtoField@log_internal@absl@@QBE?AV?$Span@$$CBD@3@XZ ?capacity@?$__split_buffer@PAPBVImpl@time_zone@cctz@time_internal@absl@@AAV?$allocator@PAPBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QBEIXZ ?capacity@?$__split_buffer@PAPBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PAPBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QBEIXZ @@ -4789,7 +4708,7 @@ EXPORTS ?chunk_begin@Cord@absl@@QBE?AVChunkIterator@12@XZ ?chunk_end@Cord@absl@@QBE?AVChunkIterator@12@XZ ?clear@?$InlinedVector@PAVLogSink@absl@@$0BA@V?$allocator@PAVLogSink@absl@@@__Cr@std@@@absl@@QAEXXZ - ?clear@?$__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@@QAEXXZ + ?clear@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QAEXXZ ?clear@?$__split_buffer@PAPBVImpl@time_zone@cctz@time_internal@absl@@AAV?$allocator@PAPBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QAEXXZ ?clear@?$__split_buffer@PAUPrefixCrc@CrcCordState@crc_internal@absl@@AAV?$allocator@PAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QAEXXZ ?clear@?$__split_buffer@PAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QAEXXZ @@ -4825,6 +4744,7 @@ EXPORTS ?combine_raw@MixingHashState@hash_internal@absl@@CA?AV123@V123@_K@Z ?common@?$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@@AAEAAVCommonFields@23@XZ ?common@?$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@@ABEABVCommonFields@23@XZ + ?compare_exchange_strong@?$__atomic_base@PAUArena@LowLevelAlloc@base_internal@absl@@$0A@@__Cr@std@@QAE_NAAPAUArena@LowLevelAlloc@base_internal@absl@@PAU4567@W4memory_order@23@2@Z ?compare_exchange_strong@?$__atomic_base@PAVTimeZone@absl@@$0A@@__Cr@std@@QAE_NAAPAVTimeZone@absl@@PAV45@W4memory_order@23@2@Z ?compare_exchange_strong@?$__atomic_base@PAVVLogSite@log_internal@absl@@$0A@@__Cr@std@@QAE_NAAPAVVLogSite@log_internal@absl@@PAV456@W4memory_order@23@2@Z ?compare_exchange_weak@?$__atomic_base@PAUHashtablezInfo@container_internal@absl@@$0A@@__Cr@std@@QAE_NAAPAUHashtablezInfo@container_internal@absl@@PAU456@W4memory_order@23@2@Z @@ -4988,7 +4908,7 @@ EXPORTS ?end@?$Splitter@VByAnyChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QBE?AV?$SplitIterator@V?$Splitter@VByAnyChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@23@XZ ?end@?$Splitter@VByAnyChar@absl@@USkipEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QBE?AV?$SplitIterator@V?$Splitter@VByAnyChar@absl@@USkipEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@23@XZ ?end@?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QBE?AV?$SplitIterator@V?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@23@XZ - ?end@?$__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?AV?$__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@@@23@XZ + ?end@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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?AV?$__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@@@23@XZ ?end@?$__split_buffer@PAPBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PAPBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QAEPAPAPBVImpl@time_zone@cctz@time_internal@absl@@XZ ?end@?$__split_buffer@PAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QAEPAPAUPrefixCrc@CrcCordState@crc_internal@absl@@XZ ?end@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?AV?$__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@23@XZ @@ -5024,7 +4944,6 @@ EXPORTS ?external@CordRep@cord_internal@absl@@QBEPBUCordRepExternal@23@XZ ?fetch_add_end@CordRepBtree@cord_internal@absl@@AAEII@Z ?find@?$unordered_map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@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@V?$allocator@U?$pair@$$CBV?$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?AV?$__hash_map_iterator@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@@@23@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@23@@Z - ?find_first_non_full@container_internal@absl@@YA?AUFindInfo@12@ABVCommonFields@12@I@Z ?fits_in_soo@?$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@@ABE_NI@Z ?fixed_time_zone@cctz@time_internal@absl@@YA?AVtime_zone@123@ABV?$duration@_JV?$ratio@$00$00@__Cr@std@@@chrono@__Cr@std@@@Z ?flat@CordRep@cord_internal@absl@@QAEPAUCordRepFlat@23@XZ @@ -5133,7 +5052,7 @@ EXPORTS ?has_timeout@KernelTimeout@synchronization_internal@absl@@QBE_NXZ ?has_zero_flag@FormatConversionSpecImpl@str_format_internal@absl@@QBE_NXZ ?hash_function@?$__hash_table@PBUCordRep@cord_internal@absl@@U?$hash@PBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PBUCordRep@cord_internal@absl@@@56@V?$allocator@PBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QAEAAU?$hash@PBUCordRep@cord_internal@absl@@@23@XZ - ?hash_function@?$__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@@QAEAAV?$__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@XZ + ?hash_function@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QAEAAV?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@XZ ?hash_ref@?$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@@AAEAAUStringHash@23@XZ ?hash_ref@?$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@@ABEABUStringHash@23@XZ ?hash_with_seed@?$HashImpl@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@hash_internal@absl@@ABEIABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@I@Z @@ -5182,10 +5101,11 @@ EXPORTS ?iterator_at_ptr@?$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@@IAE?AViterator@123@U?$pair@PAW4ctrl_t@container_internal@absl@@PAX@__Cr@std@@@Z ?kDefaultIterControl@container_internal@absl@@3W4ctrl_t@12@A ?key_eq@?$__hash_table@PBUCordRep@cord_internal@absl@@U?$hash@PBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PBUCordRep@cord_internal@absl@@@56@V?$allocator@PBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QAEAAU?$equal_to@PBUCordRep@cord_internal@absl@@@23@XZ - ?key_eq@?$__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@@QAEAAV?$__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@XZ + ?key_eq@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QAEAAV?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$pair@$$CBV?$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@XZ ?length@CordRepBtreeReader@cord_internal@absl@@QBEIXZ ?length_mod@FormatConversionSpecImpl@str_format_internal@absl@@QBE?AW4LengthMod@3@XZ ?load@?$__atomic_base@P6AXABUHashtablezInfo@container_internal@absl@@@Z$0A@@__Cr@std@@QBEP6AXABUHashtablezInfo@container_internal@absl@@@ZW4memory_order@23@@Z + ?load@?$__atomic_base@PAUArena@LowLevelAlloc@base_internal@absl@@$0A@@__Cr@std@@QBEPAUArena@LowLevelAlloc@base_internal@absl@@W4memory_order@23@@Z ?load@?$__atomic_base@PAUHashtablezInfo@container_internal@absl@@$0A@@__Cr@std@@QBEPAUHashtablezInfo@container_internal@absl@@W4memory_order@23@@Z ?load@?$__atomic_base@PAVCordzHandle@cord_internal@absl@@$0A@@__Cr@std@@QBEPAVCordzHandle@cord_internal@absl@@W4memory_order@23@@Z ?load@?$__atomic_base@PAVCordzInfo@cord_internal@absl@@$0A@@__Cr@std@@QBEPAVCordzInfo@cord_internal@absl@@W4memory_order@23@@Z @@ -5196,6 +5116,9 @@ EXPORTS ?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 ?local_time_zone@cctz@time_internal@absl@@YA?AVtime_zone@123@XZ + ?lock@Mutex@absl@@QAEXXZ + ?lock@SpinLock@base_internal@absl@@QAEXXZ + ?lock_shared@Mutex@absl@@QAEXXZ ?log_severity@LogEntry@absl@@QBE?AW4LogSeverity@2@XZ ?lookup@time_zone@cctz@time_internal@absl@@QBE?AUabsolute_lookup@1234@ABV?$time_point@Vsystem_clock@chrono@__Cr@std@@V?$duration@_JV?$ratio@$00$00@__Cr@std@@@234@@chrono@__Cr@std@@@Z ?lookup@time_zone@cctz@time_internal@absl@@QBE?AUcivil_lookup@1234@ABV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@detail@234@@Z @@ -5206,7 +5129,7 @@ EXPORTS ?max@?$numeric_limits@Vint128@absl@@@__Cr@std@@SA?AVint128@absl@@XZ ?max@?$numeric_limits@Vuint128@absl@@@__Cr@std@@SA?AVuint128@absl@@XZ ?max_load_factor@?$__hash_table@PBUCordRep@cord_internal@absl@@U?$hash@PBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PBUCordRep@cord_internal@absl@@@56@V?$allocator@PBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QAEAAMXZ - ?max_load_factor@?$__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@@QAEAAMXZ + ?max_load_factor@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QAEAAMXZ ?max_size@?$vector@PAVCommandLineFlag@absl@@V?$allocator@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@QBEIXZ ?max_size@?$vector@PAVCordzHandle@cord_internal@absl@@V?$allocator@PAVCordzHandle@cord_internal@absl@@@__Cr@std@@@__Cr@std@@QBEIXZ ?max_size@?$vector@PAVLogSink@absl@@V?$allocator@PAVLogSink@absl@@@__Cr@std@@@__Cr@std@@QBEIXZ @@ -5253,10 +5176,9 @@ EXPORTS ?parsed_conversion@UntypedFormatSpecImpl@str_format_internal@absl@@QBEPBVParsedFormatBase@23@XZ ?pointer_to@?$pointer_traits@PAU?$__hash_node_base@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SAPAU?$__hash_node_base@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@23@AAU423@@Z ?pointer_to@?$pointer_traits@PAU?$__hash_node_base@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@@@__Cr@std@@SAPAU?$__hash_node_base@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@@@23@AAU423@@Z - ?pointer_to@?$pointer_traits@PAU?$__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@@@__Cr@std@@SAPAU?$__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@AAU423@@Z + ?pointer_to@?$pointer_traits@PAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@SAPAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@AAU423@@Z ?pointer_to@?$pointer_traits@PAU?$pair@$$CBV?$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@@@__Cr@std@@SAPAU?$pair@$$CBV?$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@AAU423@@Z ?pointer_to@?$pointer_traits@PAU?$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@@@__Cr@std@@SAPAU?$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@@23@AAU423@@Z - ?pointer_to@?$pointer_traits@PBU?$__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@@@__Cr@std@@SAPBU?$__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@ABU423@@Z ?pointer_to@?$pointer_traits@PBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@SAPBU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@ABU423@@Z ?poison@InlineData@cord_internal@absl@@QAEXXZ ?poison_this@InlineData@cord_internal@absl@@QAEXXZ @@ -5373,6 +5295,7 @@ EXPORTS ?set_cordz_mean_interval@cord_internal@absl@@YAXH@Z ?set_data@InlineRep@Cord@absl@@QAEPADI@Z ?set_data@InlineRep@Cord@absl@@QAEXPBDI@Z + ?set_empty_soo@CommonFields@container_internal@absl@@QAEXXZ ?set_end@CordRepBtree@cord_internal@absl@@AAEXI@Z ?set_from_arg@InputValue@UnboundConversion@str_format_internal@absl@@QAEXH@Z ?set_full_soo@CommonFields@container_internal@absl@@QAEXXZ @@ -5424,12 +5347,10 @@ EXPORTS ?size@?$__bucket_list_deallocator@V?$allocator@PAU?$__hash_node_base@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@@@__Cr@std@@@__Cr@std@@QAEAAIXZ ?size@?$__bucket_list_deallocator@V?$allocator@PAU?$__hash_node_base@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@@@__Cr@std@@@__Cr@std@@QBEIXZ ?size@?$__hash_table@PBUCordRep@cord_internal@absl@@U?$hash@PBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PBUCordRep@cord_internal@absl@@@56@V?$allocator@PBUCordRep@cord_internal@absl@@@56@@__Cr@std@@AAEAAIXZ - ?size@?$__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@@AAEAAIXZ + ?size@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AAEAAIXZ ?size@?$__split_buffer@PAPBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PAPBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QBEIXZ ?size@?$__split_buffer@PAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QBEIXZ - ?size@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AAEAAIXZ - ?size@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QBEABIXZ - ?size@?$__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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__Cr@std@@AAEAAIXZ + ?size@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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@@QBEIXZ ?size@?$array@Uraw_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@$0BA@@__Cr@std@@QBEIXZ ?size@?$deque@PBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QBEIXZ ?size@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QBEIXZ @@ -5506,8 +5427,13 @@ EXPORTS ?transfer_unprobed_elements_to_next_capacity_fn@?$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@@CAXAAVCommonFields@23@PBW4ctrl_t@23@PAX2P6AX2EII@Z@Z ?tree@InlineRep@Cord@absl@@QBEPAUCordRep@cord_internal@3@XZ ?tree@Rep@InlineData@cord_internal@absl@@QBEPAUCordRep@34@XZ + ?try_lock@Mutex@absl@@QAE_NXZ + ?try_lock_shared@Mutex@absl@@QAE_NXZ ?type@ProtoField@log_internal@absl@@QBE?AW4WireType@23@XZ ?unchecked_deref@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@@ABEAAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@XZ + ?unlock@Mutex@absl@@QAEXXZ + ?unlock@SpinLock@base_internal@absl@@QAEXXZ + ?unlock_shared@Mutex@absl@@QAEXXZ ?unpoison@InlineData@cord_internal@absl@@QAEXXZ ?utc_time_zone@cctz@time_internal@absl@@YA?AVtime_zone@123@XZ ?value@ConvertibleToStringView@strings_internal@absl@@QBE?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ 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 6bb67140e6..1a3619a9b3 100644 --- a/naiveproxy/src/third_party/abseil-cpp/symbols_x86_rel.def +++ b/naiveproxy/src/third_party/abseil-cpp/symbols_x86_rel.def @@ -159,19 +159,19 @@ EXPORTS ??$UnparseFloatingPointVal@N@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@N@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_impl@V?$__default_alloc_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QAEXXZ@$$A6AXAAVCommandLineFlag@5@@Z@__function@__Cr@std@@@?$__policy_invoker@$$A6AXAAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@CAXPBT__policy_storage@123@AAVCommandLineFlag@absl@@@Z + ??$__call_func@V@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QAEXXZ@@?$__policy_func@$$A6AXAAVCommandLineFlag@absl@@@Z@__function@__Cr@std@@CAXPBT__policy_storage@123@AAVCommandLineFlag@absl@@@Z ??$__dispatch@$$QAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YAIUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@?$__dispatcher@$00@__base@__visitation@__variant_detail@__Cr@std@@SA?A_T$$QAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YAIUStructuredProtoField@34@@Z@@__variant@2345@AAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@345@@Z ??$__dispatch@$$QAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YAIUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@?$__dispatcher@$01@__base@__visitation@__variant_detail@__Cr@std@@SA?A_T$$QAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YAIUStructuredProtoField@34@@Z@@__variant@2345@AAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@345@@Z ??$__dispatch@$$QAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YAIUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@?$__dispatcher@$02@__base@__visitation@__variant_detail@__Cr@std@@SA?A_T$$QAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YAIUStructuredProtoField@34@@Z@@__variant@2345@AAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@345@@Z ??$__dispatch@$$QAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YAIUStructuredProtoField@34@@Z@@__variant@__visitation@__variant_detail@__Cr@std@@AAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@456@@?$__dispatcher@$0A@@__base@__visitation@__variant_detail@__Cr@std@@SA?A_T$$QAU?$__value_visitor@UBufferSizeVisitor@?1??BufferSizeForStructuredProtoField@log_internal@absl@@YAIUStructuredProtoField@34@@Z@@__variant@2345@AAV?$__base@$0A@V?$variant@_K_JIH_N@__Cr@std@@V?$variant@_K_JN@23@V?$Span@$$CBD@absl@@V?$variant@IHM@23@@345@@Z ??$__do_rehash@$00@?$__hash_table@PBUCordRep@cord_internal@absl@@U?$hash@PBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PBUCordRep@cord_internal@absl@@@56@V?$allocator@PBUCordRep@cord_internal@absl@@@56@@__Cr@std@@AAEXI@Z - ??$__do_rehash@$00@?$__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@@AAEXI@Z + ??$__do_rehash@$00@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@AAEXI@Z ??$__emplace_back_slow_path@AAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@ABV123@AAI@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@__Cr@std@@AAEPAUViableSubstitution@strings_internal@absl@@AAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@12@ABV612@AAI@Z ??$__emplace_back_slow_path@ABUUnrecognizedFlag@absl@@@?$vector@UUnrecognizedFlag@absl@@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@@__Cr@std@@AAEPAUUnrecognizedFlag@absl@@ABU34@@Z ??$__emplace_back_slow_path@W4Source@UnrecognizedFlag@absl@@AAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$vector@UUnrecognizedFlag@absl@@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@@__Cr@std@@AAEPAUUnrecognizedFlag@absl@@$$QAW4Source@34@AAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@12@@Z ??$__emplace_unique_key_args@PBUCordRep@cord_internal@absl@@ABQBU123@@?$__hash_table@PBUCordRep@cord_internal@absl@@U?$hash@PBUCordRep@cord_internal@absl@@@__Cr@std@@U?$equal_to@PBUCordRep@cord_internal@absl@@@56@V?$allocator@PBUCordRep@cord_internal@absl@@@56@@__Cr@std@@QAE?AU?$pair@V?$__hash_iterator@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@_N@12@ABQBUCordRep@cord_internal@absl@@0@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@$$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?$pair@$$CBV?$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?$pair@$$CBV?$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@@?$__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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__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 ??$__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@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@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 @@ -199,7 +199,7 @@ EXPORTS ??$emplace_front@AAPAUPrefixCrc@CrcCordState@crc_internal@absl@@@?$__split_buffer@PAUPrefixCrc@CrcCordState@crc_internal@absl@@AAV?$allocator@PAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QAEXAAPAUPrefixCrc@CrcCordState@crc_internal@absl@@@Z ??$emplace_front@PAPBVImpl@time_zone@cctz@time_internal@absl@@@?$__split_buffer@PAPBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PAPBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QAEX$$QAPAPBVImpl@time_zone@cctz@time_internal@absl@@@Z ??$emplace_front@PAUPrefixCrc@CrcCordState@crc_internal@absl@@@?$__split_buffer@PAUPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@PAUPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QAEX$$QAPAUPrefixCrc@CrcCordState@crc_internal@absl@@@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@@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?AV?$__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@@@12@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@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@@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?$pair@$$CBV?$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?$pair@$$CBV?$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?$pair@$$CBV?$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?AV?$__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@@@12@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z ??$find@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@@QAE?AViterator@012@ABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??$find_or_prepare_insert@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@@IAE?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@@ABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@45@@Z ??$find_or_prepare_insert_large@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@@AAE?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@@ABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@45@@Z @@ -262,7 +262,6 @@ EXPORTS ??0Randen@random_internal@absl@@QAE@XZ ??0ScopedMinLogLevel@log_internal@absl@@QAE@W4LogSeverityAtLeast@2@@Z ??0ScopedStderrThreshold@absl@@QAE@W4LogSeverityAtLeast@1@@Z - ??0SpinLock@base_internal@absl@@QAE@W4SchedulingMode@12@@Z ??0Status@absl@@QAE@W4StatusCode@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??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 @@ -339,7 +338,6 @@ EXPORTS ??ACord@absl@@QBEDI@Z ??BCord@absl@@QBE?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@XZ ??Bint128@absl@@QBENXZ - ??Eiterator@?$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@@QAEAAV0123@XZ ??Gdetail@cctz@time_internal@absl@@YA?AV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@0123@V40123@_J@Z ??Kabsl@@YA?AVint128@0@V10@0@Z ??Kabsl@@YA?AVuint128@0@V10@0@Z @@ -482,6 +480,7 @@ EXPORTS ?ClearLogBacktraceLocation@absl@@YAXXZ ?ClearTimeZoneMapTestOnly@Impl@time_zone@cctz@time_internal@absl@@SAXXZ ?CloneAndUnref@StatusRep@status_internal@absl@@QBEPAV123@XZ + ?CombineContiguousImpl@hash_internal@absl@@YA_K_KPBEIU?$integral_constant@H$03@__Cr@std@@@Z ?CombineContiguousImpl@hash_internal@absl@@YA_K_KPBEIU?$integral_constant@H$07@__Cr@std@@@Z ?CombineLargeContiguousImplOn32BitLengthGt8@hash_internal@absl@@YA_KPBEI_K@Z ?CombineLargeContiguousImplOn64BitLengthGt32@hash_internal@absl@@YA_KPBEI_K@Z @@ -589,7 +588,8 @@ EXPORTS ?EqualsImpl@Cord@absl@@ABE_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@I@Z ?EquivTransitions@TimeZoneInfo@cctz@time_internal@absl@@ABE_NEE@Z ?Erase@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QAEPAUPayload@status_internal@3@PBU453@0@Z - ?EraseMetaOnly@container_internal@absl@@YAXAAVCommonFields@12@PBW4ctrl_t@12@I@Z + ?EraseMetaOnlyLarge@container_internal@absl@@YAXAAVCommonFields@12@PBW4ctrl_t@12@I@Z + ?EraseMetaOnlySmall@container_internal@absl@@YAXAAVCommonFields@12@_NI@Z ?ErasePayload@StatusRep@status_internal@absl@@QAE?AUEraseResult@123@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?ErrnoToStatus@absl@@YA?AVStatus@1@HV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?ErrnoToStatusCode@absl@@YA?AW4StatusCode@1@H@Z @@ -783,6 +783,7 @@ EXPORTS ?Init@FlagImpl@flags_internal@absl@@AAEXXZ ?InitDiscreteDistribution@random_internal@absl@@YA?AV?$vector@U?$pair@NI@__Cr@std@@V?$allocator@U?$pair@NI@__Cr@std@@@23@@__Cr@std@@PAV?$vector@NV?$allocator@N@__Cr@std@@@45@@Z ?InitFrom@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QAEXABV123@@Z + ?InitSigSafeArena@base_internal@absl@@YAXXZ ?InitTables@CRC32@crc_internal@absl@@UAEXXZ ?InitTree@ChunkIterator@Cord@absl@@AAEXPAUCordRep@cord_internal@3@@Z ?InitWhat@BadStatusOrAccess@absl@@ABEXXZ @@ -838,7 +839,6 @@ EXPORTS ?LocalTime@TimeZoneInfo@cctz@time_internal@absl@@ABE?AUabsolute_lookup@time_zone@234@_JABUTransition@234@@Z ?LocalTime@TimeZoneInfo@cctz@time_internal@absl@@ABE?AUabsolute_lookup@time_zone@234@_JABUTransitionType@234@@Z ?Lock@CordzInfo@cord_internal@absl@@QAEXW4MethodIdentifier@CordzUpdateTracker@23@@Z - ?Lock@Mutex@absl@@QAEXXZ ?LockSlow@Mutex@absl@@AAEXPBUMuHowS@2@PBVCondition@2@H@Z ?LockSlowLoop@Mutex@absl@@AAEXPAUSynchWaitParams@2@H@Z ?LockSlowWithDeadline@Mutex@absl@@AAE_NPBUMuHowS@2@PBVCondition@2@VKernelTimeout@synchronization_internal@2@H@Z @@ -852,6 +852,7 @@ EXPORTS ?MakeAbsNanos@KernelTimeout@synchronization_internal@absl@@QBE_JXZ ?MakeAbsTimespec@KernelTimeout@synchronization_internal@absl@@QBE?AUtimespec@@XZ ?MakeCheckFailString@status_internal@absl@@YAPBDPBVStatus@2@PBD@Z + ?MakeCheckOpUnprintableString@log_internal@absl@@YAXAAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?MakeCheckOpValueString@log_internal@absl@@YAXAAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@C@Z ?MakeCheckOpValueString@log_internal@absl@@YAXAAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@D@Z ?MakeCheckOpValueString@log_internal@absl@@YAXAAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@E@Z @@ -988,10 +989,7 @@ EXPORTS ?ReadOneWord@FlagImpl@flags_internal@absl@@QBE_JXZ ?ReadSeedMaterialFromOSEntropy@random_internal@absl@@YA_NV?$Span@I@2@@Z ?ReadSequenceLockedData@FlagImpl@flags_internal@absl@@ABEXPAX@Z - ?ReaderLock@Mutex@absl@@QAEXXZ - ?ReaderTryLock@Mutex@absl@@QAE_NXZ ?ReaderTryLockSlow@Mutex@absl@@AAE_NXZ - ?ReaderUnlock@Mutex@absl@@QAEXXZ ?Rebuild@CordRepBtree@cord_internal@absl@@CAXPAPAV123@PAV123@_N@Z ?Rebuild@CordRepBtree@cord_internal@absl@@SAPAV123@PAV123@@Z ?RecordClearedReservationSlow@container_internal@absl@@YAXPAUHashtablezInfo@12@@Z @@ -1094,6 +1092,7 @@ EXPORTS ?ShouldLogBacktraceAt@log_internal@absl@@YA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@H@Z ?ShouldPrependLogPrefix@absl@@YA_NXZ ?ShouldSymbolizeLogStackTrace@log_internal@absl@@YA_NXZ + ?SigSafeArena@base_internal@absl@@YAPAUArena@LowLevelAlloc@12@XZ ?Signal@CondVar@absl@@QAEXXZ ?SignalAll@CondVar@absl@@QAEXXZ ?SimpleAtob@absl@@YA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PA_N@Z @@ -1213,7 +1212,6 @@ EXPORTS ?TrackCord@CordzInfo@cord_internal@absl@@SAXAAVInlineData@23@W4MethodIdentifier@CordzUpdateTracker@23@_J@Z ?Trans@Mutex@absl@@AAEXPBUMuHowS@2@@Z ?Trunc@absl@@YA?AVDuration@1@V21@0@Z - ?TryLock@Mutex@absl@@QAE_NXZ ?TryLockSlow@Mutex@absl@@AAE_NXZ ?TryNewCRC32AcceleratedX86ARMCombined@crc_internal@absl@@YAPAVCRCImpl@12@XZ ?TryParse@FlagImpl@flags_internal@absl@@ABE?AV?$unique_ptr@XUDynValueDeleter@flags_internal@absl@@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@56@AAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@56@@Z @@ -1236,7 +1234,6 @@ EXPORTS ?UnimplementedError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?UnknownError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?Unlock@CordzInfo@cord_internal@absl@@QAEXXZ - ?Unlock@Mutex@absl@@QAEXXZ ?UnlockSlow@Mutex@absl@@AAEXPAUSynchWaitParams@2@@Z ?Unparse@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@F@Z ?Unparse@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@G@Z @@ -1309,6 +1306,7 @@ EXPORTS ?__throw_length_error@?$vector@UUnrecognizedFlag@absl@@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@@__Cr@std@@CAXXZ ?__throw_length_error@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@__Cr@std@@CAXXZ ?__throw_length_error@?$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@@CAXXZ + ?combine_contiguous@MixingHashState@hash_internal@absl@@SA?AV123@V123@PBEI@Z ?cycle_clock_source_@CycleClock@base_internal@absl@@0U?$atomic@P6A_JXZ@__Cr@std@@A ?day_difference@impl@detail@cctz@time_internal@absl@@YA_J_JCC0CC@Z ?description@time_zone@cctz@time_internal@absl@@QBE?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@XZ @@ -1316,7 +1314,6 @@ EXPORTS ?destroy@?$__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?$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@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@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@@__Cr@std@@AAEXPAV?$__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@@Z ?effective_impl@time_zone@cctz@time_internal@absl@@ABEABVImpl@1234@XZ ?engines@?1??CrcAndCopy@CrcMemcpy@crc_internal@absl@@SA?AVcrc32c_t@4@PIAXPIBXIV54@_N@Z@4UArchSpecificEngines@234@B - ?find_first_non_full@container_internal@absl@@YA?AUFindInfo@12@ABVCommonFields@12@I@Z ?fixed_time_zone@cctz@time_internal@absl@@YA?AVtime_zone@123@ABV?$duration@_JV?$ratio@$00$00@__Cr@std@@@chrono@__Cr@std@@@Z ?format@detail@cctz@time_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@ABV567@ABV?$time_point@Vsystem_clock@chrono@__Cr@std@@V?$duration@_JV?$ratio@$00$00@__Cr@std@@@234@@chrono@67@ABV?$duration@_JV?$ratio@$00$0DINHOKEMGIAAA@@__Cr@std@@@967@ABVtime_zone@234@@Z ?from_chars@absl@@YA?AUfrom_chars_result@1@PBD0AAMW4chars_format@1@@Z @@ -1326,6 +1323,8 @@ EXPORTS ?kDefaultIterControl@container_internal@absl@@3W4ctrl_t@12@A ?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 ?local_time_zone@cctz@time_internal@absl@@YA?AVtime_zone@123@XZ + ?lock@Mutex@absl@@QAEXXZ + ?lock_shared@Mutex@absl@@QAEXXZ ?lookup@time_zone@cctz@time_internal@absl@@QBE?AUabsolute_lookup@1234@ABV?$time_point@Vsystem_clock@chrono@__Cr@std@@V?$duration@_JV?$ratio@$00$00@__Cr@std@@@234@@chrono@__Cr@std@@@Z ?lookup@time_zone@cctz@time_internal@absl@@QBE?AUcivil_lookup@1234@ABV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@detail@234@@Z ?memcasecmp@strings_internal@absl@@YAHPBD0I@Z @@ -1363,6 +1362,10 @@ EXPORTS ?status@BadStatusOrAccess@absl@@QBEABVStatus@2@XZ ?stream@OstreamView@LogMessage@log_internal@absl@@QAEAAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ ?transfer_unprobed_elements_to_next_capacity_fn@?$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@@CAXAAVCommonFields@23@PBW4ctrl_t@23@PAX2P6AX2EII@Z@Z + ?try_lock@Mutex@absl@@QAE_NXZ + ?try_lock_shared@Mutex@absl@@QAE_NXZ + ?unlock@Mutex@absl@@QAEXXZ + ?unlock_shared@Mutex@absl@@QAEXXZ ?utc_time_zone@cctz@time_internal@absl@@YA?AVtime_zone@123@XZ ?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 diff --git a/naiveproxy/src/third_party/angle/src/commit_id.py b/naiveproxy/src/third_party/angle/src/commit_id.py index 72352f1b18..bb1e2ce746 100755 --- a/naiveproxy/src/third_party/angle/src/commit_id.py +++ b/naiveproxy/src/third_party/angle/src/commit_id.py @@ -59,21 +59,48 @@ def unpack_ref(ref_file, ref_file_full_path, packed_refs_full_path): fout.write(git_hash + '\n') +# Get the files that GN action target angle_commit_id depends on. +# If any of these files changed, the build system should rerun the commit_id.py +# script to regenerate the angle_commit.h +# Case 1: git config extensions.refStorage == file (or empty) +# Case 1.1: .git/HEAD contains the hash. +# Return .git/HEAD +# Case 1.2: .git/HEAD contains non-hash: e.g. refs/heads/ +# Return .git/HEAD +# Return .git/refs/heads/ +# Case 2: git config extensions.refStorage == reftable +# In this case, HEAD will just store refs/heads/.invalid. If any reference is +# updated, .git/reftable/table.list will be updated. +# Return .git/reftable/table.list def get_git_inputs_and_maybe_unpack_ref(cwd): - # commit id should depend on angle's HEAD revision + # check git extensions.refStorage type + gitRefStorageType = grab_output('git config --get extensions.refStorage', cwd) + isRefTableStorage = gitRefStorageType and gitRefStorageType == "reftable" git_dir = os.path.normpath(os.path.join(cwd, get_git_dir(cwd))) head_file = os.path.join(git_dir, 'HEAD') - ret = [head_file] + ret = [] + # commit id should depend on angle's HEAD revision only if + # extensions.refStorage = file. + # If extensions.refStorage = reftable, .git/HEAD will always contains + # "refs/heads/.invalid", and we can't rely on it as an indicator of whether + # to rerun this script. + if not isRefTableStorage: + ret.append(head_file) git_common_dir = os.path.normpath(os.path.join(cwd, get_git_common_dir(cwd))) result = pathlib.Path(head_file).read_text().split() if result[0] == "ref:": - ref_file = result[1] - ref_file_full_path = os.path.join(git_common_dir, ref_file) + # if the extensions.refStorage is reftable, add .git/reftable/tables.list as an input to gn action target + if isRefTableStorage: + ret.append(os.path.join(git_common_dir, 'reftable', 'tables.list')) + else: + # if the extensions.refStorage is file, add loose ref file pointed by HEAD + ref_file = result[1] + ref_file_full_path = os.path.join(git_common_dir, ref_file) - if not os.path.exists(ref_file_full_path): - packed_refs_full_path = os.path.join(git_common_dir, 'packed-refs') - unpack_ref(ref_file, ref_file_full_path, packed_refs_full_path) - ret.append(os.path.join(git_common_dir, ref_file)) + if not os.path.exists(ref_file_full_path): + packed_refs_full_path = os.path.join(git_common_dir, 'packed-refs') + unpack_ref(ref_file, ref_file_full_path, packed_refs_full_path) + ret.append(os.path.join(git_common_dir, ref_file)) return ret diff --git a/naiveproxy/src/third_party/boringssl/BUILD.gn b/naiveproxy/src/third_party/boringssl/BUILD.gn index b962901a7d..31174ca1c7 100644 --- a/naiveproxy/src/third_party/boringssl/BUILD.gn +++ b/naiveproxy/src/third_party/boringssl/BUILD.gn @@ -155,10 +155,6 @@ component("boringssl") { configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ] - if (is_nacl) { - deps += [ "//native_client_sdk/src/libraries/nacl_io" ] - } - if (!is_debug && !(is_fuchsia && optimize_for_size)) { configs -= [ "//build/config/compiler:default_optimization" ] configs += [ "//build/config/compiler:optimize_max" ] diff --git a/naiveproxy/src/third_party/boringssl/README.chromium b/naiveproxy/src/third_party/boringssl/README.chromium index 1b0de3a78c..91fb1480cc 100644 --- a/naiveproxy/src/third_party/boringssl/README.chromium +++ b/naiveproxy/src/third_party/boringssl/README.chromium @@ -4,6 +4,7 @@ Version: git License: MIT, BSD-3-Clause, OpenSSL, ISC, SSLeay License File: src/LICENSE License Android Compatible: yes +CPEPrefix: cpe:/a:google:boringssl Security Critical: yes Shipped: yes diff --git a/naiveproxy/src/third_party/boringssl/src/CMakeLists.txt b/naiveproxy/src/third_party/boringssl/src/CMakeLists.txt index 6e1592db72..06ce07e955 100644 --- a/naiveproxy/src/third_party/boringssl/src/CMakeLists.txt +++ b/naiveproxy/src/third_party/boringssl/src/CMakeLists.txt @@ -43,7 +43,13 @@ include(GNUInstallDirs) set(INSTALL_ENABLED 1) -if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT CMAKE_CROSSCOMPILING) +if(CMAKE_VERSION VERSION_LESS 3.21 AND + CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + set(PROJECT_IS_TOP_LEVEL 1) +endif() + +if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT CMAKE_CROSSCOMPILING AND + BUILD_TESTING) find_package(PkgConfig QUIET) if (PkgConfig_FOUND) pkg_check_modules(LIBUNWIND libunwind-generic>=1.3.0) @@ -110,10 +116,6 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CLANG 1) endif() -if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten") - set(EMSCRIPTEN 1) -endif() - set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD 11) @@ -129,7 +131,7 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CLANG) # See http://llvm.org/viewvc/llvm-project?view=revision&revision=319116 set(C_CXX_FLAGS "${C_CXX_FLAGS} -W3 -Wno-unused-parameter -fmsc-version=1900") else() - if(EMSCRIPTEN) + if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten") # emscripten's emcc/clang does not accept the "-ggdb" flag. set(C_CXX_FLAGS "${C_CXX_FLAGS} -g") else() @@ -502,7 +504,7 @@ if(BUILD_TESTING) # Declare a dummy target to build all unit tests. Test targets should inject # themselves as dependencies next to the target definition. - add_custom_target(all_tests) + add_custom_target(boringssl_all_tests) add_subdirectory(ssl/test) endif() @@ -690,24 +692,24 @@ if(BUILD_TESTING) # it does. add_executable(urandom_test ${URANDOM_TEST_SOURCES}) target_link_libraries(urandom_test test_support_lib boringssl_gtest crypto) - add_dependencies(all_tests urandom_test) + add_dependencies(boringssl_all_tests urandom_test) add_executable(crypto_test ${CRYPTO_TEST_SOURCES}) target_link_libraries(crypto_test test_support_lib boringssl_gtest crypto) - add_dependencies(all_tests crypto_test) + add_dependencies(boringssl_all_tests crypto_test) add_executable(ssl_test ${SSL_TEST_SOURCES}) target_link_libraries(ssl_test test_support_lib boringssl_gtest ssl crypto) - add_dependencies(all_tests ssl_test) + add_dependencies(boringssl_all_tests ssl_test) add_executable(decrepit_test ${DECREPIT_TEST_SOURCES}) target_link_libraries(decrepit_test test_support_lib boringssl_gtest decrepit ssl crypto) - add_dependencies(all_tests decrepit_test) + add_dependencies(boringssl_all_tests decrepit_test) add_executable(pki_test ${PKI_TEST_SOURCES}) target_link_libraries(pki_test test_support_lib boringssl_gtest pki crypto) target_compile_options(pki_test PRIVATE ${PKI_CXX_FLAGS}) - add_dependencies(all_tests pki_test) + add_dependencies(boringssl_all_tests pki_test) add_executable(test_fips util/fipstools/test_fips.cc) target_link_libraries(test_fips crypto) @@ -778,28 +780,33 @@ if(BUILD_TESTING) set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS util/go_tests.txt) - if(GO_EXECUTABLE) - add_custom_target( - run_tests - COMMAND ${CMAKE_COMMAND} -E echo "Running Go tests" - COMMAND ${GO_EXECUTABLE} test ${GO_TESTS} - COMMAND ${CMAKE_COMMAND} -E echo - COMMAND ${CMAKE_COMMAND} -E echo "Running unit tests" - COMMAND ${GO_EXECUTABLE} run util/all_tests.go -build-dir - ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E echo - COMMAND ${CMAKE_COMMAND} -E echo "Running SSL tests" - COMMAND cd ssl/test/runner && - ${GO_EXECUTABLE} test -shim-path $ - ${HANDSHAKER_ARGS} ${RUNNER_ARGS} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS all_tests bssl_shim handshaker fips_specific_tests_if_any - USES_TERMINAL) - else() - add_custom_target( - run_tests - COMMAND ${CMAKE_COMMAND} -E echo "Running tests requires Go" - COMMAND ${CMAKE_COMMAND} -E false) + # CMake target names can clash when projects are imported with + # add_subdirectory. Only emit the run_tests target if we're the top-level + # target. See https://crbug.com/428112180. + if(PROJECT_IS_TOP_LEVEL) + if(GO_EXECUTABLE) + add_custom_target( + run_tests + COMMAND ${CMAKE_COMMAND} -E echo "Running Go tests" + COMMAND ${GO_EXECUTABLE} test ${GO_TESTS} + COMMAND ${CMAKE_COMMAND} -E echo + COMMAND ${CMAKE_COMMAND} -E echo "Running unit tests" + COMMAND ${GO_EXECUTABLE} run util/all_tests.go -build-dir + ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E echo + COMMAND ${CMAKE_COMMAND} -E echo "Running SSL tests" + COMMAND cd ssl/test/runner && + ${GO_EXECUTABLE} test -shim-path $ + ${HANDSHAKER_ARGS} ${RUNNER_ARGS} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS boringssl_all_tests bssl_shim handshaker fips_specific_tests_if_any + USES_TERMINAL) + else() + add_custom_target( + run_tests + COMMAND ${CMAKE_COMMAND} -E echo "Running tests requires Go" + COMMAND ${CMAKE_COMMAND} -E false) + endif() endif() endif() diff --git a/naiveproxy/src/third_party/boringssl/src/CONTRIBUTING.md b/naiveproxy/src/third_party/boringssl/src/CONTRIBUTING.md index 4d9279a60e..7f08cc3aa3 100644 --- a/naiveproxy/src/third_party/boringssl/src/CONTRIBUTING.md +++ b/naiveproxy/src/third_party/boringssl/src/CONTRIBUTING.md @@ -49,6 +49,13 @@ version of it. (Use the `git rebase` or `git commit --amend` commands.) For more detailed instructions, see the [Gerrit User Guide](https://gerrit-review.googlesource.com/Documentation/intro-user.html). +As an alternative to pushing to `refs/for/main`: if you have Chromium's +`depot_tools` installed, you can simply run `git cl upload` to upload a change. +This also has the advantage of automatically running any relevant `PRESUBMIT.py` +checks. See [depot_tools +documentation](https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools.html) +for more info. + ### Copyright headers New files contributed directly to BoringSSL should use the following copyright header, where `YEAR` is the year the file was added: diff --git a/naiveproxy/src/third_party/boringssl/src/MODULE.bazel b/naiveproxy/src/third_party/boringssl/src/MODULE.bazel index 04ed3671ee..8f57e976da 100644 --- a/naiveproxy/src/third_party/boringssl/src/MODULE.bazel +++ b/naiveproxy/src/third_party/boringssl/src/MODULE.bazel @@ -16,7 +16,7 @@ # the revision where we bump the version. module( name = "boringssl", - version = "0.20250514.0", + version = "0.20250701.0", compatibility_level = 2, ) @@ -31,6 +31,6 @@ module( # https://github.com/bazelbuild/bazel/issues/22187 is ever fixed, we can change # this. bazel_dep(name = "googletest", version = "1.17.0") -bazel_dep(name = "platforms", version = "0.0.11") -bazel_dep(name = "rules_cc", version = "0.1.1") +bazel_dep(name = "platforms", version = "1.0.0") +bazel_dep(name = "rules_cc", version = "0.1.2") bazel_dep(name = "rules_license", version = "1.0.0") diff --git a/naiveproxy/src/third_party/boringssl/src/MODULE.bazel.lock b/naiveproxy/src/third_party/boringssl/src/MODULE.bazel.lock index 8c463bab73..ecd314215e 100644 --- a/naiveproxy/src/third_party/boringssl/src/MODULE.bazel.lock +++ b/naiveproxy/src/third_party/boringssl/src/MODULE.bazel.lock @@ -16,7 +16,8 @@ "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58", - "https://bcr.bazel.build/modules/bazel_features/1.19.0/source.json": "d7bf14517c1b25b9d9c580b0f8795fceeae08a7590f507b76aace528e941375d", + "https://bcr.bazel.build/modules/bazel_features/1.28.0/MODULE.bazel": "4b4200e6cbf8fa335b2c3f43e1d6ef3e240319c33d43d60cc0fbd4b87ece299d", + "https://bcr.bazel.build/modules/bazel_features/1.28.0/source.json": "16a3fc5b4483cb307643791f5a4b7365fa98d2e70da7c378cdbde55f0c0b32cf", "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e", @@ -42,13 +43,14 @@ "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902", "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5", "https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f", - "https://bcr.bazel.build/modules/platforms/0.0.11/source.json": "f7e188b79ebedebfe75e9e1d098b8845226c7992b307e28e1496f23112e8fc29", "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee", "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37", "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615", "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814", "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d", "https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc", + "https://bcr.bazel.build/modules/platforms/1.0.0/MODULE.bazel": "f05feb42b48f1b3c225e4ccf351f367be0371411a803198ec34a389fb22aa580", + "https://bcr.bazel.build/modules/platforms/1.0.0/source.json": "f4ff1fd412e0246fd38c82328eb209130ead81d62dcd5a9e40910f867f733d96", "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7", "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c", "https://bcr.bazel.build/modules/protobuf/27.0/source.json": "1acf3d080c728d42f423fde5422fd0a1a24f44c15908124ce12363a253384193", @@ -67,8 +69,8 @@ "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f", "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", - "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513", - "https://bcr.bazel.build/modules/rules_cc/0.1.1/source.json": "d61627377bd7dd1da4652063e368d9366fc9a73920bfa396798ad92172cf645c", + "https://bcr.bazel.build/modules/rules_cc/0.1.2/MODULE.bazel": "557ddc3a96858ec0d465a87c0a931054d7dcfd6583af2c7ed3baf494407fd8d0", + "https://bcr.bazel.build/modules/rules_cc/0.1.2/source.json": "53fcb09b5816c83ca60d9d7493faf3bfaf410dfc2f15deb52d6ddd146b8d43f0", "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86", diff --git a/naiveproxy/src/third_party/boringssl/src/build.json b/naiveproxy/src/third_party/boringssl/src/build.json index 152a9915ee..a24ee0697c 100644 --- a/naiveproxy/src/third_party/boringssl/src/build.json +++ b/naiveproxy/src/third_party/boringssl/src/build.json @@ -483,6 +483,7 @@ "include/openssl/safestack.h", "include/openssl/service_indicator.h", "include/openssl/sha.h", + "include/openssl/sha2.h", "include/openssl/siphash.h", "include/openssl/slhdsa.h", "include/openssl/span.h", @@ -566,7 +567,10 @@ "third_party/fiat/p256_32.h", "third_party/fiat/p256_64.h", "third_party/fiat/p256_64_msvc.h", - "third_party/fiat/p256_bedrock.c.inc", + "third_party/fiat/p256_field.c.inc", + "third_party/fiat/p256_field_32.br.c.inc", + "third_party/fiat/p256_field_64.br.c.inc", + "third_party/fiat/p256_point.br.c.inc", "third_party/fiat/bedrock_unverified_bareminimum.c.inc", "third_party/fiat/bedrock_unverified_platform.c.inc" ], @@ -911,8 +915,10 @@ "crypto/hmac/hmac_tests.txt", "crypto/hpke/hpke_test_vectors.txt", "crypto/kyber/kyber_tests.txt", + "crypto/mldsa/mldsa_nist_keygen_44_tests.txt", "crypto/mldsa/mldsa_nist_keygen_65_tests.txt", "crypto/mldsa/mldsa_nist_keygen_87_tests.txt", + "crypto/mldsa/mldsa_nist_siggen_44_tests.txt", "crypto/mldsa/mldsa_nist_siggen_65_tests.txt", "crypto/mldsa/mldsa_nist_siggen_87_tests.txt", "crypto/mlkem/mlkem1024_decap_tests.txt", @@ -930,6 +936,7 @@ "crypto/pkcs7/test/*.pem", "crypto/pkcs8/test/*.p12", "crypto/poly1305/poly1305_tests.txt", + "crypto/rsa/test/*.pem", "crypto/siphash/siphash_tests.txt", "crypto/slhdsa/slhdsa_keygen.txt", "crypto/slhdsa/slhdsa_prehash.txt", diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/cipher/e_aesctrhmac.cc b/naiveproxy/src/third_party/boringssl/src/crypto/cipher/e_aesctrhmac.cc index fc4e0c5325..3f624e28b3 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/cipher/e_aesctrhmac.cc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/cipher/e_aesctrhmac.cc @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include "../fipsmodule/aes/internal.h" #include "../fipsmodule/cipher/internal.h" diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/cipher/internal.h b/naiveproxy/src/third_party/boringssl/src/crypto/cipher/internal.h index 3b0fb7c369..1a517bbfaa 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/cipher/internal.h +++ b/naiveproxy/src/third_party/boringssl/src/crypto/cipher/internal.h @@ -19,6 +19,7 @@ #include #include +#include #include "../internal.h" @@ -129,7 +130,7 @@ union chacha20_poly1305_seal_data { } out; }; -#if (defined(OPENSSL_X86_64) || defined(OPENSSL_AARCH64)) && \ +#if (defined(OPENSSL_X86_64) || defined(OPENSSL_AARCH64)) && \ !defined(OPENSSL_NO_ASM) static_assert(sizeof(union chacha20_poly1305_open_data) == 48, diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/curve25519/curve25519.cc b/naiveproxy/src/third_party/boringssl/src/crypto/curve25519/curve25519.cc index 3d4433721e..cbdb257622 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/curve25519/curve25519.cc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/curve25519/curve25519.cc @@ -24,7 +24,7 @@ #include #include -#include +#include #include "../internal.h" #include "internal.h" diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/curve25519/spake25519.cc b/naiveproxy/src/third_party/boringssl/src/crypto/curve25519/spake25519.cc index 5b58086d0b..2a3164b493 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/curve25519/spake25519.cc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/curve25519/spake25519.cc @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include "../fipsmodule/bn/internal.h" #include "../internal.h" diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/digest/digest_extra.cc b/naiveproxy/src/third_party/boringssl/src/crypto/digest/digest_extra.cc index 309b61c89e..4312142773 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/digest/digest_extra.cc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/digest/digest_extra.cc @@ -22,6 +22,7 @@ #include #include #include +#include #include "../asn1/internal.h" #include "../fipsmodule/digest/internal.h" diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/dsa/dsa.cc b/naiveproxy/src/third_party/boringssl/src/crypto/dsa/dsa.cc index 038052578b..c1dcd3bf76 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/dsa/dsa.cc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/dsa/dsa.cc @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include "../fipsmodule/bn/internal.h" #include "../fipsmodule/dh/internal.h" diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/evp/internal.h b/naiveproxy/src/third_party/boringssl/src/crypto/evp/internal.h index 6aa20dd92b..e5256b5d1c 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/evp/internal.h +++ b/naiveproxy/src/third_party/boringssl/src/crypto/evp/internal.h @@ -188,7 +188,10 @@ struct evp_pkey_ctx_st { bssl::UniquePtr peerkey; // operation contains one of the |EVP_PKEY_OP_*| values. int operation = EVP_PKEY_OP_UNDEFINED; - // Algorithm specific data + // Algorithm specific data. + // TODO(davidben): Since a |EVP_PKEY_CTX| never has its type change after + // creation, this should instead be a base class, with the algorithm-specific + // data on the subclass, coming from the same allocation. void *data = nullptr; } /* EVP_PKEY_CTX */; diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/evp/p_ec_asn1.cc b/naiveproxy/src/third_party/boringssl/src/crypto/evp/p_ec_asn1.cc index d89c6ebce3..d3e4b4051e 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/evp/p_ec_asn1.cc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/evp/p_ec_asn1.cc @@ -20,6 +20,7 @@ #include #include #include +#include #include "internal.h" @@ -284,3 +285,23 @@ EC_KEY *EVP_PKEY_get1_EC_KEY(const EVP_PKEY *pkey) { } return ec_key; } + +int EVP_PKEY_get_ec_curve_nid(const EVP_PKEY *pkey) { + const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey); + if (ec_key == nullptr) { + return NID_undef; + } + const EC_GROUP *group = EC_KEY_get0_group(ec_key); + if (group == nullptr) { + return NID_undef; + } + return EC_GROUP_get_curve_name(group); +} + +int EVP_PKEY_get_ec_point_conv_form(const EVP_PKEY *pkey) { + const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey); + if (ec_key == nullptr) { + return 0; + } + return EC_KEY_get_conv_form(ec_key); +} diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/evp/p_rsa.cc b/naiveproxy/src/third_party/boringssl/src/crypto/evp/p_rsa.cc index 4b47ee31ba..f2bb22b6a8 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/evp/p_rsa.cc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/evp/p_rsa.cc @@ -24,50 +24,38 @@ #include #include #include +#include #include "../internal.h" +#include "../mem_internal.h" #include "../rsa/internal.h" #include "internal.h" -typedef struct { - // Key gen parameters - int nbits; - BIGNUM *pub_exp; - // RSA padding mode - int pad_mode; - // message digest - const EVP_MD *md; - // message digest for MGF1 - const EVP_MD *mgf1md; - // PSS salt length - int saltlen; - // tbuf is a buffer which is either NULL, or is the size of the RSA modulus. - // It's used to store the output of RSA operations. - uint8_t *tbuf; - // OAEP label - uint8_t *oaep_label; - size_t oaep_labellen; -} RSA_PKEY_CTX; +namespace { -typedef struct { - uint8_t *data; - size_t len; -} RSA_OAEP_LABEL_PARAMS; +struct RSA_PKEY_CTX { + // Key gen parameters + int nbits = 2048; + bssl::UniquePtr pub_exp; + // RSA padding mode + int pad_mode = RSA_PKCS1_PADDING; + // message digest + const EVP_MD *md = nullptr; + // message digest for MGF1 + const EVP_MD *mgf1md = nullptr; + // PSS salt length + int saltlen = RSA_PSS_SALTLEN_DIGEST; + bssl::Array oaep_label; +}; static int pkey_rsa_init(EVP_PKEY_CTX *ctx) { - RSA_PKEY_CTX *rctx = - reinterpret_cast(OPENSSL_zalloc(sizeof(RSA_PKEY_CTX))); + RSA_PKEY_CTX *rctx = bssl::New(); if (!rctx) { return 0; } - rctx->nbits = 2048; - rctx->pad_mode = RSA_PKCS1_PADDING; - rctx->saltlen = RSA_PSS_SALTLEN_AUTO; - ctx->data = rctx; - return 1; } @@ -80,7 +68,7 @@ static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) { dctx = reinterpret_cast(dst->data); dctx->nbits = sctx->nbits; if (sctx->pub_exp) { - dctx->pub_exp = BN_dup(sctx->pub_exp); + dctx->pub_exp.reset(BN_dup(sctx->pub_exp.get())); if (!dctx->pub_exp) { return 0; } @@ -90,42 +78,15 @@ static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) { dctx->md = sctx->md; dctx->mgf1md = sctx->mgf1md; dctx->saltlen = sctx->saltlen; - if (sctx->oaep_label) { - OPENSSL_free(dctx->oaep_label); - dctx->oaep_label = reinterpret_cast( - OPENSSL_memdup(sctx->oaep_label, sctx->oaep_labellen)); - if (!dctx->oaep_label) { - return 0; - } - dctx->oaep_labellen = sctx->oaep_labellen; + if (!dctx->oaep_label.CopyFrom(sctx->oaep_label)) { + return 0; } return 1; } static void pkey_rsa_cleanup(EVP_PKEY_CTX *ctx) { - RSA_PKEY_CTX *rctx = reinterpret_cast(ctx->data); - - if (rctx == NULL) { - return; - } - - BN_free(rctx->pub_exp); - OPENSSL_free(rctx->tbuf); - OPENSSL_free(rctx->oaep_label); - OPENSSL_free(rctx); -} - -static int setup_tbuf(RSA_PKEY_CTX *ctx, EVP_PKEY_CTX *pk) { - if (ctx->tbuf) { - return 1; - } - ctx->tbuf = reinterpret_cast( - OPENSSL_malloc(EVP_PKEY_size(pk->pkey.get()))); - if (!ctx->tbuf) { - return 0; - } - return 1; + bssl::Delete(reinterpret_cast(ctx->data)); } static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *siglen, @@ -187,12 +148,13 @@ static int pkey_rsa_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig, size_t siglen, size_t rslen; const size_t key_len = EVP_PKEY_size(ctx->pkey.get()); - if (!setup_tbuf(rctx, ctx) || - !RSA_verify_raw(rsa, &rslen, rctx->tbuf, key_len, sig, siglen, + bssl::Array tbuf; + if (!tbuf.InitForOverwrite(key_len) || + !RSA_verify_raw(rsa, &rslen, tbuf.data(), tbuf.size(), sig, siglen, rctx->pad_mode)) { return 0; } - if (rslen != tbslen || CRYPTO_memcmp(tbs, rctx->tbuf, rslen) != 0) { + if (rslen != tbslen || CRYPTO_memcmp(tbs, tbuf.data(), rslen) != 0) { OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_SIGNATURE); return 0; } @@ -232,33 +194,28 @@ static int pkey_rsa_verify_recover(EVP_PKEY_CTX *ctx, uint8_t *out, uint8_t *asn1_prefix; size_t asn1_prefix_len; int asn1_prefix_allocated; - if (!setup_tbuf(rctx, ctx) || - !RSA_add_pkcs1_prefix(&asn1_prefix, &asn1_prefix_len, + if (!RSA_add_pkcs1_prefix(&asn1_prefix, &asn1_prefix_len, &asn1_prefix_allocated, EVP_MD_type(rctx->md), kDummyHash, hash_len)) { return 0; } + bssl::UniquePtr free_asn1_prefix(asn1_prefix_allocated ? asn1_prefix + : nullptr); + bssl::Array tbuf; size_t rslen; - int ok = 1; - if (!RSA_verify_raw(rsa, &rslen, rctx->tbuf, key_len, sig, sig_len, + if (!tbuf.InitForOverwrite(key_len) || + !RSA_verify_raw(rsa, &rslen, tbuf.data(), tbuf.size(), sig, sig_len, RSA_PKCS1_PADDING) || rslen != asn1_prefix_len || // Compare all but the hash suffix. - CRYPTO_memcmp(rctx->tbuf, asn1_prefix, asn1_prefix_len - hash_len) != 0) { - ok = 0; - } - - if (asn1_prefix_allocated) { - OPENSSL_free(asn1_prefix); - } - - if (!ok) { + CRYPTO_memcmp(tbuf.data(), asn1_prefix, asn1_prefix_len - hash_len) != + 0) { return 0; } if (out != NULL) { - OPENSSL_memcpy(out, rctx->tbuf + rslen - hash_len, hash_len); + OPENSSL_memcpy(out, tbuf.data() + rslen - hash_len, hash_len); } *out_len = hash_len; @@ -282,11 +239,12 @@ static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen, } if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) { - if (!setup_tbuf(rctx, ctx) || - !RSA_padding_add_PKCS1_OAEP_mgf1(rctx->tbuf, key_len, in, inlen, - rctx->oaep_label, rctx->oaep_labellen, - rctx->md, rctx->mgf1md) || - !RSA_encrypt(rsa, outlen, out, *outlen, rctx->tbuf, key_len, + bssl::Array tbuf; + if (!tbuf.InitForOverwrite(key_len) || + !RSA_padding_add_PKCS1_OAEP_mgf1( + tbuf.data(), tbuf.size(), in, inlen, rctx->oaep_label.data(), + rctx->oaep_label.size(), rctx->md, rctx->mgf1md) || + !RSA_encrypt(rsa, outlen, out, *outlen, tbuf.data(), tbuf.size(), RSA_NO_PADDING)) { return 0; } @@ -313,13 +271,15 @@ static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen, } if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) { + bssl::Array tbuf; size_t padded_len; - if (!setup_tbuf(rctx, ctx) || - !RSA_decrypt(rsa, &padded_len, rctx->tbuf, key_len, in, inlen, + if (!tbuf.InitForOverwrite(key_len) || + !RSA_decrypt(rsa, &padded_len, tbuf.data(), tbuf.size(), in, inlen, RSA_NO_PADDING) || - !RSA_padding_check_PKCS1_OAEP_mgf1( - out, outlen, key_len, rctx->tbuf, padded_len, rctx->oaep_label, - rctx->oaep_labellen, rctx->md, rctx->mgf1md)) { + !RSA_padding_check_PKCS1_OAEP_mgf1(out, outlen, key_len, tbuf.data(), + padded_len, rctx->oaep_label.data(), + rctx->oaep_label.size(), rctx->md, + rctx->mgf1md)) { return 0; } return 1; @@ -365,8 +325,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { OPENSSL_PUT_ERROR(EVP, EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE); return 0; } - if ((p1 == RSA_PKCS1_PSS_PADDING || p1 == RSA_PKCS1_OAEP_PADDING) && - rctx->md == NULL) { + if (p1 == RSA_PKCS1_OAEP_PADDING && rctx->md == NULL) { rctx->md = EVP_sha1(); } rctx->pad_mode = p1; @@ -385,7 +344,9 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN) { *(int *)p2 = rctx->saltlen; } else { - if (p1 < -2) { + // Negative salt lengths are special values. + if (p1 < 0 && + (p1 != RSA_PSS_SALTLEN_DIGEST && p1 != RSA_PSS_SALTLEN_AUTO)) { return 0; } rctx->saltlen = p1; @@ -404,8 +365,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { if (!p2) { return 0; } - BN_free(rctx->pub_exp); - rctx->pub_exp = reinterpret_cast(p2); + rctx->pub_exp.reset(reinterpret_cast(p2)); return 1; case EVP_PKEY_CTRL_RSA_OAEP_MD: @@ -455,11 +415,10 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PADDING_MODE); return 0; } - OPENSSL_free(rctx->oaep_label); - RSA_OAEP_LABEL_PARAMS *params = - reinterpret_cast(p2); - rctx->oaep_label = params->data; - rctx->oaep_labellen = params->len; + // |EVP_PKEY_CTRL_RSA_OAEP_LABEL| takes ownership of |label|'s underlying + // buffer (via |Reset|), but only on success. + auto *label = reinterpret_cast *>(p2); + rctx->oaep_label.Reset(label->data(), label->size()); return 1; } @@ -468,7 +427,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PADDING_MODE); return 0; } - CBS_init((CBS *)p2, rctx->oaep_label, rctx->oaep_labellen); + *reinterpret_cast(p2) = CBS(rctx->oaep_label); return 1; default: @@ -478,29 +437,29 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { } static int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { - RSA *rsa = NULL; RSA_PKEY_CTX *rctx = reinterpret_cast(ctx->data); - if (!rctx->pub_exp) { - rctx->pub_exp = BN_new(); - if (!rctx->pub_exp || !BN_set_word(rctx->pub_exp, RSA_F4)) { + rctx->pub_exp.reset(BN_new()); + if (!rctx->pub_exp || !BN_set_word(rctx->pub_exp.get(), RSA_F4)) { return 0; } } - rsa = RSA_new(); + bssl::UniquePtr rsa(RSA_new()); if (!rsa) { return 0; } - if (!RSA_generate_key_ex(rsa, rctx->nbits, rctx->pub_exp, NULL)) { - RSA_free(rsa); + if (!RSA_generate_key_ex(rsa.get(), rctx->nbits, rctx->pub_exp.get(), + nullptr)) { return 0; } - EVP_PKEY_assign_RSA(pkey, rsa); + EVP_PKEY_assign_RSA(pkey, rsa.release()); return 1; } +} // namespace + const EVP_PKEY_METHOD rsa_pkey_meth = { EVP_PKEY_RSA, pkey_rsa_init, @@ -588,9 +547,9 @@ int EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) { int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, uint8_t *label, size_t label_len) { - RSA_OAEP_LABEL_PARAMS params = {label, label_len}; + bssl::Span span(label, label_len); return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, - EVP_PKEY_CTRL_RSA_OAEP_LABEL, 0, ¶ms); + EVP_PKEY_CTRL_RSA_OAEP_LABEL, 0, &span); } int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bcm.cc b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bcm.cc index e862014e4f..227e5242de 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bcm.cc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bcm.cc @@ -26,7 +26,7 @@ #include #include -#include +#include #include "../bcm_support.h" #include "../internal.h" diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bcm_interface.h b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bcm_interface.h index b11a558d75..e60458c24d 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bcm_interface.h +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bcm_interface.h @@ -529,6 +529,140 @@ OPENSSL_EXPORT bcm_status BCM_mldsa87_verify_internal( OPENSSL_EXPORT bcm_status BCM_mldsa87_marshal_private_key( CBB *out, const struct BCM_mldsa87_private_key *private_key); +// BCM_MLDSA44_PRIVATE_KEY_BYTES is the number of bytes in an encoded ML-DSA-44 +// private key. +#define BCM_MLDSA44_PRIVATE_KEY_BYTES 2560 + +// BCM_MLDSA44_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-DSA-44 +// public key. +#define BCM_MLDSA44_PUBLIC_KEY_BYTES 1312 + +// BCM_MLDSA44_SIGNATURE_BYTES is the number of bytes in an encoded ML-DSA-44 +// signature. +#define BCM_MLDSA44_SIGNATURE_BYTES 2420 + +struct BCM_mldsa44_private_key { + union { + uint8_t bytes[32 + 32 + 64 + 256 * 4 * (4 + 4 + 4)]; + uint32_t alignment; + } opaque; +}; + +struct BCM_mldsa44_public_key { + union { + uint8_t bytes[32 + 64 + 256 * 4 * 4]; + uint32_t alignment; + } opaque; +}; + +struct BCM_mldsa44_prehash { + union { + uint8_t bytes[200 + 4 + 4 + 4 * sizeof(size_t)]; + uint64_t alignment; + } opaque; +}; + +OPENSSL_EXPORT bcm_status BCM_mldsa44_generate_key( + uint8_t out_encoded_public_key[BCM_MLDSA44_PUBLIC_KEY_BYTES], + uint8_t out_seed[BCM_MLDSA_SEED_BYTES], + struct BCM_mldsa44_private_key *out_private_key); + +OPENSSL_EXPORT bcm_status BCM_mldsa44_private_key_from_seed( + struct BCM_mldsa44_private_key *out_private_key, + const uint8_t seed[BCM_MLDSA_SEED_BYTES]); + +OPENSSL_EXPORT bcm_status BCM_mldsa44_public_from_private( + struct BCM_mldsa44_public_key *out_public_key, + const struct BCM_mldsa44_private_key *private_key); + +OPENSSL_EXPORT bcm_status +BCM_mldsa44_check_key_fips(struct BCM_mldsa44_private_key *private_key); + +OPENSSL_EXPORT bcm_status BCM_mldsa44_generate_key_fips( + uint8_t out_encoded_public_key[BCM_MLDSA44_PUBLIC_KEY_BYTES], + uint8_t out_seed[BCM_MLDSA_SEED_BYTES], + struct BCM_mldsa44_private_key *out_private_key); + +OPENSSL_EXPORT bcm_status BCM_mldsa44_private_key_from_seed_fips( + struct BCM_mldsa44_private_key *out_private_key, + const uint8_t seed[BCM_MLDSA_SEED_BYTES]); + +OPENSSL_EXPORT bcm_status BCM_mldsa44_sign( + uint8_t out_encoded_signature[BCM_MLDSA44_SIGNATURE_BYTES], + const struct BCM_mldsa44_private_key *private_key, const uint8_t *msg, + size_t msg_len, const uint8_t *context, size_t context_len); + +OPENSSL_EXPORT bcm_status +BCM_mldsa44_verify(const struct BCM_mldsa44_public_key *public_key, + const uint8_t *signature, const uint8_t *msg, size_t msg_len, + const uint8_t *context, size_t context_len); + +OPENSSL_EXPORT void BCM_mldsa44_prehash_init( + struct BCM_mldsa44_prehash *out_prehash_ctx, + const struct BCM_mldsa44_public_key *public_key, const uint8_t *context, + size_t context_len); + +OPENSSL_EXPORT void BCM_mldsa44_prehash_update( + struct BCM_mldsa44_prehash *inout_prehash_ctx, const uint8_t *msg, + size_t msg_len); + +OPENSSL_EXPORT void BCM_mldsa44_prehash_finalize( + uint8_t out_msg_rep[BCM_MLDSA_MU_BYTES], + struct BCM_mldsa44_prehash *inout_prehash_ctx); + +OPENSSL_EXPORT bcm_status BCM_mldsa44_sign_message_representative( + uint8_t out_encoded_signature[BCM_MLDSA44_SIGNATURE_BYTES], + const struct BCM_mldsa44_private_key *private_key, + const uint8_t msg_rep[BCM_MLDSA_MU_BYTES]); + +OPENSSL_EXPORT bcm_status BCM_mldsa44_marshal_public_key( + CBB *out, const struct BCM_mldsa44_public_key *public_key); + +OPENSSL_EXPORT bcm_status BCM_mldsa44_parse_public_key( + struct BCM_mldsa44_public_key *public_key, CBS *in); + +OPENSSL_EXPORT bcm_status BCM_mldsa44_parse_private_key( + struct BCM_mldsa44_private_key *private_key, CBS *in); + +// BCM_mldsa44_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. +OPENSSL_EXPORT bcm_status BCM_mldsa44_generate_key_external_entropy( + uint8_t out_encoded_public_key[BCM_MLDSA44_PUBLIC_KEY_BYTES], + struct BCM_mldsa44_private_key *out_private_key, + const uint8_t entropy[BCM_MLDSA_SEED_BYTES]); + +OPENSSL_EXPORT bcm_status BCM_mldsa44_generate_key_external_entropy_fips( + uint8_t out_encoded_public_key[BCM_MLDSA44_PUBLIC_KEY_BYTES], + struct BCM_mldsa44_private_key *out_private_key, + const uint8_t entropy[BCM_MLDSA_SEED_BYTES]); + +// BCM_mldsa44_sign_internal signs |msg| using |private_key| and writes the +// signature to |out_encoded_signature|. The |context_prefix| and |context| are +// prefixed to the message, in that order, before signing. The |randomizer| +// value can be set to zero bytes in order to make a deterministic signature, or +// else filled with entropy for the usual |MLDSA_sign| behavior. +OPENSSL_EXPORT bcm_status BCM_mldsa44_sign_internal( + uint8_t out_encoded_signature[BCM_MLDSA44_SIGNATURE_BYTES], + const struct BCM_mldsa44_private_key *private_key, const uint8_t *msg, + size_t msg_len, const uint8_t *context_prefix, size_t context_prefix_len, + const uint8_t *context, size_t context_len, + const uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES]); + +// BCM_mldsa44_verify_internal verifies that |encoded_signature| is a valid +// signature of |msg| by |public_key|. The |context_prefix| and |context| are +// prefixed to the message before verification, in that order. +OPENSSL_EXPORT bcm_status BCM_mldsa44_verify_internal( + const struct BCM_mldsa44_public_key *public_key, + const uint8_t encoded_signature[BCM_MLDSA44_SIGNATURE_BYTES], + const uint8_t *msg, size_t msg_len, const uint8_t *context_prefix, + size_t context_prefix_len, const uint8_t *context, size_t context_len); + +// BCM_mldsa44_marshal_private_key serializes |private_key| to |out| in the +// NIST format for ML-DSA-44 private keys. +OPENSSL_EXPORT bcm_status BCM_mldsa44_marshal_private_key( + CBB *out, const struct BCM_mldsa44_private_key *private_key); + // ML-KEM // diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/asm/armv8-mont.pl b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/asm/armv8-mont.pl index fe4d8cf3b5..80e0eeae6d 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/asm/armv8-mont.pl +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/asm/armv8-mont.pl @@ -60,7 +60,7 @@ open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; $lo1,$hi1,$nj,$m1,$nlo,$nhi, $ovf, $i,$j,$tp,$tj) = map("x$_",6..17,19..24); -# void bn_mul_mont( +# void bn_mul_mont_words( $rp="x0"; # BN_ULONG *rp, $ap="x1"; # const BN_ULONG *ap, $bp="x2"; # const BN_ULONG *bp, @@ -71,10 +71,10 @@ $num="x5"; # size_t num); $code.=<<___; .text -.globl bn_mul_mont -.type bn_mul_mont,%function +.globl bn_mul_mont_words +.type bn_mul_mont_words,%function .align 5 -bn_mul_mont: +bn_mul_mont_words: AARCH64_SIGN_LINK_REGISTER tst $num,#7 b.eq __bn_sqr8x_mont @@ -275,7 +275,7 @@ bn_mul_mont: ldr x29,[sp],#64 AARCH64_VALIDATE_LINK_REGISTER ret -.size bn_mul_mont,.-bn_mul_mont +.size bn_mul_mont_words,.-bn_mul_mont_words ___ { ######################################################################## @@ -292,7 +292,7 @@ $code.=<<___; .align 5 __bn_sqr8x_mont: // Not adding AARCH64_SIGN_LINK_REGISTER here because __bn_sqr8x_mont is jumped to - // only from bn_mul_mont which has already signed the return address. + // only from bn_mul_mont_words which has already signed the return address. cmp $ap,$bp b.ne __bn_mul4x_mont .Lsqr8x_mont: @@ -1075,7 +1075,7 @@ $code.=<<___; .align 5 __bn_mul4x_mont: // Not adding AARCH64_SIGN_LINK_REGISTER here because __bn_mul4x_mont is jumped to - // only from bn_mul_mont or __bn_mul8x_mont which have already signed the + // only from bn_mul_mont_words or __bn_mul8x_mont which have already signed the // return address. stp x29,x30,[sp,#-128]! add x29,sp,#0 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 c3e30cbe43..59cfea67b9 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 @@ -49,7 +49,7 @@ open STDOUT,">$output"; $sse2=1; -&function_begin("bn_mul_mont"); +&function_begin("bn_mul_mont_words"); $i="edx"; $j="ecx"; @@ -325,7 +325,7 @@ $mask="mm7"; &mov ("esp",$_sp); # pull saved stack pointer # No return value -&function_end("bn_mul_mont"); +&function_end("bn_mul_mont_words"); &asciz("Montgomery Multiplication for x86, CRYPTOGAMS by "); diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/exponentiation.cc.inc b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/exponentiation.cc.inc index 205f4b4329..a6c7d55309 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/exponentiation.cc.inc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/exponentiation.cc.inc @@ -560,9 +560,9 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, // |bn_mul_mont_gather5| and |bn_power5| implement the "almost" reduction // variant, so the values here may not be fully reduced. They are bounded by R // (i.e. they fit in |top| words), not |m|. Additionally, we pass these - // "almost" reduced inputs into |bn_mul_mont|, which implements the normal - // reduction variant. Given those inputs, |bn_mul_mont| may not give reduced - // output, but it will still produce "almost" reduced output. + // "almost" reduced inputs into |bn_mul_mont_words|, which implements the + // normal reduction variant. Given those inputs, |bn_mul_mont_words| may not + // give reduced output, but it will still produce "almost" reduced output. // // TODO(davidben): Using "almost" reduction complicates analysis of this code, // and its interaction with other parts of the project. Determine whether this @@ -578,12 +578,12 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, const BN_ULONG *n0 = mont->n0; bn_scatter5(tmp.d, top, powerbuf, 0); bn_scatter5(am.d, am.width, powerbuf, 1); - bn_mul_mont(tmp.d, am.d, am.d, np, n0, top); + bn_mul_mont_words(tmp.d, am.d, am.d, np, n0, top); bn_scatter5(tmp.d, top, powerbuf, 2); // Square to compute powers of two. for (i = 4; i < 32; i *= 2) { - bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_words(tmp.d, tmp.d, tmp.d, np, n0, top); bn_scatter5(tmp.d, top, powerbuf, i); } // Compute odd powers |i| based on |i - 1|, then all powers |i * 2^j|. @@ -591,7 +591,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1); bn_scatter5(tmp.d, top, powerbuf, i); for (int j = 2 * i; j < 32; j *= 2) { - bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_words(tmp.d, tmp.d, tmp.d, np, n0, top); bn_scatter5(tmp.d, top, powerbuf, j); } } @@ -614,11 +614,11 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, wvalue = (wvalue << 1) + BN_is_bit_set(p, bits); } - bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); - bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); - bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); - bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); - bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_words(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_words(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_words(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_words(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_words(tmp.d, tmp.d, tmp.d, np, n0, top); bn_mul_mont_gather5(tmp.d, tmp.d, powerbuf, np, n0, top, wvalue); } } else { diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/generic.cc.inc b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/generic.cc.inc index 9a42fa0a42..337dc359e0 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/generic.cc.inc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/generic.cc.inc @@ -44,24 +44,24 @@ do { \ BN_ULLONG t; \ t = (BN_ULLONG)(w) * (a) + (r) + (c); \ - (r) = Lw(t); \ - (c) = Hw(t); \ + (r) = (BN_ULONG)(t); \ + (c) = (BN_ULONG)((t) >> BN_BITS2); \ } while (0) -#define mul(r, a, w, c) \ - do { \ - BN_ULLONG t; \ - t = (BN_ULLONG)(w) * (a) + (c); \ - (r) = Lw(t); \ - (c) = Hw(t); \ +#define mul(r, a, w, c) \ + do { \ + BN_ULLONG t; \ + t = (BN_ULLONG)(w) * (a) + (c); \ + (r) = (BN_ULONG)(t); \ + (c) = (BN_ULONG)((t) >> BN_BITS2); \ } while (0) -#define sqr(r0, r1, a) \ - do { \ - BN_ULLONG t; \ - t = (BN_ULLONG)(a) * (a); \ - (r0) = Lw(t); \ - (r1) = Hw(t); \ +#define sqr(r0, r1, a) \ + do { \ + BN_ULLONG t; \ + t = (BN_ULLONG)(a) * (a); \ + (r0) = (BN_ULONG)(t); \ + (r1) = (BN_ULONG)((t) >> BN_BITS2); \ } while (0) #else @@ -198,8 +198,8 @@ void bn_sqr_add_words(BN_ULONG *r, const BN_ULONG *a, size_t n) { BN_ULONG hi; \ BN_ULLONG t = (BN_ULLONG)(a) * (b); \ t += (c0); /* no carry */ \ - (c0) = (BN_ULONG)Lw(t); \ - hi = (BN_ULONG)Hw(t); \ + (c0) = (BN_ULONG)(t); \ + hi = (BN_ULONG)((t) >> BN_BITS2); \ (c1) += (hi); \ (c2) += (c1) < hi; \ } while (0) @@ -209,13 +209,13 @@ void bn_sqr_add_words(BN_ULONG *r, const BN_ULONG *a, size_t n) { BN_ULONG hi; \ BN_ULLONG t = (BN_ULLONG)(a) * (b); \ BN_ULLONG tt = t + (c0); /* no carry */ \ - (c0) = (BN_ULONG)Lw(tt); \ - hi = (BN_ULONG)Hw(tt); \ + (c0) = (BN_ULONG)(tt); \ + hi = (BN_ULONG)((tt) >> BN_BITS2); \ (c1) += hi; \ (c2) += (c1) < hi; \ t += (c0); /* no carry */ \ - (c0) = (BN_ULONG)Lw(t); \ - hi = (BN_ULONG)Hw(t); \ + (c0) = (BN_ULONG)(t); \ + hi = (BN_ULONG)((t) >> BN_BITS2); \ (c1) += hi; \ (c2) += (c1) < hi; \ } while (0) @@ -225,8 +225,8 @@ void bn_sqr_add_words(BN_ULONG *r, const BN_ULONG *a, size_t n) { BN_ULONG hi; \ BN_ULLONG t = (BN_ULLONG)(a)[i] * (a)[i]; \ t += (c0); /* no carry */ \ - (c0) = (BN_ULONG)Lw(t); \ - hi = (BN_ULONG)Hw(t); \ + (c0) = (BN_ULONG)(t); \ + hi = (BN_ULONG)((t) >> BN_BITS2); \ (c1) += hi; \ (c2) += (c1) < hi; \ } while (0) 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 1ec2562508..3619ddd73b 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 @@ -105,11 +105,6 @@ extern "C" { sizeof(x) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA \ } -#if defined(BN_ULLONG) -#define Lw(t) ((BN_ULONG)(t)) -#define Hw(t) ((BN_ULONG)((t) >> BN_BITS2)) -#endif - // bn_minimal_width returns the minimal number of words needed to represent // |bn|. int bn_minimal_width(const BIGNUM *bn); @@ -268,16 +263,27 @@ int bn_rand_secret_range(BIGNUM *r, int *out_is_uniform, BN_ULONG min_inclusive, // |BIGNUM|s, in |bn_wexpand|, but the exactfloat library needs to create 8 MiB // values for other operations. // -// TODO(crbug.com/402677800): This is not quite tight enough to limit the -// |bn_mul_mont| allocation to under a page. Lower the maximum RSA key and then -// lower this to match. -#define BN_MONTGOMERY_MAX_WORDS (16384 / BN_BITS2) +// This limit is set so that one number fits within 1 KiB, giving room to +// allocate a few of them on the stack in |bn_mul_mont_words| without exceeding +// a page (4 KiB). It is also set to limit the DoS impact of large RSA, DH, and +// DSA keys, which scale cubically. +#define BN_MONTGOMERY_MAX_WORDS (8192 / BN_BITS2) + +struct bn_mont_ctx_st { + // RR is R^2, reduced modulo |N|. It is used to convert to Montgomery form. It + // is guaranteed to have the same width as |N|. + BIGNUM RR; + // N is the modulus. It is always stored in minimal form, so |N.width| + // determines R. + BIGNUM N; + BN_ULONG n0[BN_MONT_CTX_N0_LIMBS]; // least significant words of (R*Ri-1)/N +}; #if !defined(OPENSSL_NO_ASM) && \ (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \ defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) #define OPENSSL_BN_ASM_MONT -// bn_mul_mont writes |ap| * |bp| mod |np| to |rp|, each |num| words +// bn_mul_mont_words writes |ap| * |bp| mod |np| to |rp|, each |num| words // long. Inputs and outputs are in Montgomery form. |n0| is a pointer to the // corresponding field in |BN_MONT_CTX|. // @@ -295,8 +301,9 @@ int bn_rand_secret_range(BIGNUM *r, int *out_is_uniform, BN_ULONG min_inclusive, // // See also discussion in |ToWord| in abi_test.h for notes on smaller-than-word // inputs. -void bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, - const BN_ULONG *np, const BN_ULONG *n0, size_t num); +void bn_mul_mont_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, + const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], size_t num); #if defined(OPENSSL_X86_64) inline int bn_mulx_adx_capable(void) { @@ -304,30 +311,36 @@ inline int bn_mulx_adx_capable(void) { return CRYPTO_is_BMI2_capable() && CRYPTO_is_ADX_capable(); } void bn_mul_mont_nohw(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, - const BN_ULONG *np, const BN_ULONG *n0, size_t num); + const BN_ULONG *np, + const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], size_t num); inline int bn_mul4x_mont_capable(size_t num) { return num >= 8 && (num & 3) == 0; } void bn_mul4x_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, - const BN_ULONG *np, const BN_ULONG *n0, size_t num); + const BN_ULONG *np, const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], + size_t num); inline int bn_mulx4x_mont_capable(size_t num) { return bn_mul4x_mont_capable(num) && bn_mulx_adx_capable(); } void bn_mulx4x_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, - const BN_ULONG *np, const BN_ULONG *n0, size_t num); + const BN_ULONG *np, const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], + size_t num); inline int bn_sqr8x_mont_capable(size_t num) { return num >= 8 && (num & 7) == 0; } void bn_sqr8x_mont(BN_ULONG *rp, const BN_ULONG *ap, BN_ULONG mulx_adx_capable, - const BN_ULONG *np, const BN_ULONG *n0, size_t num); + const BN_ULONG *np, const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], + size_t num); #elif defined(OPENSSL_ARM) inline int bn_mul8x_mont_neon_capable(size_t num) { return (num & 7) == 0 && CRYPTO_is_NEON_capable(); } void bn_mul8x_mont_neon(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, - const BN_ULONG *np, const BN_ULONG *n0, size_t num); + const BN_ULONG *np, + const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], size_t num); void bn_mul_mont_nohw(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, - const BN_ULONG *np, const BN_ULONG *n0, size_t num); + const BN_ULONG *np, + const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], size_t num); #endif #endif // OPENSSL_BN_ASM_MONT @@ -340,7 +353,8 @@ void bn_mul_mont_nohw(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, 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); + const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], int num, + int power); inline int bn_mulx4x_mont_gather5_capable(int num) { return bn_mul4x_mont_gather5_capable(num) && CRYPTO_is_ADX_capable() && @@ -348,11 +362,13 @@ inline int bn_mulx4x_mont_gather5_capable(int num) { } 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); + const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], 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); + const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], 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 @@ -368,7 +384,8 @@ void bn_gather5(BN_ULONG *out, size_t num, const BN_ULONG *table, size_t 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); + const BN_ULONG *np, const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], + int num, int power); inline int bn_power5_capable(int num) { return (num & 7) == 0; } @@ -377,7 +394,8 @@ inline int bn_powerx5_capable(int num) { 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); + const BN_ULONG *np, const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], + int num, int power); #endif // !OPENSSL_NO_ASM && OPENSSL_X86_64 diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/montgomery.cc.inc b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/montgomery.cc.inc index aac5af837e..6281b299ed 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/montgomery.cc.inc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/montgomery.cc.inc @@ -64,8 +64,9 @@ BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, const BN_MONT_CTX *from) { if (!BN_copy(&to->RR, &from->RR) || !BN_copy(&to->N, &from->N)) { return NULL; } - to->n0[0] = from->n0[0]; - to->n0[1] = from->n0[1]; + for (size_t i = 0; i < BN_MONT_CTX_N0_LIMBS; i++) { + to->n0[i] = from->n0[i]; + } return to; } @@ -111,8 +112,6 @@ static int bn_mont_ctx_set_N_and_n0(BN_MONT_CTX *mont, const BIGNUM *mod) { mont->n0[0] = (BN_ULONG)n0; #if BN_MONT_CTX_N0_LIMBS == 2 mont->n0[1] = (BN_ULONG)(n0 >> BN_BITS2); -#else - mont->n0[1] = 0; #endif return 1; } @@ -309,16 +308,16 @@ int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, } #if defined(OPENSSL_BN_ASM_MONT) - // |bn_mul_mont| requires at least 128 bits of limbs. + // |bn_mul_mont_words| requires at least 128 bits of limbs. int num = mont->N.width; if (num >= (128 / BN_BITS2) && a->width == num && b->width == num) { if (!bn_wexpand(r, num)) { return 0; } - // This bound is implied by |bn_mont_ctx_set_N_and_n0|. |bn_mul_mont| + // This bound is implied by |bn_mont_ctx_set_N_and_n0|. |bn_mul_mont_words| // allocates |num| words on the stack, so |num| cannot be too large. assert((size_t)num <= BN_MONTGOMERY_MAX_WORDS); - bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num); + bn_mul_mont_words(r->d, a->d, b->d, mont->N.d, mont->n0, num); r->neg = 0; r->width = num; return 1; @@ -359,9 +358,9 @@ void bn_mod_mul_montgomery_small(BN_ULONG *r, const BN_ULONG *a, } #if defined(OPENSSL_BN_ASM_MONT) - // |bn_mul_mont| requires at least 128 bits of limbs. + // |bn_mul_mont_words| requires at least 128 bits of limbs. if (num >= (128 / BN_BITS2)) { - bn_mul_mont(r, a, b, mont->N.d, mont->n0, num); + bn_mul_mont_words(r, a, b, mont->N.d, mont->n0, num); return; } #endif @@ -382,8 +381,8 @@ void bn_mod_mul_montgomery_small(BN_ULONG *r, const BN_ULONG *a, } #if defined(OPENSSL_BN_ASM_MONT) && defined(OPENSSL_X86_64) -void bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, - const BN_ULONG *np, const BN_ULONG *n0, size_t num) { +void bn_mul_mont_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, size_t num) { if (ap == bp && bn_sqr8x_mont_capable(num)) { bn_sqr8x_mont(rp, ap, bn_mulx_adx_capable(), np, n0, num); } else if (bn_mulx4x_mont_capable(num)) { @@ -397,8 +396,8 @@ void bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, #endif #if defined(OPENSSL_BN_ASM_MONT) && defined(OPENSSL_ARM) -void bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, - const BN_ULONG *np, const BN_ULONG *n0, size_t num) { +void bn_mul_mont_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, size_t num) { if (bn_mul8x_mont_neon_capable(num)) { bn_mul8x_mont_neon(rp, ap, bp, np, n0, num); } else { diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/ec/p256.cc.inc b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/ec/p256.cc.inc index 6a5f2d3a5a..6a8abcdbfb 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/ec/p256.cc.inc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/ec/p256.cc.inc @@ -30,14 +30,8 @@ #include "../delocate.h" #include "./internal.h" -#if defined(BORINGSSL_HAS_UINT128) -#include "../../../third_party/fiat/p256_64.h" -#elif defined(OPENSSL_64_BIT) -#include "../../../third_party/fiat/p256_64_msvc.h" -#else -#include "../../../third_party/fiat/p256_32.h" -#endif - +#include "../../../third_party/fiat/p256_field.c.inc" +#include "../../../third_party/fiat/p256_point.br.c.inc" // utility functions, handwritten @@ -56,13 +50,6 @@ static const fiat_p256_felem fiat_p256_one = { #endif // 64BIT -static fiat_p256_limb_t fiat_p256_nz( - const fiat_p256_limb_t in1[FIAT_P256_NLIMBS]) { - fiat_p256_limb_t ret; - fiat_p256_nonzero(&ret, in1); - return ret; -} - static void fiat_p256_copy(fiat_p256_limb_t out[FIAT_P256_NLIMBS], const fiat_p256_limb_t in1[FIAT_P256_NLIMBS]) { for (size_t i = 0; i < FIAT_P256_NLIMBS; i++) { @@ -172,198 +159,44 @@ static void fiat_p256_inv_square(fiat_p256_felem out, // Building on top of the field operations we have the operations on the // elliptic curve group itself. Points on the curve are represented in Jacobian // coordinates. -// -// Both operations were transcribed to Coq and proven to correspond to naive -// implementations using Affine coordinates, for all suitable fields. In the -// Coq proofs, issues of constant-time execution and memory layout (aliasing) -// conventions were not considered. Specification of affine coordinates: -// -// As a sanity check, a proof that these points form a commutative group: -// -// fiat_p256_point_double calculates 2*(x_in, y_in, z_in) -// -// The method is taken from: -// http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b -// -// Coq transcription and correctness proof: -// -// -// -// Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed. -// while x_out == y_in is not (maybe this works, but it's not tested). static void fiat_p256_point_double(fiat_p256_felem x_out, fiat_p256_felem y_out, fiat_p256_felem z_out, const fiat_p256_felem x_in, const fiat_p256_felem y_in, const fiat_p256_felem z_in) { - fiat_p256_felem delta, gamma, beta, ftmp, ftmp2, tmptmp, alpha, fourbeta; - // delta = z^2 - fiat_p256_square(delta, z_in); - // gamma = y^2 - fiat_p256_square(gamma, y_in); - // beta = x*gamma - fiat_p256_mul(beta, x_in, gamma); - - // alpha = 3*(x-delta)*(x+delta) - fiat_p256_sub(ftmp, x_in, delta); - fiat_p256_add(ftmp2, x_in, delta); - - fiat_p256_add(tmptmp, ftmp2, ftmp2); - fiat_p256_add(ftmp2, ftmp2, tmptmp); - fiat_p256_mul(alpha, ftmp, ftmp2); - - // x' = alpha^2 - 8*beta - fiat_p256_square(x_out, alpha); - fiat_p256_add(fourbeta, beta, beta); - fiat_p256_add(fourbeta, fourbeta, fourbeta); - fiat_p256_add(tmptmp, fourbeta, fourbeta); - fiat_p256_sub(x_out, x_out, tmptmp); - - // z' = (y + z)^2 - gamma - delta - fiat_p256_add(delta, gamma, delta); - fiat_p256_add(ftmp, y_in, z_in); - fiat_p256_square(z_out, ftmp); - fiat_p256_sub(z_out, z_out, delta); - - // y' = alpha*(4*beta - x') - 8*gamma^2 - fiat_p256_sub(y_out, fourbeta, x_out); - fiat_p256_add(gamma, gamma, gamma); - fiat_p256_square(gamma, gamma); - fiat_p256_mul(y_out, alpha, y_out); - fiat_p256_add(gamma, gamma, gamma); - fiat_p256_sub(y_out, y_out, gamma); + uint8_t out[3*32], in[3*32]; + static_assert(sizeof(fiat_p256_felem) == 32); + OPENSSL_memcpy(&in[0], x_in, 32); + OPENSSL_memcpy(&in[32], y_in, 32); + OPENSSL_memcpy(&in[64], z_in, 32); + p256_point_double((br_word_t)out, (br_word_t)in); + OPENSSL_memcpy(x_out, &out[0], 32); + OPENSSL_memcpy(y_out, &out[32], 32); + OPENSSL_memcpy(z_out, &out[64], 32); } -// fiat_p256_point_add calculates (x1, y1, z1) + (x2, y2, z2) -// -// The method is taken from: -// http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl, -// adapted for mixed addition (z2 = 1, or z2 = 0 for the point at infinity). -// -// Coq transcription and correctness proof: -// -// -// -// This function includes a branch for checking whether the two input points -// are equal, (while not equal to the point at infinity). This case never -// happens during single point multiplication, so there is no timing leak for -// ECDH or ECDSA signing. static void fiat_p256_point_add(fiat_p256_felem x3, fiat_p256_felem y3, fiat_p256_felem z3, const fiat_p256_felem x1, const fiat_p256_felem y1, - const fiat_p256_felem z1, const int mixed, + const fiat_p256_felem z1, const fiat_p256_felem x2, const fiat_p256_felem y2, const fiat_p256_felem z2) { - fiat_p256_felem x_out, y_out, z_out; - fiat_p256_limb_t z1nz = fiat_p256_nz(z1); - fiat_p256_limb_t z2nz = fiat_p256_nz(z2); - - // z1z1 = z1z1 = z1**2 - fiat_p256_felem z1z1; - fiat_p256_square(z1z1, z1); - - fiat_p256_felem u1, s1, two_z1z2; - if (!mixed) { - // z2z2 = z2**2 - fiat_p256_felem z2z2; - fiat_p256_square(z2z2, z2); - - // u1 = x1*z2z2 - fiat_p256_mul(u1, x1, z2z2); - - // two_z1z2 = (z1 + z2)**2 - (z1z1 + z2z2) = 2z1z2 - fiat_p256_add(two_z1z2, z1, z2); - fiat_p256_square(two_z1z2, two_z1z2); - fiat_p256_sub(two_z1z2, two_z1z2, z1z1); - fiat_p256_sub(two_z1z2, two_z1z2, z2z2); - - // s1 = y1 * z2**3 - fiat_p256_mul(s1, z2, z2z2); - fiat_p256_mul(s1, s1, y1); - } else { - // We'll assume z2 = 1 (special case z2 = 0 is handled later). - - // u1 = x1*z2z2 - fiat_p256_copy(u1, x1); - // two_z1z2 = 2z1z2 - fiat_p256_add(two_z1z2, z1, z1); - // s1 = y1 * z2**3 - fiat_p256_copy(s1, y1); - } - - // u2 = x2*z1z1 - fiat_p256_felem u2; - fiat_p256_mul(u2, x2, z1z1); - - // h = u2 - u1 - fiat_p256_felem h; - fiat_p256_sub(h, u2, u1); - - fiat_p256_limb_t xneq = fiat_p256_nz(h); - - // z_out = two_z1z2 * h - fiat_p256_mul(z_out, h, two_z1z2); - - // z1z1z1 = z1 * z1z1 - fiat_p256_felem z1z1z1; - fiat_p256_mul(z1z1z1, z1, z1z1); - - // s2 = y2 * z1**3 - fiat_p256_felem s2; - fiat_p256_mul(s2, y2, z1z1z1); - - // r = (s2 - s1)*2 - fiat_p256_felem r; - fiat_p256_sub(r, s2, s1); - fiat_p256_add(r, r, r); - - fiat_p256_limb_t yneq = fiat_p256_nz(r); - - fiat_p256_limb_t is_nontrivial_double = constant_time_is_zero_w(xneq | yneq) & - ~constant_time_is_zero_w(z1nz) & - ~constant_time_is_zero_w(z2nz); - if (constant_time_declassify_w(is_nontrivial_double)) { - fiat_p256_point_double(x3, y3, z3, x1, y1, z1); - return; - } - - // I = (2h)**2 - fiat_p256_felem i; - fiat_p256_add(i, h, h); - fiat_p256_square(i, i); - - // J = h * I - fiat_p256_felem j; - fiat_p256_mul(j, h, i); - - // V = U1 * I - fiat_p256_felem v; - fiat_p256_mul(v, u1, i); - - // x_out = r**2 - J - 2V - fiat_p256_square(x_out, r); - fiat_p256_sub(x_out, x_out, j); - fiat_p256_sub(x_out, x_out, v); - fiat_p256_sub(x_out, x_out, v); - - // y_out = r(V-x_out) - 2 * s1 * J - fiat_p256_sub(y_out, v, x_out); - fiat_p256_mul(y_out, y_out, r); - fiat_p256_felem s1j; - fiat_p256_mul(s1j, s1, j); - fiat_p256_sub(y_out, y_out, s1j); - fiat_p256_sub(y_out, y_out, s1j); - - fiat_p256_cmovznz(x_out, z1nz, x2, x_out); - fiat_p256_cmovznz(x3, z2nz, x1, x_out); - fiat_p256_cmovznz(y_out, z1nz, y2, y_out); - fiat_p256_cmovznz(y3, z2nz, y1, y_out); - fiat_p256_cmovznz(z_out, z1nz, z2, z_out); - fiat_p256_cmovznz(z3, z2nz, z1, z_out); + uint8_t out[3 * 32], in1[3 * 32], in2[3 * 32]; + static_assert(sizeof(fiat_p256_felem) == 32); + OPENSSL_memcpy(&in1[0], x1, 32); + OPENSSL_memcpy(&in1[32], y1, 32); + OPENSSL_memcpy(&in1[64], z1, 32); + OPENSSL_memcpy(&in2[0], x2, 32); + OPENSSL_memcpy(&in2[32], y2, 32); + OPENSSL_memcpy(&in2[64], z2, 32); + p256_point_add_vartime_if_doubling((br_word_t)out, (br_word_t)in1, + (br_word_t)in2); + OPENSSL_memcpy(x3, &out[0], 32); + OPENSSL_memcpy(y3, &out[32], 32); + OPENSSL_memcpy(z3, &out[64], 32); } - #include "./p256_table.h" // fiat_p256_select_point_affine selects the |idx-1|th point from a @@ -454,8 +287,7 @@ static void ec_GFp_nistp256_add(const EC_GROUP *group, EC_JACOBIAN *r, fiat_p256_from_generic(x2, &b->X); fiat_p256_from_generic(y2, &b->Y); fiat_p256_from_generic(z2, &b->Z); - fiat_p256_point_add(x1, y1, z1, x1, y1, z1, 0 /* both Jacobian */, x2, y2, - z2); + fiat_p256_point_add(x1, y1, z1, x1, y1, z1, x2, y2, z2); fiat_p256_to_generic(&r->X, x1); fiat_p256_to_generic(&r->Y, y1); fiat_p256_to_generic(&r->Z, z1); @@ -486,7 +318,7 @@ static void ec_GFp_nistp256_point_mul(const EC_GROUP *group, EC_JACOBIAN *r, if (j & 1) { fiat_p256_point_add(p_pre_comp[j][0], p_pre_comp[j][1], p_pre_comp[j][2], p_pre_comp[1][0], p_pre_comp[1][1], p_pre_comp[1][2], - 0, p_pre_comp[j - 1][0], p_pre_comp[j - 1][1], + p_pre_comp[j - 1][0], p_pre_comp[j - 1][1], p_pre_comp[j - 1][2]); } else { fiat_p256_point_double(p_pre_comp[j][0], p_pre_comp[j][1], @@ -524,8 +356,8 @@ static void ec_GFp_nistp256_point_mul(const EC_GROUP *group, EC_JACOBIAN *r, fiat_p256_cmovznz(tmp[1], (fiat_p256_limb_t)sign, tmp[1], ftmp); if (!skip) { - fiat_p256_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], - 0 /* mixed */, tmp[0], tmp[1], tmp[2]); + fiat_p256_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], tmp[0], + tmp[1], tmp[2]); } else { fiat_p256_copy(nq[0], tmp[0]); fiat_p256_copy(nq[1], tmp[1]); @@ -562,8 +394,8 @@ static void ec_GFp_nistp256_point_mul_base(const EC_GROUP *group, fiat_p256_g_pre_comp[1], tmp); if (!skip) { - fiat_p256_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], - 1 /* mixed */, tmp[0], tmp[1], tmp[2]); + fiat_p256_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], tmp[0], + tmp[1], tmp[2]); } else { fiat_p256_copy(nq[0], tmp[0]); fiat_p256_copy(nq[1], tmp[1]); @@ -579,8 +411,8 @@ static void ec_GFp_nistp256_point_mul_base(const EC_GROUP *group, // Select the point to add, in constant time. fiat_p256_select_point_affine((fiat_p256_limb_t)bits, 15, fiat_p256_g_pre_comp[0], tmp); - fiat_p256_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */, - tmp[0], tmp[1], tmp[2]); + fiat_p256_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], tmp[0], + tmp[1], tmp[2]); } fiat_p256_to_generic(&r->X, nq[0]); @@ -605,8 +437,7 @@ static void ec_GFp_nistp256_point_mul_public(const EC_GROUP *group, for (size_t i = 1; i < OPENSSL_ARRAY_SIZE(p_pre_comp); i++) { fiat_p256_point_add(p_pre_comp[i][0], p_pre_comp[i][1], p_pre_comp[i][2], p_pre_comp[i - 1][0], p_pre_comp[i - 1][1], - p_pre_comp[i - 1][2], 0 /* not mixed */, p2[0], p2[1], - p2[2]); + p_pre_comp[i - 1][2], p2[0], p2[1], p2[2]); } // Set up the coefficients for |p_scalar|. @@ -632,9 +463,8 @@ static void ec_GFp_nistp256_point_mul_public(const EC_GROUP *group, if (bits != 0) { size_t index = (size_t)(bits - 1); fiat_p256_point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2], - 1 /* mixed */, fiat_p256_g_pre_comp[1][index][0], - fiat_p256_g_pre_comp[1][index][1], - fiat_p256_one); + fiat_p256_g_pre_comp[1][index][0], + fiat_p256_g_pre_comp[1][index][1], fiat_p256_one); skip = 0; } @@ -646,9 +476,8 @@ static void ec_GFp_nistp256_point_mul_public(const EC_GROUP *group, if (bits != 0) { size_t index = (size_t)(bits - 1); fiat_p256_point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2], - 1 /* mixed */, fiat_p256_g_pre_comp[0][index][0], - fiat_p256_g_pre_comp[0][index][1], - fiat_p256_one); + fiat_p256_g_pre_comp[0][index][0], + fiat_p256_g_pre_comp[0][index][1], fiat_p256_one); skip = 0; } } @@ -664,8 +493,7 @@ static void ec_GFp_nistp256_point_mul_public(const EC_GROUP *group, } if (!skip) { fiat_p256_point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2], - 0 /* not mixed */, p_pre_comp[idx][0], *y, - p_pre_comp[idx][2]); + p_pre_comp[idx][0], *y, p_pre_comp[idx][2]); } else { fiat_p256_copy(ret[0], p_pre_comp[idx][0]); fiat_p256_copy(ret[1], *y); diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/mldsa/mldsa.cc.inc b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/mldsa/mldsa.cc.inc index 5c32da8abc..630d77ec8c 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/mldsa/mldsa.cc.inc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/mldsa/mldsa.cc.inc @@ -50,7 +50,6 @@ constexpr uint32_t kPrime = 8380417; constexpr uint32_t kPrimeNegInverse = 4236238847; constexpr int kDroppedBits = 13; constexpr uint32_t kHalfPrime = (kPrime - 1) / 2; -constexpr uint32_t kGamma2 = (kPrime - 1) / 32; // 256^-1 mod kPrime, in Montgomery form. constexpr uint32_t kInverseDegreeMontgomery = 41978; @@ -65,6 +64,8 @@ constexpr size_t public_key_bytes() { return BCM_MLDSA65_PUBLIC_KEY_BYTES; } else if constexpr (K == 8) { return BCM_MLDSA87_PUBLIC_KEY_BYTES; + } else if constexpr (K == 4) { + return BCM_MLDSA44_PUBLIC_KEY_BYTES; } } @@ -74,6 +75,8 @@ constexpr size_t signature_bytes() { return BCM_MLDSA65_SIGNATURE_BYTES; } else if constexpr (K == 8) { return BCM_MLDSA87_SIGNATURE_BYTES; + } else if constexpr (K == 4) { + return BCM_MLDSA44_SIGNATURE_BYTES; } } @@ -83,6 +86,8 @@ constexpr int tau() { return 49; } else if constexpr (K == 8) { return 60; + } else if constexpr (K == 4) { + return 39; } } @@ -92,22 +97,71 @@ constexpr int lambda_bytes() { return 192 / 8; } else if constexpr (K == 8) { return 256 / 8; + } else if constexpr (K == 4) { + return 128 / 8; + } +} + +template +constexpr int gamma1_bits() { + if constexpr (K == 6 || K == 8) { + return 19; + } else if constexpr (K == 4) { + return 17; } } template constexpr int gamma1() { + return 1 << gamma1_bits(); +} + +template +constexpr int scalar_le_gamma1_bytes() { + return ((gamma1_bits() + 1) * kDegree) / 8; +} + +template +constexpr uint32_t w1_coeffs_bits() { if constexpr (K == 6 || K == 8) { - return 1 << 19; + return 4; + } else if constexpr (K == 4) { + return 6; } } +template +constexpr uint32_t w1_scalar_bytes() { + return (w1_coeffs_bits() * kDegree) / 8; +} + +template +constexpr uint32_t w1_bytes() { + return w1_scalar_bytes() * K; +} + +template +constexpr uint32_t prime_minus_one_over_gamma2() { + if constexpr (K == 6 || K == 8) { + return 32; + } else if constexpr (K == 4) { + return 88; + } +} + +template +constexpr uint32_t gamma2() { + return (kPrime - 1) / prime_minus_one_over_gamma2(); +} + template constexpr int beta() { if constexpr (K == 6) { return 196; } else if constexpr (K == 8) { return 120; + } else if constexpr (K == 4) { + return 78; } } @@ -117,6 +171,8 @@ constexpr int omega() { return 55; } else if constexpr (K == 8) { return 75; + } else if constexpr (K == 4) { + return 80; } } @@ -124,7 +180,7 @@ template constexpr int eta() { if constexpr (K == 6) { return 4; - } else if constexpr (K == 8) { + } else if constexpr (K == 8 || K == 4) { return 2; } } @@ -133,7 +189,7 @@ template constexpr int plus_minus_eta_bitlen() { if constexpr (K == 6) { return 4; - } else if constexpr (K == 8) { + } else if constexpr (K == 8 || K == 4) { return 3; } } @@ -433,42 +489,54 @@ void scale_power2_round(uint32_t *out, uint32_t r1) { } // FIPS 204, Algorithm 37 (`HighBits`). +template uint32_t high_bits(uint32_t x) { // Reference description (given 0 <= x < q): // // ``` - // int32_t r0 = x mod+- (2 * kGamma2); + // int32_t r0 = x mod+- (2 * gamma2); // if (x - r0 == q - 1) { // return 0; // } else { - // return (x - r0) / (2 * kGamma2); + // return (x - r0) / (2 * gamma2); // } // ``` // - // 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; + if constexpr (prime_minus_one_over_gamma2() == 32) { + // Below is the formula taken from the reference implementation. + // + // Here, Gamma2 == 2^18 - 2^8 + // This returns ((ceil(x / 2^7) * (2^10 + 1) + 2^21) / 2^22) mod 2^4 + r1 = (r1 * 1025 + (1 << 21)) >> 22; + r1 &= 15; + } else if constexpr (prime_minus_one_over_gamma2() == 88) { + // 1488/2^24 is close enough to 1/1488 so that r1 becomes x/(2 gamma2) + // rounded down. + r1 = (r1 * 11275 + (1 << 23)) >> 24; + + // For corner-case r1 = (Q-1)/(2 gamma2) = 44, we have to set r1=0. + r1 ^= ((uint32_t)(((int32_t)(43 - r1)) >> 31)) & r1; + } return r1; } // FIPS 204, Algorithm 36 (`Decompose`). +template void decompose(uint32_t *r1, int32_t *r0, uint32_t r) { - *r1 = high_bits(r); + *r1 = high_bits(r); *r0 = r; - *r0 -= *r1 * 2 * (int32_t)kGamma2; + *r0 -= *r1 * 2 * (int32_t)gamma2(); *r0 -= (((int32_t)kHalfPrime - *r0) >> 31) & (int32_t)kPrime; } // FIPS 204, Algorithm 38 (`LowBits`). +template int32_t low_bits(uint32_t x) { uint32_t r1; int32_t r0; - decompose(&r1, &r0, x); + decompose(&r1, &r0, x); return r0; } @@ -480,24 +548,45 @@ int32_t low_bits(uint32_t x) { // // It then computes HighBits (algorithm 37) of z and z+r. But z+r is just w - // cs2, so this takes three arguments and saves an addition. +template int32_t make_hint(uint32_t ct0, uint32_t cs2, uint32_t w) { uint32_t r_plus_z = mod_sub(w, cs2); uint32_t r = reduce_once(r_plus_z + ct0); - return high_bits(r) != high_bits(r_plus_z); + return high_bits(r) != high_bits(r_plus_z); } // FIPS 204, Algorithm 40 (`UseHint`). +template uint32_t use_hint_vartime(uint32_t h, uint32_t r) { uint32_t r1; int32_t r0; - decompose(&r1, &r0, r); + decompose(&r1, &r0, r); if (h) { - if (r0 > 0) { - // m = 16, thus |mod m| in the spec turns into |& 15|. - return (r1 + 1) & 15; + if constexpr (prime_minus_one_over_gamma2() == 32) { + if (r0 > 0) { + // (Q-1)/(2 gamma2) = m = 16, thus |mod m| in the spec turns into |& + // 15|. + return (r1 + 1) & 15; + } else { + return (r1 - 1) & 15; + } } else { - return (r1 - 1) & 15; + // m = 44 + static_assert(prime_minus_one_over_gamma2() == 88); + if (r0 > 0) { + if (r1 == 43) { + return 0; + } else { + return r1 + 1; + } + } else { + if (r1 == 0) { + return 43; + } else { + return r1 - 1; + } + } } } return r1; @@ -515,15 +604,17 @@ void scalar_scale_power2_round(scalar *out, const scalar *in) { } } +template void scalar_high_bits(scalar *out, const scalar *in) { for (int i = 0; i < kDegree; i++) { - out->c[i] = high_bits(in->c[i]); + out->c[i] = high_bits(in->c[i]); } } +template void scalar_low_bits(scalar *out, const scalar *in) { for (int i = 0; i < kDegree; i++) { - out->c[i] = low_bits(in->c[i]); + out->c[i] = low_bits(in->c[i]); } } @@ -541,16 +632,18 @@ void scalar_max_signed(uint32_t *max, const scalar *s) { } } +template void scalar_make_hint(scalar *out, const scalar *ct0, const scalar *cs2, const scalar *w) { for (int i = 0; i < kDegree; i++) { - out->c[i] = make_hint(ct0->c[i], cs2->c[i], w->c[i]); + out->c[i] = make_hint(ct0->c[i], cs2->c[i], w->c[i]); } } +template void scalar_use_hint_vartime(scalar *out, const scalar *h, const scalar *r) { for (int i = 0; i < kDegree; i++) { - out->c[i] = use_hint_vartime(h->c[i], r->c[i]); + out->c[i] = use_hint_vartime(h->c[i], r->c[i]); } } @@ -568,17 +661,17 @@ void vector_scale_power2_round(vector *out, const vector *in) { } } -template -void vector_high_bits(vector *out, const vector *in) { - for (int i = 0; i < X; i++) { - scalar_high_bits(&out->v[i], &in->v[i]); +template +void vector_high_bits(vector *out, const vector *in) { + for (int i = 0; i < K; i++) { + scalar_high_bits(&out->v[i], &in->v[i]); } } -template -void vector_low_bits(vector *out, const vector *in) { - for (int i = 0; i < X; i++) { - scalar_low_bits(&out->v[i], &in->v[i]); +template +void vector_low_bits(vector *out, const vector *in) { + for (int i = 0; i < K; i++) { + scalar_low_bits(&out->v[i], &in->v[i]); } } @@ -612,19 +705,19 @@ size_t vector_count_ones(const vector *a) { return count; } -template -void vector_make_hint(vector *out, const vector *ct0, - const vector *cs2, const vector *w) { - for (int i = 0; i < X; i++) { - scalar_make_hint(&out->v[i], &ct0->v[i], &cs2->v[i], &w->v[i]); +template +void vector_make_hint(vector *out, const vector *ct0, + const vector *cs2, const vector *w) { + for (int i = 0; i < K; i++) { + scalar_make_hint(&out->v[i], &ct0->v[i], &cs2->v[i], &w->v[i]); } } -template -void vector_use_hint_vartime(vector *out, const vector *h, - const vector *r) { - for (int i = 0; i < X; i++) { - scalar_use_hint_vartime(&out->v[i], &h->v[i], &r->v[i]); +template +void vector_use_hint_vartime(vector *out, const vector *h, + const vector *r) { + for (int i = 0; i < K; i++) { + scalar_use_hint_vartime(&out->v[i], &h->v[i], &r->v[i]); } } @@ -643,6 +736,25 @@ static void scalar_encode_4(uint8_t out[128], const scalar *s) { } } +// FIPS 204, Algorithm 16 (`SimpleBitPack`). Specialized to bitlen(b) = 6. +void scalar_encode_6(uint8_t out[192], const scalar *s) { + // Every four elements lands on a byte boundary. + static_assert(kDegree % 4 == 0, "kDegree must be a multiple of 4"); + for (int i = 0; i < kDegree / 4; i++) { + uint32_t a = s->c[4 * i]; + uint32_t b = s->c[4 * i + 1]; + uint32_t c = s->c[4 * i + 2]; + uint32_t d = s->c[4 * i + 3]; + declassify_assert(a < 64); + declassify_assert(b < 64); + declassify_assert(c < 64); + declassify_assert(d < 64); + out[3 * i] = a | (b << 6); + out[3 * i + 1] = (b >> 2) | (c << 4); + out[3 * i + 2] = (c >> 4) | (d << 2); + } +} + // FIPS 204, Algorithm 16 (`SimpleBitPack`). Specialized to bitlen(b) = 10. void scalar_encode_10(uint8_t out[320], const scalar *s) { // Every four elements lands on a byte boundary. @@ -730,10 +842,10 @@ void scalar_encode_signed_13_12(uint8_t out[416], const scalar *s) { e |= g << 14; e |= h << 27; h >>= 5; - OPENSSL_memcpy(&out[13 * i], &a, sizeof(a)); - OPENSSL_memcpy(&out[13 * i + 4], &c, sizeof(c)); - OPENSSL_memcpy(&out[13 * i + 8], &e, sizeof(e)); - OPENSSL_memcpy(&out[13 * i + 12], &h, 1); + CRYPTO_store_u32_le(&out[13 * i], a); + CRYPTO_store_u32_le(&out[13 * i + 4], c); + CRYPTO_store_u32_le(&out[13 * i + 8], e); + out[13 * i + 12] = static_cast(h); } } @@ -757,9 +869,35 @@ void scalar_encode_signed_20_19(uint8_t out[640], const scalar *s) { b |= c << 8; b |= d << 28; d >>= 4; - OPENSSL_memcpy(&out[10 * i], &a, sizeof(a)); - OPENSSL_memcpy(&out[10 * i + 4], &b, sizeof(b)); - OPENSSL_memcpy(&out[10 * i + 8], &d, 2); + CRYPTO_store_u32_le(&out[10 * i], a); + CRYPTO_store_u32_le(&out[10 * i + 4], b); + CRYPTO_store_u16_le(&out[10 * i + 8], static_cast(d)); + } +} + +// FIPS 204, Algorithm 17 (`BitPack`). Specialized to bitlen(a+b) = 18 and b = +// 2^17. +void scalar_encode_signed_18_17(uint8_t out[576], const scalar *s) { + static const uint32_t kMax = 1u << 17; + static_assert(kDegree % 4 == 0, "kDegree must be a multiple of 4"); + for (int i = 0; i < kDegree / 4; i++) { + uint32_t a = mod_sub(kMax, s->c[4 * i]); + uint32_t b = mod_sub(kMax, s->c[4 * i + 1]); + uint32_t c = mod_sub(kMax, s->c[4 * i + 2]); + uint32_t d = mod_sub(kMax, s->c[4 * i + 3]); + declassify_assert(a < (1u << 18)); + declassify_assert(b < (1u << 18)); + declassify_assert(c < (1u << 18)); + declassify_assert(d < (1u << 18)); + out[9 * i] = (uint8_t)a; + out[9 * i + 1] = (uint8_t)(a >> 8); + out[9 * i + 2] = (uint8_t)(a >> 16) | (uint8_t)(b << 2); + out[9 * i + 3] = (uint8_t)(b >> 6); + out[9 * i + 4] = (uint8_t)(b >> 14) | (uint8_t)(c << 4); + out[9 * i + 5] = (uint8_t)(c >> 4); + out[9 * i + 6] = (uint8_t)(c >> 12) | (uint8_t)(d << 6); + out[9 * i + 7] = (uint8_t)(d >> 2); + out[9 * i + 8] = (uint8_t)(d >> 10); } } @@ -775,6 +913,9 @@ void scalar_encode_signed(uint8_t *out, const scalar *s, int bits, } else if (bits == 20) { assert(max == 1u << 19); scalar_encode_signed_20_19(out, s); + } else if (bits == 18) { + assert(max == 1u << 17); + scalar_encode_signed_18_17(out, s); } else { assert(bits == 13); assert(max == 1u << 12); @@ -784,10 +925,9 @@ void scalar_encode_signed(uint8_t *out, const scalar *s, int bits, // FIPS 204, Algorithm 18 (`SimpleBitUnpack`). Specialized for bitlen(b) == 10. void scalar_decode_10(scalar *out, const uint8_t in[320]) { - uint32_t v; static_assert(kDegree % 4 == 0, "kDegree must be a multiple of 4"); for (int i = 0; i < kDegree / 4; i++) { - OPENSSL_memcpy(&v, &in[5 * i], sizeof(v)); + uint32_t v = CRYPTO_load_u32_le(&in[5 * i]); out->c[4 * i] = v & 0x3ff; out->c[4 * i + 1] = (v >> 10) & 0x3ff; out->c[4 * i + 2] = (v >> 20) & 0x3ff; @@ -798,10 +938,9 @@ void scalar_decode_10(scalar *out, const uint8_t in[320]) { // FIPS 204, Algorithm 19 (`BitUnpack`). Specialized to bitlen(a+b) = 4 and b = // 4. int scalar_decode_signed_4_4(scalar *out, const uint8_t in[128]) { - uint32_t v; static_assert(kDegree % 8 == 0, "kDegree must be a multiple of 8"); for (int i = 0; i < kDegree / 8; i++) { - OPENSSL_memcpy(&v, &in[4 * i], sizeof(v)); + uint32_t v = CRYPTO_load_u32_le(&in[4 * i]); // None of the nibbles may be >= 9. So if the MSB of any nibble is set, none // of the other bits may be set. First, select all the MSBs. const uint32_t msbs = v & 0x88888888u; @@ -865,14 +1004,12 @@ void scalar_decode_signed_13_12(scalar *out, const uint8_t in[416]) { static const uint32_t k13Bits = (1u << 13) - 1; static const uint32_t k7Bits = (1u << 7) - 1; - uint32_t a, b, c; - uint8_t d; static_assert(kDegree % 8 == 0, "kDegree must be a multiple of 8"); for (int i = 0; i < kDegree / 8; i++) { - OPENSSL_memcpy(&a, &in[13 * i], sizeof(a)); - OPENSSL_memcpy(&b, &in[13 * i + 4], sizeof(b)); - OPENSSL_memcpy(&c, &in[13 * i + 8], sizeof(c)); - d = in[13 * i + 12]; + uint32_t a = CRYPTO_load_u32_le(&in[13 * i]); + uint32_t b = CRYPTO_load_u32_le(&in[13 * i + 4]); + uint32_t c = CRYPTO_load_u32_le(&in[13 * i + 8]); + uint8_t d = in[13 * i + 12]; // It's not possible for a 13-bit number to be out of range when the max is // 2^12. @@ -887,19 +1024,43 @@ void scalar_decode_signed_13_12(scalar *out, const uint8_t in[416]) { } } +// FIPS 204, Algorithm 19 (`BitUnpack`). Specialized to bitlen(a+b) = 18 and b = +// 2^17. +void scalar_decode_signed_18_17(scalar *out, const uint8_t in[576]) { + static const uint32_t kMax = 1u << 17; + + static_assert(kDegree % 4 == 0, "kDegree must be a multiple of 4"); + for (int i = 0; i < kDegree / 4; i++) { + uint32_t a = uint32_t{in[9 * i]} | (uint32_t{in[9 * i + 1]} << 8) | + ((uint32_t{in[9 * i + 2]} & 0x3) << 16); + uint32_t b = (uint32_t{in[9 * i + 2]} >> 2) | + (uint32_t{in[9 * i + 3]} << 6) | + ((uint32_t{in[9 * i + 4]} & 0xf) << 14); + uint32_t c = (uint32_t{in[9 * i + 4]} >> 4) | + (uint32_t{in[9 * i + 5]} << 4) | + ((uint32_t{in[9 * i + 6]} & 0x3f) << 12); + uint32_t d = (uint32_t{in[9 * i + 6]} >> 6) | + (uint32_t{in[9 * i + 7]} << 2) | + (uint32_t{in[9 * i + 8]} << 10); + + out->c[i * 4] = mod_sub(kMax, a); + out->c[i * 4 + 1] = mod_sub(kMax, b); + out->c[i * 4 + 2] = mod_sub(kMax, c); + out->c[i * 4 + 3] = mod_sub(kMax, d); + } +} + // FIPS 204, Algorithm 19 (`BitUnpack`). Specialized to bitlen(a+b) = 20 and b = // 2^19. void scalar_decode_signed_20_19(scalar *out, const uint8_t in[640]) { static const uint32_t kMax = 1u << 19; static const uint32_t k20Bits = (1u << 20) - 1; - uint32_t a, b; - uint16_t c; static_assert(kDegree % 4 == 0, "kDegree must be a multiple of 4"); for (int i = 0; i < kDegree / 4; i++) { - OPENSSL_memcpy(&a, &in[10 * i], sizeof(a)); - OPENSSL_memcpy(&b, &in[10 * i + 4], sizeof(b)); - OPENSSL_memcpy(&c, &in[10 * i + 8], sizeof(c)); + uint32_t a = CRYPTO_load_u32_le(&in[10 * i]); + uint32_t b = CRYPTO_load_u32_le(&in[10 * i + 4]); + uint16_t c = CRYPTO_load_u16_le(&in[10 * i + 8]); // It's not possible for a 20-bit number to be out of range when the max is // 2^19. @@ -923,6 +1084,10 @@ int scalar_decode_signed(scalar *out, const uint8_t *in, int bits, assert(max == (1u << 12)); scalar_decode_signed_13_12(out, in); return 1; + } else if (bits == 18) { + assert(max == (1u << 17)); + scalar_decode_signed_18_17(out, in); + return 1; } else if (bits == 20) { assert(max == (1u << 19)); scalar_decode_signed_20_19(out, in); @@ -1016,13 +1181,14 @@ void scalar_uniform(scalar *out, const uint8_t derived_seed[kSigmaBytes + 2]) { } // FIPS 204, Algorithm 34 (`ExpandMask`), but just a single step. +template void scalar_sample_mask(scalar *out, const uint8_t derived_seed[kRhoPrimeBytes + 2]) { - uint8_t buf[640]; + uint8_t buf[scalar_le_gamma1_bytes()]; BORINGSSL_keccak(buf, sizeof(buf), derived_seed, kRhoPrimeBytes + 2, boringssl_shake256); - scalar_decode_signed_20_19(out, buf); + scalar_decode_signed(out, buf, gamma1_bits() + 1, gamma1()); } // FIPS 204, Algorithm 29 (`SampleInBall`). @@ -1108,7 +1274,7 @@ void vector_expand_short(vector *s1, vector *s2, } // FIPS 204, Algorithm 34 (`ExpandMask`). -template +template void vector_expand_mask(vector *out, const uint8_t seed[kRhoPrimeBytes], size_t kappa) { assert(kappa + L <= 0x10000); @@ -1119,7 +1285,7 @@ void vector_expand_mask(vector *out, const uint8_t seed[kRhoPrimeBytes], size_t index = kappa + i; derived_seed[kRhoPrimeBytes] = index & 0xFF; derived_seed[kRhoPrimeBytes + 1] = (index >> 8) & 0xFF; - scalar_sample_mask(&out->v[i], derived_seed); + scalar_sample_mask(&out->v[i], derived_seed); } } @@ -1136,6 +1302,10 @@ void vector_encode(uint8_t *out, const vector *a, int bits) { for (int i = 0; i < K; i++) { scalar_encode_4(out + i * bits * kDegree / 8, &a->v[i]); } + } else if (bits == 6) { + for (int i = 0; i < K; i++) { + scalar_encode_6(out + i * bits * kDegree / 8, &a->v[i]); + } } else { assert(bits == 10); for (int i = 0; i < K; i++) { @@ -1179,8 +1349,8 @@ int vector_decode_signed(vector *out, const uint8_t *in, int bits, // FIPS 204, Algorithm 28 (`w1Encode`). template -void w1_encode(uint8_t out[128 * K], const vector *w1) { - vector_encode(out, w1, 4); +void w1_encode(uint8_t out[w1_bytes()], const vector *w1) { + vector_encode(out, w1, w1_coeffs_bits()); } // FIPS 204, Algorithm 20 (`HintBitPack`). @@ -1364,10 +1534,11 @@ int mldsa_marshal_signature(CBB *out, const struct signature *sign) { } uint8_t *vectorl_output; - if (!CBB_add_space(out, &vectorl_output, 640 * L)) { + if (!CBB_add_space(out, &vectorl_output, scalar_le_gamma1_bytes() * L)) { return 0; } - vector_encode_signed(vectorl_output, &sign->z, 20, 1 << 19); + vector_encode_signed(vectorl_output, &sign->z, gamma1_bits() + 1, + gamma1()); uint8_t *hint_output; if (!CBB_add_space(out, &hint_output, omega() + K)) { @@ -1384,9 +1555,10 @@ int mldsa_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. - !vector_decode_signed(&sign->z, CBS_data(&z_bytes), 20, 1 << 19) || + !CBS_get_bytes(in, &z_bytes, scalar_le_gamma1_bytes() * L) || + // Note: Decoding b+1 bits into (-2^b, 2^b] cannot fail. + !vector_decode_signed(&sign->z, CBS_data(&z_bytes), gamma1_bits() + 1, + gamma1()) || !CBS_get_bytes(in, &hint_bytes, omega() + K) || !hint_bit_unpack(&sign->h, CBS_data(&hint_bytes))) { return 0; @@ -1561,7 +1733,7 @@ int mldsa_sign_mu( // kappa must not exceed 2**16/L = 13107. But the probability of it // exceeding even 1000 iterations is vanishingly small. for (size_t kappa = 0;; kappa += L) { - vector_expand_mask(&values->y, rho_prime, kappa); + vector_expand_mask(&values->y, rho_prime, kappa); vector *y_ntt = &values->cs1; OPENSSL_memcpy(y_ntt, &values->y, sizeof(*y_ntt)); @@ -1571,12 +1743,12 @@ int mldsa_sign_mu( vector_inverse_ntt(&values->w); vector_high_bits(&values->w1, &values->w); - uint8_t w1_encoded[128 * K]; + uint8_t w1_encoded[w1_bytes()]; w1_encode(w1_encoded, &values->w1); BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256); BORINGSSL_keccak_absorb(&keccak_ctx, mu, kMuBytes); - BORINGSSL_keccak_absorb(&keccak_ctx, w1_encoded, 128 * K); + BORINGSSL_keccak_absorb(&keccak_ctx, w1_encoded, w1_bytes()); BORINGSSL_keccak_squeeze(&keccak_ctx, values->sign.c_tilde, 2 * lambda_bytes()); @@ -1609,7 +1781,7 @@ int mldsa_sign_mu( uint32_t r0_max = vector_max_signed(r0); if (constant_time_declassify_w( constant_time_ge_w(z_max, gamma1() - beta()) | - constant_time_ge_w(r0_max, kGamma2 - beta()))) { + constant_time_ge_w(r0_max, gamma2() - beta()))) { #if defined(BORINGSSL_FIPS_BREAK_TESTS) // In order to show that our self-tests trigger both restart cases in // this loop, printf-logging is added when built in break-test mode. @@ -1626,7 +1798,7 @@ int mldsa_sign_mu( // See above. uint32_t ct0_max = vector_max(ct0); size_t h_ones = vector_count_ones(&values->sign.h); - if (constant_time_declassify_w(constant_time_ge_w(ct0_max, kGamma2) | + if (constant_time_declassify_w(constant_time_ge_w(ct0_max, gamma2()) | constant_time_lt_w(omega(), h_ones))) { #if defined(BORINGSSL_FIPS_BREAK_TESTS) // In order to show that our self-tests trigger both restart cases in @@ -1778,13 +1950,13 @@ int mldsa_verify_internal_no_self_test( vector_inverse_ntt(w1); vector_use_hint_vartime(w1, &values->sign.h, w1); - uint8_t w1_encoded[128 * K]; + uint8_t w1_encoded[w1_bytes()]; w1_encode(w1_encoded, w1); uint8_t c_tilde[2 * lambda_bytes()]; BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256); BORINGSSL_keccak_absorb(&keccak_ctx, mu, kMuBytes); - BORINGSSL_keccak_absorb(&keccak_ctx, w1_encoded, 128 * K); + BORINGSSL_keccak_absorb(&keccak_ctx, w1_encoded, w1_bytes()); BORINGSSL_keccak_squeeze(&keccak_ctx, c_tilde, 2 * lambda_bytes()); uint32_t z_max = vector_max(&values->sign.z); @@ -1871,6 +2043,39 @@ struct prehash_context *prehash_context_from_external_87( return reinterpret_cast(external); } +struct private_key<4, 4> *private_key_from_external_44( + const struct BCM_mldsa44_private_key *external) { + static_assert(sizeof(struct BCM_mldsa44_private_key) == + sizeof(struct private_key<4, 4>), + "MLDSA44 private key size incorrect"); + static_assert(alignof(struct BCM_mldsa44_private_key) == + alignof(struct private_key<4, 4>), + "MLDSA44 private key alignment incorrect"); + return (struct private_key<4, 4> *)external; +} + +struct public_key<4> *public_key_from_external_44( + const struct BCM_mldsa44_public_key *external) { + static_assert( + sizeof(struct BCM_mldsa44_public_key) == sizeof(struct public_key<4>), + "MLDSA44 public key size incorrect"); + static_assert( + alignof(struct BCM_mldsa44_public_key) == alignof(struct public_key<4>), + "MLDSA44 public key alignment incorrect"); + return (struct public_key<4> *)external; +} + +struct prehash_context *prehash_context_from_external_44( + struct BCM_mldsa44_prehash *external) { + static_assert( + sizeof(struct BCM_mldsa44_prehash) == sizeof(struct prehash_context), + "MLDSA pre-hash context size incorrect"); + static_assert( + alignof(struct BCM_mldsa44_prehash) == alignof(struct prehash_context), + "MLDSA pre-hash context alignment incorrect"); + return reinterpret_cast(external); +} + namespace fips { #include "fips_known_values.inc" @@ -2442,6 +2647,209 @@ bcm_status BCM_mldsa87_marshal_public_key( out, mldsa::public_key_from_external_87(public_key))); } + +// ML-DSA-44 specific wrappers. + +bcm_status BCM_mldsa44_parse_public_key( + struct BCM_mldsa44_public_key *public_key, CBS *in) { + return bcm_as_approved_status(mldsa_parse_public_key( + mldsa::public_key_from_external_44(public_key), in)); +} + +bcm_status BCM_mldsa44_marshal_private_key( + CBB *out, const struct BCM_mldsa44_private_key *private_key) { + return bcm_as_approved_status(mldsa_marshal_private_key( + out, mldsa::private_key_from_external_44(private_key))); +} + +bcm_status BCM_mldsa44_parse_private_key( + struct BCM_mldsa44_private_key *private_key, CBS *in) { + return bcm_as_approved_status( + mldsa_parse_private_key(mldsa::private_key_from_external_44(private_key), + in) && + CBS_len(in) == 0); +} + +bcm_status BCM_mldsa44_check_key_fips( + struct BCM_mldsa44_private_key *private_key) { + return bcm_as_approved_status( + mldsa::fips::check_key(mldsa::private_key_from_external_44(private_key))); +} + +// Calls |MLDSA_generate_key_external_entropy| with random bytes from +// |BCM_rand_bytes|. +bcm_status BCM_mldsa44_generate_key( + uint8_t out_encoded_public_key[BCM_MLDSA44_PUBLIC_KEY_BYTES], + uint8_t out_seed[BCM_MLDSA_SEED_BYTES], + struct BCM_mldsa44_private_key *out_private_key) { + BCM_rand_bytes(out_seed, BCM_MLDSA_SEED_BYTES); + return BCM_mldsa44_generate_key_external_entropy(out_encoded_public_key, + out_private_key, out_seed); +} + +bcm_status BCM_mldsa44_private_key_from_seed( + struct BCM_mldsa44_private_key *out_private_key, + const uint8_t seed[BCM_MLDSA_SEED_BYTES]) { + uint8_t public_key[BCM_MLDSA44_PUBLIC_KEY_BYTES]; + return BCM_mldsa44_generate_key_external_entropy(public_key, out_private_key, + seed); +} + +bcm_status BCM_mldsa44_generate_key_external_entropy( + uint8_t out_encoded_public_key[BCM_MLDSA44_PUBLIC_KEY_BYTES], + struct BCM_mldsa44_private_key *out_private_key, + const uint8_t entropy[BCM_MLDSA_SEED_BYTES]) { + return bcm_as_not_approved_status(mldsa_generate_key_external_entropy( + out_encoded_public_key, + mldsa::private_key_from_external_44(out_private_key), entropy)); +} + +bcm_status BCM_mldsa44_generate_key_fips( + uint8_t out_encoded_public_key[BCM_MLDSA44_PUBLIC_KEY_BYTES], + uint8_t out_seed[BCM_MLDSA_SEED_BYTES], + struct BCM_mldsa44_private_key *out_private_key) { + if (out_encoded_public_key == nullptr || out_private_key == nullptr) { + return bcm_status::failure; + } + if (BCM_mldsa44_generate_key(out_encoded_public_key, out_seed, + out_private_key) == bcm_status::failure) { + return bcm_status::failure; + } + return BCM_mldsa44_check_key_fips(out_private_key); +} + +bcm_status BCM_mldsa44_generate_key_external_entropy_fips( + uint8_t out_encoded_public_key[BCM_MLDSA44_PUBLIC_KEY_BYTES], + struct BCM_mldsa44_private_key *out_private_key, + const uint8_t entropy[BCM_MLDSA_SEED_BYTES]) { + if (out_encoded_public_key == nullptr || out_private_key == nullptr) { + return bcm_status::failure; + } + if (BCM_mldsa44_generate_key_external_entropy(out_encoded_public_key, + out_private_key, entropy) == + bcm_status::failure) { + return bcm_status::failure; + } + return BCM_mldsa44_check_key_fips(out_private_key); +} + +bcm_status BCM_mldsa44_private_key_from_seed_fips( + struct BCM_mldsa44_private_key *out_private_key, + const uint8_t seed[BCM_MLDSA_SEED_BYTES]) { + uint8_t public_key[BCM_MLDSA44_PUBLIC_KEY_BYTES]; + if (BCM_mldsa44_generate_key_external_entropy(public_key, out_private_key, + seed) == bcm_status::failure) { + return bcm_status::failure; + } + return BCM_mldsa44_check_key_fips(out_private_key); +} + +bcm_status BCM_mldsa44_public_from_private( + struct BCM_mldsa44_public_key *out_public_key, + const struct BCM_mldsa44_private_key *private_key) { + return bcm_as_approved_status(mldsa_public_from_private( + mldsa::public_key_from_external_44(out_public_key), + mldsa::private_key_from_external_44(private_key))); +} + +bcm_status BCM_mldsa44_sign_internal( + uint8_t out_encoded_signature[BCM_MLDSA44_SIGNATURE_BYTES], + const struct BCM_mldsa44_private_key *private_key, const uint8_t *msg, + size_t msg_len, const uint8_t *context_prefix, size_t context_prefix_len, + const uint8_t *context, size_t context_len, + const uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES]) { + return bcm_as_approved_status(mldsa_sign_internal( + out_encoded_signature, mldsa::private_key_from_external_44(private_key), + msg, msg_len, context_prefix, context_prefix_len, context, context_len, + randomizer)); +} + +// ML-DSA signature in randomized mode, filling the random bytes with +// |BCM_rand_bytes|. +bcm_status BCM_mldsa44_sign( + uint8_t out_encoded_signature[BCM_MLDSA44_SIGNATURE_BYTES], + const struct BCM_mldsa44_private_key *private_key, const uint8_t *msg, + size_t msg_len, const uint8_t *context, size_t context_len) { + BSSL_CHECK(context_len <= 255); + uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES]; + BCM_rand_bytes(randomizer, sizeof(randomizer)); + + const uint8_t context_prefix[2] = {0, static_cast(context_len)}; + return BCM_mldsa44_sign_internal( + out_encoded_signature, private_key, msg, msg_len, context_prefix, + sizeof(context_prefix), context, context_len, randomizer); +} + +// ML-DSA pre-hashed API: initializing a pre-hashing context. +void BCM_mldsa44_prehash_init(struct BCM_mldsa44_prehash *out_prehash_ctx, + const struct BCM_mldsa44_public_key *public_key, + const uint8_t *context, size_t context_len) { + BSSL_CHECK(context_len <= 255); + + const uint8_t context_prefix[2] = {0, static_cast(context_len)}; + mldsa_prehash_init(mldsa::prehash_context_from_external_44(out_prehash_ctx), + mldsa::public_key_from_external_44(public_key), + context_prefix, sizeof(context_prefix), context, + context_len); +} + +// ML-DSA pre-hashed API: updating a pre-hashing context with a message chunk. +void BCM_mldsa44_prehash_update(struct BCM_mldsa44_prehash *inout_prehash_ctx, + const uint8_t *msg, size_t msg_len) { + mldsa_prehash_update( + mldsa::prehash_context_from_external_44(inout_prehash_ctx), msg, msg_len); +} + +// ML-DSA pre-hashed API: obtaining a message representative to sign. +void BCM_mldsa44_prehash_finalize( + uint8_t out_msg_rep[BCM_MLDSA_MU_BYTES], + struct BCM_mldsa44_prehash *inout_prehash_ctx) { + mldsa_prehash_finalize( + out_msg_rep, mldsa::prehash_context_from_external_44(inout_prehash_ctx)); +} + +// ML-DSA pre-hashed API: signing a message representative. +bcm_status BCM_mldsa44_sign_message_representative( + uint8_t out_encoded_signature[BCM_MLDSA44_SIGNATURE_BYTES], + const struct BCM_mldsa44_private_key *private_key, + const uint8_t msg_rep[BCM_MLDSA_MU_BYTES]) { + uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES]; + BCM_rand_bytes(randomizer, sizeof(randomizer)); + CONSTTIME_SECRET(randomizer, sizeof(randomizer)); + + return bcm_as_approved_status(mldsa_sign_mu( + out_encoded_signature, mldsa::private_key_from_external_44(private_key), + msg_rep, randomizer)); +} + +// FIPS 204, Algorithm 3 (`ML-DSA.Verify`). +bcm_status BCM_mldsa44_verify(const struct BCM_mldsa44_public_key *public_key, + const uint8_t *signature, const uint8_t *msg, + size_t msg_len, const uint8_t *context, + size_t context_len) { + BSSL_CHECK(context_len <= 255); + const uint8_t context_prefix[2] = {0, static_cast(context_len)}; + return BCM_mldsa44_verify_internal(public_key, signature, msg, msg_len, + context_prefix, sizeof(context_prefix), + context, context_len); +} + +bcm_status BCM_mldsa44_verify_internal( + const struct BCM_mldsa44_public_key *public_key, + const uint8_t encoded_signature[BCM_MLDSA44_SIGNATURE_BYTES], + const uint8_t *msg, size_t msg_len, const uint8_t *context_prefix, + size_t context_prefix_len, const uint8_t *context, size_t context_len) { + return bcm_as_approved_status(mldsa::mldsa_verify_internal<4, 4>( + mldsa::public_key_from_external_44(public_key), encoded_signature, msg, + msg_len, context_prefix, context_prefix_len, context, context_len)); +} + +bcm_status BCM_mldsa44_marshal_public_key( + CBB *out, const struct BCM_mldsa44_public_key *public_key) { + return bcm_as_approved_status(mldsa_marshal_public_key( + out, mldsa::public_key_from_external_44(public_key))); +} + int boringssl_self_test_mldsa() { return mldsa::fips::keygen_self_test() && mldsa::fips::sign_self_test() && mldsa::fips::verify_self_test(); diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/rsa/padding.cc.inc b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/rsa/padding.cc.inc index 2b9e20dc63..726d23dfc7 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/rsa/padding.cc.inc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/rsa/padding.cc.inc @@ -178,16 +178,14 @@ int RSA_verify_PKCS1_PSS_mgf1(const RSA *rsa, const uint8_t *mHash, size_t emLen, maskedDBLen, salt_start; FIPS_service_indicator_lock_state(); - // Negative sLen has special meanings: - // -1 sLen == hLen - // -2 salt length is autorecovered from signature - // -N reserved size_t hLen = EVP_MD_size(Hash); if (sLen == RSA_PSS_SALTLEN_DIGEST) { sLen = (int)hLen; } else if (sLen == RSA_PSS_SALTLEN_AUTO) { - // Leave |sLen| negative. + // Leave |sLen| negative, which will trigger the logic below to recover and + // allow any salt length. } else if (sLen < 0) { + // Other negative values are reserved. OPENSSL_PUT_ERROR(RSA, RSA_R_SLEN_CHECK_FAILED); goto err; } @@ -202,7 +200,7 @@ int RSA_verify_PKCS1_PSS_mgf1(const RSA *rsa, const uint8_t *mHash, EM++; emLen--; } - // |sLen| may be -2 for the non-standard salt length recovery mode. + // |sLen| may be negative for the non-standard salt length recovery mode. if (emLen < hLen + 2 || (sLen >= 0 && emLen < hLen + (size_t)sLen + 2)) { OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE); goto err; @@ -299,16 +297,14 @@ int RSA_padding_add_PKCS1_PSS_mgf1(const RSA *rsa, unsigned char *EM, goto err; } - // Negative sLenRequested has special meanings: - // -1 sLen == hLen - // -2 salt length is maximized - // -N reserved size_t sLen; if (sLenRequested == RSA_PSS_SALTLEN_DIGEST) { sLen = hLen; } else if (sLenRequested == RSA_PSS_SALTLEN_AUTO) { + // Use the maximum possible salt length. sLen = emLen - hLen - 2; } else if (sLenRequested < 0) { + // Other negative values are reserved. OPENSSL_PUT_ERROR(RSA, RSA_R_SLEN_CHECK_FAILED); goto err; } else { diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/slhdsa/thash.cc.inc b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/slhdsa/thash.cc.inc index 6aa3d4d13b..448ac0f767 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/slhdsa/thash.cc.inc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/slhdsa/thash.cc.inc @@ -17,7 +17,7 @@ #include #include -#include +#include #include "../../internal.h" #include "./params.h" diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/hpke/hpke.cc b/naiveproxy/src/third_party/boringssl/src/crypto/hpke/hpke.cc index bd10775d95..321f9db6e4 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/hpke/hpke.cc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/hpke/hpke.cc @@ -27,7 +27,8 @@ #include #include #include -#include +#include +#include #include "../fipsmodule/ec/internal.h" #include "../internal.h" @@ -35,7 +36,7 @@ // This file implements RFC 9180. -#define MAX_SEED_LEN X25519_PRIVATE_KEY_LEN +#define MAX_SEED_LEN XWING_SEED_LEN #define MAX_SHARED_SECRET_LEN SHA256_DIGEST_LENGTH struct evp_hpke_kem_st { @@ -601,6 +602,122 @@ const EVP_HPKE_KEM *EVP_hpke_p256_hkdf_sha256(void) { return &kKEM; } +#define XWING_PRIVATE_KEY_LEN 32 +#define XWING_PUBLIC_KEY_LEN 1216 +#define XWING_PUBLIC_VALUE_LEN 1120 +#define XWING_SEED_LEN 64 +#define XWING_SHARED_KEY_LEN 32 + +static int xwing_init_key(EVP_HPKE_KEY *key, const uint8_t *priv_key, + size_t priv_key_len) { + CBS cbs; + CBS_init(&cbs, priv_key, priv_key_len); + XWING_private_key private_key; + if (!XWING_parse_private_key(&private_key, &cbs) || CBS_len(&cbs) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return 0; + } + + if (!XWING_public_from_private(key->public_key, &private_key)) { + return 0; + } + + if (priv_key_len > sizeof(key->private_key)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return 0; + } + OPENSSL_memcpy(key->private_key, priv_key, priv_key_len); + return 1; +} + +static int xwing_generate_key(EVP_HPKE_KEY *key) { + XWING_private_key private_key; + if (!XWING_generate_key(key->public_key, &private_key)) { + return 0; + } + + CBB cbb; + CBB_init_fixed(&cbb, key->private_key, XWING_PRIVATE_KEY_LEN); + if (!XWING_marshal_private_key(&cbb, &private_key) || + CBB_len(&cbb) != XWING_PRIVATE_KEY_LEN) { + return 0; + } + + return 1; +} + +static int xwing_encap_with_seed(const EVP_HPKE_KEM *kem, + uint8_t *out_shared_secret, + size_t *out_shared_secret_len, + uint8_t *out_enc, size_t *out_enc_len, + size_t max_enc, const uint8_t *peer_public_key, + size_t peer_public_key_len, + const uint8_t *seed, size_t seed_len) { + if (max_enc < XWING_PUBLIC_VALUE_LEN) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE); + return 0; + } + if (peer_public_key_len != XWING_PUBLIC_KEY_LEN || + seed_len != XWING_SEED_LEN) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return 0; + } + + if (!XWING_encap_external_entropy(out_enc, out_shared_secret, peer_public_key, + seed)) { + OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR); + return 0; + } + + *out_enc_len = XWING_PUBLIC_VALUE_LEN; + *out_shared_secret_len = XWING_SHARED_KEY_LEN; + return 1; +} + +static int xwing_decap(const EVP_HPKE_KEY *key, uint8_t *out_shared_secret, + size_t *out_shared_secret_len, const uint8_t *enc, + size_t enc_len) { + if (enc_len != XWING_PUBLIC_VALUE_LEN) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return 0; + } + + CBS cbs; + CBS_init(&cbs, key->private_key, XWING_PRIVATE_KEY_LEN); + XWING_private_key private_key; + if (!XWING_parse_private_key(&private_key, &cbs)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return 0; + } + + if (!XWING_decap(out_shared_secret, enc, &private_key)) { + OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR); + return 0; + } + + *out_shared_secret_len = XWING_SHARED_KEY_LEN; + return 1; +} + +const EVP_HPKE_KEM *EVP_hpke_xwing(void) { + static const EVP_HPKE_KEM kKEM = { + /*id=*/EVP_HPKE_XWING, + /*public_key_len=*/XWING_PUBLIC_KEY_LEN, + /*private_key_len=*/XWING_PRIVATE_KEY_LEN, + /*seed_len=*/XWING_SEED_LEN, + /*enc_len=*/XWING_PUBLIC_VALUE_LEN, + xwing_init_key, + xwing_generate_key, + xwing_encap_with_seed, + xwing_decap, + // X-Wing doesn't support authenticated encapsulation/decapsulation: + // https://datatracker.ietf.org/doc/html/draft-connolly-cfrg-xwing-kem-08#name-use-in-hpke + /* auth_encap_with_seed= */ nullptr, + /* auth_decap= */ nullptr, + }; + return &kKEM; +} + uint16_t EVP_HPKE_KEM_id(const EVP_HPKE_KEM *kem) { return kem->id; } size_t EVP_HPKE_KEM_public_key_len(const EVP_HPKE_KEM *kem) { diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/hrss/hrss.cc b/naiveproxy/src/third_party/boringssl/src/crypto/hrss/hrss.cc index 81807c26a3..35311ef274 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/hrss/hrss.cc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/hrss/hrss.cc @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include "../internal.h" #include "internal.h" diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/internal.h b/naiveproxy/src/third_party/boringssl/src/crypto/internal.h index 676d2a1133..e1dcf2235a 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/internal.h +++ b/naiveproxy/src/third_party/boringssl/src/crypto/internal.h @@ -890,6 +890,16 @@ static inline void *OPENSSL_memset(void *dst, int c, size_t n) { // endianness. They use |memcpy|, and so avoid alignment or strict aliasing // requirements on the input and output pointers. +static inline uint16_t CRYPTO_load_u16_le(const void *in) { + uint16_t v; + OPENSSL_memcpy(&v, in, sizeof(v)); + return v; +} + +static inline void CRYPTO_store_u16_le(void *out, uint16_t v) { + OPENSSL_memcpy(out, &v, sizeof(v)); +} + static inline uint16_t CRYPTO_load_u16_be(const void *in) { uint16_t v; OPENSSL_memcpy(&v, in, sizeof(v)); @@ -1448,6 +1458,9 @@ inline int CRYPTO_fuzzer_mode_enabled(void) { return 0; } // CRYPTO_addc_* returns |x + y + carry|, and sets |*out_carry| to the carry // bit. |carry| must be zero or one. + +// NOTE: Unoptimized GCC builds may compile these builtins to non-constant-time +// code. For correct constant-time behavior, ensure builds are optimized. #if OPENSSL_HAS_BUILTIN(__builtin_addc) inline unsigned int CRYPTO_addc_impl(unsigned int x, unsigned int y, diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/mldsa/mldsa.cc b/naiveproxy/src/third_party/boringssl/src/crypto/mldsa/mldsa.cc index 721d2dbe88..bbe4062b3c 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/mldsa/mldsa.cc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/mldsa/mldsa.cc @@ -28,6 +28,12 @@ static_assert(sizeof(BCM_mldsa87_public_key) == sizeof(MLDSA87_public_key)); static_assert(alignof(BCM_mldsa87_public_key) == alignof(MLDSA87_public_key)); static_assert(sizeof(BCM_mldsa87_prehash) == sizeof(MLDSA87_prehash)); static_assert(alignof(BCM_mldsa87_prehash) == alignof(MLDSA87_prehash)); +static_assert(sizeof(BCM_mldsa44_private_key) == sizeof(MLDSA44_private_key)); +static_assert(alignof(BCM_mldsa44_private_key) == alignof(MLDSA44_private_key)); +static_assert(sizeof(BCM_mldsa44_public_key) == sizeof(MLDSA44_public_key)); +static_assert(alignof(BCM_mldsa44_public_key) == alignof(MLDSA44_public_key)); +static_assert(sizeof(BCM_mldsa44_prehash) == sizeof(MLDSA44_prehash)); +static_assert(alignof(BCM_mldsa44_prehash) == alignof(MLDSA44_prehash)); static_assert(MLDSA_SEED_BYTES == BCM_MLDSA_SEED_BYTES); static_assert(MLDSA_MU_BYTES == BCM_MLDSA_MU_BYTES); static_assert(MLDSA65_PRIVATE_KEY_BYTES == BCM_MLDSA65_PRIVATE_KEY_BYTES); @@ -36,6 +42,9 @@ static_assert(MLDSA65_SIGNATURE_BYTES == BCM_MLDSA65_SIGNATURE_BYTES); static_assert(MLDSA87_PRIVATE_KEY_BYTES == BCM_MLDSA87_PRIVATE_KEY_BYTES); static_assert(MLDSA87_PUBLIC_KEY_BYTES == BCM_MLDSA87_PUBLIC_KEY_BYTES); static_assert(MLDSA87_SIGNATURE_BYTES == BCM_MLDSA87_SIGNATURE_BYTES); +static_assert(MLDSA44_PRIVATE_KEY_BYTES == BCM_MLDSA44_PRIVATE_KEY_BYTES); +static_assert(MLDSA44_PUBLIC_KEY_BYTES == BCM_MLDSA44_PUBLIC_KEY_BYTES); +static_assert(MLDSA44_SIGNATURE_BYTES == BCM_MLDSA44_SIGNATURE_BYTES); int MLDSA65_generate_key( uint8_t out_encoded_public_key[MLDSA65_PUBLIC_KEY_BYTES], @@ -226,3 +235,98 @@ int MLDSA87_parse_public_key(struct MLDSA87_public_key *public_key, CBS *in) { return bcm_success(BCM_mldsa87_parse_public_key( reinterpret_cast(public_key), in)); } + +int MLDSA44_generate_key( + uint8_t out_encoded_public_key[MLDSA44_PUBLIC_KEY_BYTES], + uint8_t out_seed[MLDSA_SEED_BYTES], + struct MLDSA44_private_key *out_private_key) { + return bcm_success(BCM_mldsa44_generate_key( + out_encoded_public_key, out_seed, + reinterpret_cast(out_private_key))); +} + +int MLDSA44_private_key_from_seed(struct MLDSA44_private_key *out_private_key, + const uint8_t *seed, size_t seed_len) { + if (seed_len != BCM_MLDSA_SEED_BYTES) { + return 0; + } + return bcm_success(BCM_mldsa44_private_key_from_seed( + reinterpret_cast(out_private_key), seed)); +} + +int MLDSA44_public_from_private(struct MLDSA44_public_key *out_public_key, + const struct MLDSA44_private_key *private_key) { + return bcm_success(BCM_mldsa44_public_from_private( + reinterpret_cast(out_public_key), + reinterpret_cast(private_key))); +} + +int MLDSA44_sign(uint8_t out_encoded_signature[MLDSA44_SIGNATURE_BYTES], + const struct MLDSA44_private_key *private_key, + const uint8_t *msg, size_t msg_len, const uint8_t *context, + size_t context_len) { + if (context_len > 255) { + return 0; + } + return bcm_success(BCM_mldsa44_sign( + out_encoded_signature, + reinterpret_cast(private_key), msg, + msg_len, context, context_len)); +} + +int MLDSA44_verify(const struct MLDSA44_public_key *public_key, + const uint8_t *signature, size_t signature_len, + const uint8_t *msg, size_t msg_len, const uint8_t *context, + size_t context_len) { + if (context_len > 255 || signature_len != BCM_MLDSA44_SIGNATURE_BYTES) { + return 0; + } + return bcm_success(BCM_mldsa44_verify( + reinterpret_cast(public_key), signature, + msg, msg_len, context, context_len)); +} + +int MLDSA44_prehash_init(struct MLDSA44_prehash *out_state, + const struct MLDSA44_public_key *public_key, + const uint8_t *context, size_t context_len) { + if (context_len > 255) { + return 0; + } + BCM_mldsa44_prehash_init( + reinterpret_cast(out_state), + reinterpret_cast(public_key), context, + context_len); + return 1; +} + +void MLDSA44_prehash_update(struct MLDSA44_prehash *inout_state, + const uint8_t *msg, size_t msg_len) { + BCM_mldsa44_prehash_update( + reinterpret_cast(inout_state), msg, msg_len); +} + +void MLDSA44_prehash_finalize(uint8_t out_msg_rep[MLDSA_MU_BYTES], + struct MLDSA44_prehash *inout_state) { + BCM_mldsa44_prehash_finalize( + out_msg_rep, reinterpret_cast(inout_state)); +} + +int MLDSA44_sign_message_representative( + uint8_t out_encoded_signature[MLDSA44_SIGNATURE_BYTES], + const struct MLDSA44_private_key *private_key, + const uint8_t msg_rep[MLDSA_MU_BYTES]) { + return bcm_success(BCM_mldsa44_sign_message_representative( + out_encoded_signature, + reinterpret_cast(private_key), msg_rep)); +} + +int MLDSA44_marshal_public_key(CBB *out, + const struct MLDSA44_public_key *public_key) { + return bcm_success(BCM_mldsa44_marshal_public_key( + out, reinterpret_cast(public_key))); +} + +int MLDSA44_parse_public_key(struct MLDSA44_public_key *public_key, CBS *in) { + return bcm_success(BCM_mldsa44_parse_public_key( + reinterpret_cast(public_key), in)); +} diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa511.pem b/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa511.pem new file mode 100644 index 0000000000..fc5d71aae4 --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa511.pem @@ -0,0 +1,9 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIBOAIBAAJATYW40539KYSwoyeOEfrlrlfbSwxaFqlqk96aWadopzn6jWcb+9rS +lUIgWMnbKvWrD053rIItvUCvqfnu9yAb+wIDAQABAkAKjNNNgWfNubAsVBrCmame +Y3iFqyWrhdzqSNYqs1zLvTDmI/ugvTEnAsPOUPxg28T4ToCPywtz8DvvVOvBPzdp +AiEAwh25dNj3gE3pEM4yh03wbND2TvF/Dj0eHl45tLWhXK8CIGY8gTLtP2crIqyZ +wI20M25KL2BRveKJTNmyXg/FW0B1AiAG+zSxTCBSn/qy3QeaMCZmc3l4S10rcO1F +YFQo+KNOBwIgAykXrWVcMmpI9iECrN7HQD+W21lrj1dDQu+arM4jFgkCIQCm76vH +LgDhqssyYLFMt2nZbihJtpdqQWsv5f4Eu8kFGw== +-----END RSA PRIVATE KEY----- diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa511pub.pem b/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa511pub.pem new file mode 100644 index 0000000000..204a813b6d --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa511pub.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFswDQYJKoZIhvcNAQEBBQADSgAwRwJATYW40539KYSwoyeOEfrlrlfbSwxaFqlq +k96aWadopzn6jWcb+9rSlUIgWMnbKvWrD053rIItvUCvqfnu9yAb+wIDAQAB +-----END PUBLIC KEY----- diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa512.pem b/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa512.pem new file mode 100644 index 0000000000..17ed85ac3a --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa512.pem @@ -0,0 +1,9 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIBPAIBAAJBANLjQBoscno3D27YpNv1I2baUkzvz8gKculrIWvH7vcylUPItquY +0aWlVhvqQ+o/NytKAKWcJEdSDzQus9qF8xMCAwEAAQJBANH/4/xsWE7ld2PNLlWu +hWNNcnkUsRcleIqB2NUIUikrEbjflzIr/kzLHXx7qMgdaz1CDQkBahnGUbg5mfw8 +3skCIQDwoouuravi2c6IzuWYWdItfnCF48ipSuSzOK4x1eyAXwIhAOBac62gFvFz +5+1q66VrDK/RpbfcaJYNUBQIq1TPMjnNAiAI9JOsOYxnEeIM115WECmxRb5cTUDf +hAkE3nwlIKf/kwIhAN2YGafFdsPX4p06vTOur2I9ZTxcBCUpUw3mnitvV0GFAiEA +uARtcqqF5h71dNkzIU2lvd0pbpH/fKceViAoIoB/AP0= +-----END RSA PRIVATE KEY----- diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa512pub.pem b/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa512pub.pem new file mode 100644 index 0000000000..49f8e63d94 --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa512pub.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANLjQBoscno3D27YpNv1I2baUkzvz8gK +culrIWvH7vcylUPItquY0aWlVhvqQ+o/NytKAKWcJEdSDzQus9qF8xMCAwEAAQ== +-----END PUBLIC KEY----- diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa8192.pem b/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa8192.pem new file mode 100644 index 0000000000..397ef6f9fd --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa8192.pem @@ -0,0 +1,99 @@ +-----BEGIN RSA PRIVATE KEY----- +MIISKQIBAAKCBAEArdfc7gqU0Jg02VccpxpKPZs2yEKzD1qTqtzuR9Go7F0k05zU +XqljIAR0zrkbTBucjhIiu7pjB2w4HBP1eKjXX07t6bvP5QVcCFM9siC8R8vktOMh +iU+kGnGZAEC7FDpv473X9qOxgduQpnrmwnwtd1Hmp9heuY+gACKEzOuEf59iQQI5 +CT3yLnlwuIzbZOe2KRrgBmICgKetmFMdaR6LAKpMqIAAQd3RQqg2iYyx8aaTg1di +Zl731Ld/YCsrxFIvATNVyY6aBd6Il9r+qxhWzfqv2TkwUT4IaqQ508faN/M4YVhJ ++gCyUuxFeEobQilMfEaKLSgY6b9h+UNkA5F7wDMO8nUKu9QVJbI2RvZt34M4Duc9 +aLryQWKkSwFYOS9Ed46/pPRhc3dhIL9B5uPdQwABn7ndpDy+lPVZCX4xcrSHFy6M +I63K/KhwhARFXXbQ/QLrzfCfaG21r84PUm+MceYSFO8QMCMNfcsgR6GvhHWemc44 +8dSPunkpCpTkO6XW1lPnccDjPySQP6oxZTjlbaAhjEGCMvWr62dc9O3IoiwvRBtw +r//2PEjFdhc45iiPMI6abX5McawaFADNWutyzcmnExWNJkaLMcOCeYeGLPuOAZoX +GTRy4Hv9tE0BKdm0iwmn6Okx5MoavT9JshQtwpDh9qQjwg0Lex1UOqITnM4LVcUY +d53k55Ab4erix2fjTEFWlJWPdSJx1X0qoVKfwBP1fYyNgMNzv7DPOkC3Uhl4BhTA +Q1u35dxWpD5R4LiKvTOJiPOd+ZChgPjJxk9IlMi/4WcPG7Sd28zbV3wUk4jckFpr +fYZMndBcm2pB1ghFDCozG9qEUaUmZTCAKGqST+zhzaGD/aPT/gK9Hs1d1xT3zYTi +d/1g3Ksb8dKAVybUDtc2p3Q6+JFr1wgZzucIwegItfdmJEdFn3MGkvsZCsIP7o6V +wgfNzcXcjLdDEt1cJKTLJiJcWY1JYEokDjcNLkOPQM6JV957JcM0KYRf851tuOhF +eX/h1jvJAMocX2KAmt0Le2gRkq8RhXOv0I7zNckLP1bqR27IWfbZS85wHofzSWPx +0tR9mYwmMKSdq2hdVAlpQIADRbVRuy0poUWe+vpLUbTRyl0vTnVpl6VYkJtEwhI/ +dOojdphxN7haz7oGK180JXK1ZsQtPb9n1SDLYIbpY9Ydva7denI0epoykGKR4cxq +PvFKxFLdWy71HuLJZpSE792Qb2+sntnyPLSqhBb2fVI/JBsS5JyPG59bekcQqK2+ +DSNiQAglk/8PClS3SO1EA9YLkI4/4jpX/xIXRh6clYV6tzdKmX+NO8jq3ceQvClc +etSB30Vz3dMxMzaTQoJLjBwfmBu/8PJU88gvNQIDAQABAoIEAFt653igOtVV8yGX +1K0eiYjHv9k8OCvRNznHjuBeNO1EypdMxPiXXGFB1xHdmL7BHO4qHvr4xxnl2dT0 +r8zx1HwD9fB0c58J5fc/jozI6ytA4TZK+5/dN/buZlwatBed9Lk8coQIeeVi3Eiv +DfW0ENzkTWNv2dD+Am1vvMB1A0GBZtvcxpTVczb/ktCa1uzPfi09Rjw1oSmAkzpA +Ko7hkrYj57kXuorupirUh/Z0AkOuq5uHBXHncbUPZsj9jsd9k9ym3fL1xplmFC0N +AcyZPzyfOaAulv15jkZH62JFndCpfbbEFhGoAi7exGPbY2K6htQy7o16tzlyC6V2 +0A+MpDls5OWzr5VNsl8m26cWEJV44Kv/BXKyRb8goGIT8BAPjpD3nmO4cfuoC4WG +/6/3oryaKUCbN0Yw7P1H6rWzIWRCGYCabwZrcxDntmXSNYpMdwddXSb/A3OZn+1G +mwt/RcG+Fy/K6ZLbL0NN+8uWCt3CY1Z+jbq8Z3HyRiWaWkwFJfudJYLXxP26SOon +rlycxyacCGtdIZ2dZ/21Y9ZDtruYUrsdUXxcToBErxxIdhmvqEIeGKebubBrp0F1 +dprsoXonLnM9eQx2PNNQFb3MElBjg8PWCWerEPSOauBRUVZriLVNvH01EZtaux1x +S1+ZfMcRJMd8cpCv+qWrtmIwXe+6IrqL12GkQnKq2o2bVsgvq8qhvSvFBQgXcFrT +2HgGw+Dt5ARplsU3KSgk6gQBxJlR7EqkFMKez/M6eq24ukLF0dBdCHwELTVjJ7/F +wnkgHNATmyXSQHprdeqJnnpE0x9ivO0DP+RWh4bI8xtWbNmMlI0nfTDyvr4SdBvm +drE6GTASg/lJFNGXG8n3Q9bAz1LQVmbVA+cp5GtwlH04c0UJ7jSGMkiF9ptqsAvd +JS4KCTThgopHVNKbtFmefgEavL3DaYF1HdLOXlIEq//xgz6Gw1QckISXuuQSsviU +pVyxURQWoXVG7/DqPU2dQGJa9w5UZrnLl8E5RoA66qd6ACExA4fvQxq/+zuN+oyZ +OdwgoKkAQ+bLnFN30G+K6MuHE3TQE1QRfSGJD5TiwTr+YDeMPF4durClsSmzjYEG +dzL+JLPXV37FzNbKB+S8fqW45Je2V/qrvvQaaJUmqcUM+dBfPS7NWWqW6I4u8gVc +aVSxfOLETgcxW+TyUpAxoYfxxcNKzJyn6XYdVWm+12FnxC0H3jJMAnf6KPRmjOYG +wxW40RqbBbcWsDCd/Q+nFide7I48NNewGvxPFsWnWvZk16YxibMGfLNUZokXfRoJ +PdpYdsfw9980tHKNH+fIJuF8kD9Dx8ijkmHVy0kf8/UxKgkwp3gIrpQBb8zfje7+ +m0VkUnUCggIBAOTof2wkwAsp1aFmEIXzMD6PEc7Q0Fn5URdZUyiNSY+v9/wZpJHS +9Yi+EMmokFDV++OyzMvKnkD+QUDow3yPbPzHD1ckwLeZTXMrx+8v+0CC6rt9ye/8 +wfj1BZHhGx6UzN3GFUKyhHCXTJloFPSyILUVxh/CVgY6HJlC98cKvwgupkFWvb21 +TfFDEfhUoc+7TmSV+aLJJ8KZQO4JCD1w5jtO3NFWIvzuwhv6GvTLLTulvkEqrplU +D2pYzLFu48DLyUc0mLnD4aPK49l/OunfRCEe6F+QJ7QTGHghfeXKG9LgQKg2Dauq +iYq6rWapfjRZG1MN1xHNgF6aPm3YVBFJLkNxKLhZlVs/BqJzqbqn6Sm4G/ZghvAz +PedNmPrT13BCfJhVonox57eR/ez39bI2y5VuOTx/FjG9LuwW98EgDLCTHv2Hpzbw +qLqBVfM1zSm9XHTvbc4rFWpEzs0qUlX3ucMBI/Ss4cuAAWD+VCDXKhu8irzpyCQC +3ToXTpp3CiUNf1jNGXfiyhW2l7YmC/rkrioNLA7dJ+y8gvhW9wl0AK9FZAnLHhYh +bj77GhU8gCguPnrWjzkTREmLBpck3rl0wfrKk8zIzKXJJAgLeU7tD4g8QTUof77A +jDgd+AWRYDC09rIn1JHgscIlQ6IiCrJqy8cYdHS7QtfiPD1LZubou2IvAoICAQDC +av8YT6mZSXklbx+JFN58J50ruNtj/QzcbJbGwuY6FlisVDWTRk/sVTN67b6PICWk +zOXuHL3U1g3vgmaTZ31UU8jmw75v+yR2lvK8UvtNx1JOOTAWy2x4J7YvHmQCR1kY +XVASbif6YEk1wkaQqxNlGoECGkQR4w7itFNxG1kj5eDobOAmu7DYaV4oIfzknM5p +iPrCpasfx2WyQcz/LrFYGU/d2xaIPJbGOFNNAFi//JKZBnEXgUFBJeSQKFMDO6ra +wg/Q2Ae0zD++PHC8wnxJ/P/1UAl2eaYi0q0NRWpK8byyxPGYzKI0VU09BSHex6Mf +JJSs7AO7IkP81HiwWHJVySGubbdSNw4jBenjbCJ7TmnypkRXHKFD7bi7hl+/Kw0/ +Q1M9ivN9lod10WTZwmr4+f7vLZ/QwD6qjZc4d3GSWiNyQ/XWy32cAwETrugtZTxV +tJxPQxh0OPESpqo1Wd4W+4GvGYxTO/01ZqHLdM0ZAIFHVG53soDg8W5HqG1d6uzn +RIO/9uV25zupI7LeoyNTMc/QidDSw7oL/sGylZ47qrBl+ymLCZeT72rXpsXMGZ4h +UtnMhiy4GPT98CnMZd78rymNP7SAL8iI0D3PmLEvmM5BP2VU0V7Thy0CBekB7VeI +BAQvF8NDzmG3r1Gke2t31x9JSDoKn6GBuNzpPoCf2wKCAgEAoSTrTv4wE6vHsG9h +gmrIs8GUD7wAcNaKt50yZYHRH04JjXef2uhf4Xur5cq8jauWP51Hfs+MyMQ0u7Ug +qTduyiR4MCi3YoiRdVqEzWVBwxBmnsbWuhN9mf0jhqapqMWn0xf3L5TslzZrvjL/ +TaN4UwKZDxKH7KpMJ7h1JbHy+ZedgrHFsR9JV2aX5/HsV4jMjxLlQivJybyJcQj6 +vAYWjfneiZ/R0a1jCL7w6xN9LFhprwaVE2uRzpPkxaQCwV60u2PTgDLdTaku7ZYb +qzh5hbd0bpHU4Xfv6eHp9zJok/M6kTA8P3U2jmsMVxFKvx9blQRROz8n93EuMbXw +uJqD7wZiXCT0d9/Ok95IxhYeljf9t1wMolvwYDzITQuExoqHm9XtI4iuTxR/ZarJ +VEQu3WtS77unrCw6NAmXMGWXiVaIooI0vQB+R411LFnbrF6aD9fdvR2nXcBCtTvt +6ocSRq0u2rg53ECot9dS8iuGgTAhmwwY0QETLCnsM+FJSvxNgf4gx7zn9pEsDBaM +qHsEAKZ1NaGK0aWDrb/K+OSo9roqypoq+/lc2wl6Oyj0L1UetusEuHFPyVYNtalH +AdeoFx01HxzctHj83Iz3QRCxtn50iS+Rfn+eNoMibwkAZkl+wbw4cNl1Se9hxWmh +jiiQfABDO0n4rHGfZqcGMdf00hECggIBAK9DVYPNDM8q9RNSAdPKBGdYLs/jbaPN +03JCUgoMWQ+0ZWu03jdOA27BwA7plAfiqwzNydnF/zuHXDi2DVKE0O7cORgPDfZV +KKHfoiMzi2iqbwAlfbyO1dHbutjvRKjpOOBF/pEezNthQZ487PAtyOYz5mjG1OZr +Elg8x5wHU2yRJxdgTxGb0ejF1CPJv/k3gryQx74BKysSzhLMTskchrMs3lrZzo4y +UJmQ3UdlMJyiTGW28OyHkRPx3QI3193qRDPBDhDvLsNF/ZC5W8hOa00nznaPGHi9 +YY+y7F4yXYgCNGHUORfOIcubum1v2wDCZ8MDbyQT/6kLUs7xm3sdwLSlBMACGGj9 +SLk584cZTFxsbAZa7PC61oYuH4KtuFLVtLN7NecdBDQLJ0KG6auFIHoipDdpodDF +/bgyvEgjJTcSGzI/Ibfo6etiqe3cl2GVCbcZgm/RxJHBY1G0/Wvq/9MoF9iJ536B +bdpeEy0etmX7lo9/BbbSLGycORZQN4ea6MXzdfHv2Rw/iAEKNY2O86FkHjuYga/+ +0hFOL7+WMXcIgMzuhpzYoNSz2FVf+p/r2CmiTsWZj2bG2NSzVHr2uvZ/0a2L6GRG +rzjmwVIMDG8kCYu4Ytj7hcia63APc+ZQ17++Hyd0/Ip72ouEeM0WleMLAyFFA03g +afBPfpalyb5RAoICAD/ncTlq8LfGiJXZyySqWsIdxZf/29mjApbe7SGZj9Vy3I2E +RC0A80v6ChOZb9VPwawVYIprkfP4K+Knz7W3z7TO1fgAxA5N3FRYksAIZOto8UUX +cRl6n+hCtbuV3ntWWNtLA8g4KqPZYzJo0dlZxF2hVKBkrmN5fhXMKNMwHbxOn/32 +gmOKt8nzHCz1eru573VjMtQrxQpV/5E6Mkg/pkHRYs7nWd89wYcw3J1iKJhohkk3 +Gs7c5PLf7wYfMyyRCcNr0Npli5jBzvIHbvJNlF17rhyNwjOPW4+ZE8RXZyKCiV01 +t5eblKegWyKFNKoxvSsY69YFFP/imYjOqcJf8Ac9N8YBPYioyBGDck9T41cToXLZ +FDKZoZ/MB1j0WENXXLdLffOyWJnjFYbezy6mWDFQR7y1OJq9HuDGcD4ltr0Ob2/N +IvHJQ5Cc09yh5FD7t4JemfvynF/TfCuUAJTMe3NhVzsCtYBykJ5UhBUEhly5Kgtb +CsMqBdD0JlX63fmTxUHmKoaS72uWj9aBClTTqMKPVcQtFeVV9ZZ3zy8sYAjsZGVa +qvC+cMu7b0up6jsYzIXX1N9eUbg86JG+0NoxZSst9jD4FH2tWxGrvEpI8ccF5TWD +fFTCeKZtiIw797IQTLVOBEhq045A+fMa52hg4AT1a3RcNCi8qgBSqvbZ2jGr +-----END RSA PRIVATE KEY----- diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa8192pub.pem b/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa8192pub.pem new file mode 100644 index 0000000000..eec24a68c6 --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa8192pub.pem @@ -0,0 +1,25 @@ +-----BEGIN PUBLIC KEY----- +MIIEIjANBgkqhkiG9w0BAQEFAAOCBA8AMIIECgKCBAEArdfc7gqU0Jg02VccpxpK +PZs2yEKzD1qTqtzuR9Go7F0k05zUXqljIAR0zrkbTBucjhIiu7pjB2w4HBP1eKjX +X07t6bvP5QVcCFM9siC8R8vktOMhiU+kGnGZAEC7FDpv473X9qOxgduQpnrmwnwt +d1Hmp9heuY+gACKEzOuEf59iQQI5CT3yLnlwuIzbZOe2KRrgBmICgKetmFMdaR6L +AKpMqIAAQd3RQqg2iYyx8aaTg1diZl731Ld/YCsrxFIvATNVyY6aBd6Il9r+qxhW +zfqv2TkwUT4IaqQ508faN/M4YVhJ+gCyUuxFeEobQilMfEaKLSgY6b9h+UNkA5F7 +wDMO8nUKu9QVJbI2RvZt34M4Duc9aLryQWKkSwFYOS9Ed46/pPRhc3dhIL9B5uPd +QwABn7ndpDy+lPVZCX4xcrSHFy6MI63K/KhwhARFXXbQ/QLrzfCfaG21r84PUm+M +ceYSFO8QMCMNfcsgR6GvhHWemc448dSPunkpCpTkO6XW1lPnccDjPySQP6oxZTjl +baAhjEGCMvWr62dc9O3IoiwvRBtwr//2PEjFdhc45iiPMI6abX5McawaFADNWuty +zcmnExWNJkaLMcOCeYeGLPuOAZoXGTRy4Hv9tE0BKdm0iwmn6Okx5MoavT9JshQt +wpDh9qQjwg0Lex1UOqITnM4LVcUYd53k55Ab4erix2fjTEFWlJWPdSJx1X0qoVKf +wBP1fYyNgMNzv7DPOkC3Uhl4BhTAQ1u35dxWpD5R4LiKvTOJiPOd+ZChgPjJxk9I +lMi/4WcPG7Sd28zbV3wUk4jckFprfYZMndBcm2pB1ghFDCozG9qEUaUmZTCAKGqS +T+zhzaGD/aPT/gK9Hs1d1xT3zYTid/1g3Ksb8dKAVybUDtc2p3Q6+JFr1wgZzucI +wegItfdmJEdFn3MGkvsZCsIP7o6VwgfNzcXcjLdDEt1cJKTLJiJcWY1JYEokDjcN +LkOPQM6JV957JcM0KYRf851tuOhFeX/h1jvJAMocX2KAmt0Le2gRkq8RhXOv0I7z +NckLP1bqR27IWfbZS85wHofzSWPx0tR9mYwmMKSdq2hdVAlpQIADRbVRuy0poUWe ++vpLUbTRyl0vTnVpl6VYkJtEwhI/dOojdphxN7haz7oGK180JXK1ZsQtPb9n1SDL +YIbpY9Ydva7denI0epoykGKR4cxqPvFKxFLdWy71HuLJZpSE792Qb2+sntnyPLSq +hBb2fVI/JBsS5JyPG59bekcQqK2+DSNiQAglk/8PClS3SO1EA9YLkI4/4jpX/xIX +Rh6clYV6tzdKmX+NO8jq3ceQvClcetSB30Vz3dMxMzaTQoJLjBwfmBu/8PJU88gv +NQIDAQAB +-----END PUBLIC KEY----- diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa8193.pem b/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa8193.pem new file mode 100644 index 0000000000..7b9d0850ec --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa8193.pem @@ -0,0 +1,99 @@ +-----BEGIN RSA PRIVATE KEY----- +MIISKgIBAAKCBAEBeaDZhOt3skLqjWcZLNFT+9klhXTS6wSwPhz8dBfyovOgm0YF +/jyqb8TfrwbrD4+KpOHqiSigqyrHgBAwCxS5Nb7yEfP35Fx5fBRlxwy+t4hiyJrv +kIGerlIvXGl0AErm7Le/wOk6pCtEuCxD3U3gFB5EbOyW6a6pgN7YTV+uiUieWQKe +iZiJwjYOlqhszJuCSFswAsZCn0665w6d79qBsoYSfnhGmsbTgmNgM0DOWejIwdR9 +1ocnHnXCQqsOo1UBU9koWFdNvfwTWDvtZCLlfAh7Q6jg6BydknIkuenvH1oeqSpt +yfm/7SDS1J0qyxZbijdD7bW3Wd5aN5Rgq4otpd6EuOtTUMtnmJzRGhNiaSTs0W0t +8FHYTKiSai5TOEt4NWyRI6evqShxLzmZQ614cZ/8qlY1ab0144akLpyzd+rVzF5x +tU03IZKC2dElajaopSqCOt20dxNJgBDUhJnjePzB9MhF59YfbQ8Bv789csekQbNW +IIUkG2TzGWxT5x313SgPDtYdxdUPJz0ZKjDvBcq4PAYkqZ//vmSWZBxBbvm+tE3J +bPcSwBkLF9XHTeUO1DkhFi8t1/9YXS/rMYCs3hazjBHvUY++8+t7nysmeYtlxc2V +OgoLkSv7tBvTufMnzYywdNSM55/K86SOwB8YHI18nJcbehkimBNqDPTUmsVGeYFP +oT0c5RAOuMj5aNTq5hPBhz/Xjy2pn26cHoe+JQV0S2vmuNk8rj+ZK+QfRegMjTY8 +BGI5R0XQOXhfzwJ6K2UBIds29fHfEfQ5dknSbXeDy1QILYQYRxr80uWkdVvUeKX/ +zvkK6e7oQYWvBBC+B51OF403UlwPksa7dXoskfTkN/5zbUu4jm7H517+fQpDeicF +G7N8X1DOEnMltzs4vIeymiQYf1CbmvywV9i67am1oKZiErc0gGueBoKQer0PuUPM +kN57FTEEGHKGBBLhQopGUCa1r9w8ueUaI1kNhJyWds+nnlpIm9vHyvvwHfuB+rip +mLsX7rXSZIhBmxAZe0+ZGHPiWend5STtvEXSiKN03i3kYejH4UvVveDilaQ6Y76L +tuPleLvEYwjDs/MQH1C6W/uM5MtIaAIjOOgfGQ5SCydDPsYfB/SZXk4kSWqmr/ft +lh/HASJDfmTO6xE0dDeShNDezNVq3KSLEPy/2Hxgs6EQ/m0evO1SGISN9+IIbwjK +JycN7BSJfRYfC8cXb9mk0BoH7BO/YVhwil/UK/gC/yHZEdOQH+j6YiljbKodSR5+ +frRUOdh22wA3KAwflTqlSD9pkdMgmTrwHVIeXDJo50rkOsCvxUgnHfxaXkgtqhKb +5GMBmxTrHM7cB0+eUOSRtxpMsU71gBQIfwLLwQIDAQABAoIEAQFARdKWMBrJfoVt +vhYU88iV3fo7sPQ9zTEozO60C6eG2rfJWV812//1YXUQ/f4YqXY+FzkScPmrklG3 +ZINKsp3OXo7x+Qeyj1edi7MyWbXa9PpLB1TNK5IIaL2wU+PFZ8Fo3QLtuyE4IVZc +GXbJWAYHKhCAjTwFH1S1bsrm/JKL7qIV/em160BTDgPbdScpdW7OrUAP6lSQxnYw +By6eQaUkYx+GUb4YAS9b86qgbYNVr9+svOqpKuFbrSY/4tI8ZpkEozXbjtfpnMRP +XiwddJdLVeotXSq60aI2lUZew3BCF+3PLaQF3CMSG3eUSWQE8IZcuDiNgEPsHXBI +mThP5JaIiivopfV4nbrULZQO2IfrgxyzFjUTEGcxxPrAwV9lbGSccuK56btK7Xjp +Q6GgS5zOSZFCanFMp+Pvf775pX904h/IAAXSbZWnjJob4I0qAwePZXkkMeqf3yTE +UAHeIKJTd5OMZtsbIHhwx3yFQs377iR6cH5IgIM6FKk1U7HpX3ipxBLZU3HW2rfK +YMBaDzx5nhAZIGCx2HhP4wHGEEzSsVAznZGLMBWgBN1qrq4le3LTPUy5gvQPsIoi +JsUDrA1xIrHOx1tAwniCaaLkQPWVuktrssuweNqMmlAU1lEA8aA9begufiKvQ9Ae +Sd+kQ/rwJHOeX243ZN/5OOYF7RPv2dfVvw0WeXKCJVgouEuW2xH47N5jTkFSPU/h +DJezrTJqwntKsw0JBEFKwyBmEcjKXN+mOF7Xg+qOY/xGVQU4Yk38/w9tyuBACpDG +76r7cE2T4a4awwF9h1qvV8POUSK2AE6G6+v/UW3DRlyDy/xLn/qjMSiF6FSyKgu/ +hxcIxQxX42z7PLSAzjeNQ19QvxU+yyR4F87OCudJJSC1JlIesTx9jQnJC135h002 +CRYemJ7NlRs69HS0Ut00cuhDcdwgEyZo2E2aiIGRi7WRPBFo6cIgDTuqgckwt++0 +BocQX2j2Qg0lGVollAnjzNoRBKzMJhr4s62awzvhK1SkCTuJPFbUXBKC+Ij+KftW +Rh/VnazKtBAzpGwgqeYzEsHfeH1lvkebzZvlG6EUvXD3Y6SnWUYhU8XGkMkcyZwP +z1RCCuPutXTKMstKrQy3d+v+9e8oL8dmLrfn1jHJPOzxLxDpvgBCBLkIuyzERuVV +kyfmYeAdgFK4/0q1G5CaUkgLrj604kle1EhQp2OjSbecBm72ze7lolUZHTloxxSB +mcAyhrDotCuyS8KYLh7zypNn4UxPyTGQhUWKT8eyCALhbJzi07s2MY8d+fnwBqUE +WzKLcEWcDNKnuqQ3JePW7bQpHQMjZJAqQLohqBjwbI4vx3CCGsqALNvcnijWcR88 +K5AqcXktAoICAQG2oc0dLLo+O7mXpoIH20Q8b1chu12cLyR8kpvJaNFOjZ6cxzYe +nOqRIbaB4Gvc0KMO4yFw+E2c5Hb0AlSXqSJd0NEfo8rwgjbSlIWOMZ2Q8OLKut4w +ZgpZaPL+9pIGIvv8gaNXniO/1wfh06esFHjjYW/25g3l2hCAf0kOR2AahL1aht/Z +2bsdGvjHUvZ0UlN4uNPPYRkL7lMMMuJR6Jj8vhe+gnbJtgs0lDljboMyqJCGKAT9 +JgK0iR7AHu8dPo+HFwjYhc8GkWZow89tO0+hqfd4fnQAtTqJe2U3TTSAMcPB5Fhv +e++eelzb1DParimKwAHJzg41ul18MCcG9nG6iaaAkL8sRCxgGS8SyHgT/bRoQLz3 +o8E9VekI3rzZWVsCd/dSmia1+JG4t1wrRZZR0737yLNA7P860IHrgUMuDBKEdITY +eYnfx5i73PReg5qSJK9RwzoJx3PgAQZSxY9lfM/6wmugOXRrlfcbpkYfHxPE4H/T +RzJE57neD/buFUCkTpcfU2nf4KmhZfNESd+zjGFIC5D9wc5tw+trBbqFIsek+Rq8 +524Z5VGFAwZDC13YwRFYyhCBJ9HMHyN7Wl6IbJ5plWhYEkD8WzLYFxjUnyamSmIF +C+sFK90d2SQqmiEN18vYf824gH2qBxkn85xY730K9dAs/5XM9oCfzIlmewKCAgEA +3GVvtyANtsqlpAcPYh7tkg9x6KA90+Q1QJFHA0otu6MBBwhqdDcsgCPSiteii5+7 +MTAtQ1loOjyPQuTaP7cegLc9cXfTdgU3lqLpYTUsXSznw6HlELxZTnUPizSSlUs+ +oRm2YvYEH7eHZb1DVRcLZ+pGEMDKk95MoLj+aJQWBYUN6qFPPNCVMo7bLG4mwGeJ +Ewp7KRBZckKqOoOub7Og8/+JIHfgRR+29THCtKEV1oB3cnKHgJ6vo228Z6yMZpe4 +UNg3HogiB5DvVRDhHVIqHMz1ErHALOxw2ZPoNJDHRCK1OL3I7HehhD/fKd/vC16X +MjYOEq2mmmGFivT20zJBJDjuEl4QuX/IU4wXNZ4D3nCyFW+y45c/8WUhiGW0XcSU +gbDF9Tmlj9nHr+SijzJYbPI1c01qY8ptZ/j9CX4as22PK4+EEoI/g+zLU4XdVtH7 +PzwWcCiznLiBejWSBcaR1O9zXpFnRyK6oYdsKSPllLX2Jppa4hG2c5O40J9aPvPd +dmDxtdutDviknecNXBI/IXBsNrVj5GJk1aAtzLlDFcVmyWPafq/blGM3X3lSdpby +mz/Vl77LSUuujiKH4YNZGlWqH2TZ12WoCEpIJ8OFGRm78cEse+44bn7TpnVjVWXR +2x+NQImzGtnMwZG08l8ZZnH0qf7v5BWMRb7db2vm//MCggIBAS2kVZcjpCyaDAaj +Jjba7jEVbHkxDa4TqWbVt7apk48Oyy4LvUcOKC2IXqcwO10OSaQ6REwZJd6oKrmh +RKVLVevoZ3f3vt7o3WSxaKshqbb8QSqjmZr1AVb9WmZGEKORuXKrgDYH9ZO+/5eo +Y11ucrgD0Oicyp/v93s2jXn5UbjK4iD4Mcbx+cCJRN5mSkAyQV761AaAQqY2zfvM +nmEvsM3WuCN2OtR6kXgmGtUrMaRL0Z/As7WXRzL6PSBn5Y5Z8IA5Mgcc9gMRSLjx +N5tpt1h4t0uwwnueJdRX/IIsYNdr4bBcJQj91QpKIcO3SbWwIbdeVZx/TLxcHmAC +CUS7g/iBIvS1FhMOCupHR10GabVtunwbURiID6Lriqdj7cEWtwSalYXDpq1rdGLw +Db1gTICXOcaF/ee/U8IRk9bt/NIU0UMvkhAAfPVcoMdIqvC4Vjr8aWiz9hy1ghVg +/wU7AWMMk0ZiH3t/J3W5Gsdz8DMEvyacMKuOAZ7rMKHqnqiaCuszdK/BQEUKjf0F +TGcA2oryFhBii+JGPnyzyBjARsW55kuoV1/jU48RaZ8sNkky7uXZ1+EUjIcVaCyU +mWUB/5KYB9SaP7iZTQF+gheiwputmvmum3vW91eGE7isFDgL6IFJjtCjC0k/a6va +18zmtfVfNMGty+y2E0Fxn4DFOxQzAoICAB/Oe8rf01rX8AO2CSBN+lcj53p89a9I +te61iJwO7n6vzYwoSMSw2bk8cjwbVpfz214D5+RaWNJevwYWZPDhCoPk7fccJeZY +ZmdU531h4R8pReFT0e0SYYkTF8UtNyJYk5dIUKwDeSDiqaWjJL547up2QtpUGGgy +orhnOj/5bxwo0ZNU6EyMhZugRj0pQGpwBrY6wv9wHpiAynRbYKc6MzZDYJTQ+ArB +wvOr1L+gp7gnHhXkNW34eLyLL69+lVyQ9MamDX5YgyC4Z/HM19AVdYJmic/C20sg +bEDaOZ6sbjWFFMY1jXOi6Cpf1WMDsEnhwsw6RNmpOev5uv4M0Do2fHQvyxvXe25p +5I06IHdacJB/jxPM5PI3d8DsqWQ32UnW/t+glVEImr4h3dGim1szFtPSOKiFOZ9h +LVzd8BaYnl3ap9jPg23wYh415DoPjZvj/fBoSYyyMwmhDv6GEKbIu28Rh4LUVSVM ++8Yn9xIQ3icSA44apJcPm1cesINbG/kN1J4q63clVtpcQ9WN7L2m3HmE8fkLQHlL +QeYakcGD0wynSmgyAuxZkMTfdLRQm/gFXMnO8pJNtKTFSVG15gpDnG5SgpS5Rz7w +qslXfwZODz1KG3eOO08/V+GKaB0Tv9wpL5oB+a6gsLplSEl/L6/yzYWdWIPYCOLP +wUinfOmBlvrFAoICAQEKJzfms84mnWw9nhjZkSqNuHG7jHI1rXOPe0+ak72k6fIA +cQ2sLZUlmlZuNfp9Y5TSaMQHp8owMw048O0kv2ghrmjtrqpe/cd7d6ltUEWE4Di7 ++2q8m9u/quSAs6O4ITR5Htw5oHHxHNzSpSzFXrp37gMekjNEGaSMyn22oR53uQp7 +AGywnsmb+Kxkl56dPwZmKm/Gp4ESgfLSV5jKl7CFqwpvNp7iV2nspqz0gleSM2iB +wMCVFIlA1v3yYag+rDW/o7nDB9NPvKAeb/C+CDyAbWwz89QEV0jMAIsk2R4fpTHD +HySUuCKwjc0aqvI3xVnAvZoJNPnLtPoS9H5vaNNj5stsBl8Y6QK+knuWzej5sCZV +ulSJLHQOGdA0MDfTE4pz9EQ3jCr3h5G8ZURUrXjnPKwFFWVp1qV+4Ayh+rcxqF7l +ewSP5Tlj7HguOqBkqHDoPsxB+yto1NeYQ/aNARYaC3ojNQReTm/4SHl74zq9SjMW +1rxIxZBoEH1NO93Dq0GLQyrOOvHLp3JRrNbIsYWON5g7mTV7m7dr2y3UUwRbOqKo +NViTsG9Q6p5BEey0A06V0jpjMEuc/KLq/dv8rvEKOq219oztnnp5sw2bTqgxqOHC +DsjiyAkM1hDmiHVxIPv114eJXv96a41DGKcdRXLqQiHlWcTtCCl/xS/oQom+qg== +-----END RSA PRIVATE KEY----- diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa8193pub.pem b/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa8193pub.pem new file mode 100644 index 0000000000..864137fcb9 --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/crypto/rsa/test/rsa8193pub.pem @@ -0,0 +1,25 @@ +-----BEGIN PUBLIC KEY----- +MIIEIjANBgkqhkiG9w0BAQEFAAOCBA8AMIIECgKCBAEBeaDZhOt3skLqjWcZLNFT ++9klhXTS6wSwPhz8dBfyovOgm0YF/jyqb8TfrwbrD4+KpOHqiSigqyrHgBAwCxS5 +Nb7yEfP35Fx5fBRlxwy+t4hiyJrvkIGerlIvXGl0AErm7Le/wOk6pCtEuCxD3U3g +FB5EbOyW6a6pgN7YTV+uiUieWQKeiZiJwjYOlqhszJuCSFswAsZCn0665w6d79qB +soYSfnhGmsbTgmNgM0DOWejIwdR91ocnHnXCQqsOo1UBU9koWFdNvfwTWDvtZCLl +fAh7Q6jg6BydknIkuenvH1oeqSptyfm/7SDS1J0qyxZbijdD7bW3Wd5aN5Rgq4ot +pd6EuOtTUMtnmJzRGhNiaSTs0W0t8FHYTKiSai5TOEt4NWyRI6evqShxLzmZQ614 +cZ/8qlY1ab0144akLpyzd+rVzF5xtU03IZKC2dElajaopSqCOt20dxNJgBDUhJnj +ePzB9MhF59YfbQ8Bv789csekQbNWIIUkG2TzGWxT5x313SgPDtYdxdUPJz0ZKjDv +Bcq4PAYkqZ//vmSWZBxBbvm+tE3JbPcSwBkLF9XHTeUO1DkhFi8t1/9YXS/rMYCs +3hazjBHvUY++8+t7nysmeYtlxc2VOgoLkSv7tBvTufMnzYywdNSM55/K86SOwB8Y +HI18nJcbehkimBNqDPTUmsVGeYFPoT0c5RAOuMj5aNTq5hPBhz/Xjy2pn26cHoe+ +JQV0S2vmuNk8rj+ZK+QfRegMjTY8BGI5R0XQOXhfzwJ6K2UBIds29fHfEfQ5dknS +bXeDy1QILYQYRxr80uWkdVvUeKX/zvkK6e7oQYWvBBC+B51OF403UlwPksa7dXos +kfTkN/5zbUu4jm7H517+fQpDeicFG7N8X1DOEnMltzs4vIeymiQYf1CbmvywV9i6 +7am1oKZiErc0gGueBoKQer0PuUPMkN57FTEEGHKGBBLhQopGUCa1r9w8ueUaI1kN +hJyWds+nnlpIm9vHyvvwHfuB+ripmLsX7rXSZIhBmxAZe0+ZGHPiWend5STtvEXS +iKN03i3kYejH4UvVveDilaQ6Y76LtuPleLvEYwjDs/MQH1C6W/uM5MtIaAIjOOgf +GQ5SCydDPsYfB/SZXk4kSWqmr/ftlh/HASJDfmTO6xE0dDeShNDezNVq3KSLEPy/ +2Hxgs6EQ/m0evO1SGISN9+IIbwjKJycN7BSJfRYfC8cXb9mk0BoH7BO/YVhwil/U +K/gC/yHZEdOQH+j6YiljbKodSR5+frRUOdh22wA3KAwflTqlSD9pkdMgmTrwHVIe +XDJo50rkOsCvxUgnHfxaXkgtqhKb5GMBmxTrHM7cB0+eUOSRtxpMsU71gBQIfwLL +wQIDAQAB +-----END PUBLIC KEY----- diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/sha/sha256.cc b/naiveproxy/src/third_party/boringssl/src/crypto/sha/sha256.cc index 9a0b6cb1cb..b3f40ce462 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/sha/sha256.cc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/sha/sha256.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include +#include #include diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/sha/sha512.cc b/naiveproxy/src/third_party/boringssl/src/crypto/sha/sha512.cc index 40a2a797bd..a24f7170aa 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/sha/sha512.cc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/sha/sha512.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include +#include #include diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/spake2plus/internal.h b/naiveproxy/src/third_party/boringssl/src/crypto/spake2plus/internal.h index c5c99cdbec..7344c57eec 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/spake2plus/internal.h +++ b/naiveproxy/src/third_party/boringssl/src/crypto/spake2plus/internal.h @@ -19,7 +19,7 @@ #include -#include +#include #include #include "../fipsmodule/ec/internal.h" diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/spake2plus/spake2plus.cc b/naiveproxy/src/third_party/boringssl/src/crypto/spake2plus/spake2plus.cc index 2e29f1fcd7..edf26294bc 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/spake2plus/spake2plus.cc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/spake2plus/spake2plus.cc @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include "../fipsmodule/bn/internal.h" #include "../fipsmodule/ec/internal.h" diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/trust_token/pmbtoken.cc b/naiveproxy/src/third_party/boringssl/src/crypto/trust_token/pmbtoken.cc index 09b5de2832..58ba28f256 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/trust_token/pmbtoken.cc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/trust_token/pmbtoken.cc @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include "../ec/internal.h" #include "../fipsmodule/bn/internal.h" diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/trust_token/trust_token.cc b/naiveproxy/src/third_party/boringssl/src/crypto/trust_token/trust_token.cc index 41ef6b7d65..a5c2b879e6 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/trust_token/trust_token.cc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/trust_token/trust_token.cc @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include "internal.h" diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/trust_token/voprf.cc b/naiveproxy/src/third_party/boringssl/src/crypto/trust_token/voprf.cc index 02ba58d403..9eca4bf66a 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/trust_token/voprf.cc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/trust_token/voprf.cc @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include "../ec/internal.h" #include "../fipsmodule/ec/internal.h" diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/armv8-mont-apple.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/armv8-mont-apple.S index 6aad968129..fadf3e2463 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/armv8-mont-apple.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/armv8-mont-apple.S @@ -6,11 +6,11 @@ #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_AARCH64) && defined(__APPLE__) .text -.globl _bn_mul_mont -.private_extern _bn_mul_mont +.globl _bn_mul_mont_words +.private_extern _bn_mul_mont_words .align 5 -_bn_mul_mont: +_bn_mul_mont_words: AARCH64_SIGN_LINK_REGISTER tst x5,#7 b.eq __bn_sqr8x_mont @@ -216,7 +216,7 @@ Lcond_copy: .align 5 __bn_sqr8x_mont: // Not adding AARCH64_SIGN_LINK_REGISTER here because __bn_sqr8x_mont is jumped to - // only from bn_mul_mont which has already signed the return address. + // only from bn_mul_mont_words which has already signed the return address. cmp x1,x2 b.ne __bn_mul4x_mont Lsqr8x_mont: @@ -978,7 +978,7 @@ Lsqr8x_done: .align 5 __bn_mul4x_mont: // Not adding AARCH64_SIGN_LINK_REGISTER here because __bn_mul4x_mont is jumped to - // only from bn_mul_mont or __bn_mul8x_mont which have already signed the + // only from bn_mul_mont_words or __bn_mul8x_mont which have already signed the // return address. stp x29,x30,[sp,#-128]! add x29,sp,#0 diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/armv8-mont-linux.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/armv8-mont-linux.S index e49322b0c6..574647f82d 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/armv8-mont-linux.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/armv8-mont-linux.S @@ -6,11 +6,11 @@ #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_AARCH64) && defined(__ELF__) .text -.globl bn_mul_mont -.hidden bn_mul_mont -.type bn_mul_mont,%function +.globl bn_mul_mont_words +.hidden bn_mul_mont_words +.type bn_mul_mont_words,%function .align 5 -bn_mul_mont: +bn_mul_mont_words: AARCH64_SIGN_LINK_REGISTER tst x5,#7 b.eq __bn_sqr8x_mont @@ -211,12 +211,12 @@ bn_mul_mont: ldr x29,[sp],#64 AARCH64_VALIDATE_LINK_REGISTER ret -.size bn_mul_mont,.-bn_mul_mont +.size bn_mul_mont_words,.-bn_mul_mont_words .type __bn_sqr8x_mont,%function .align 5 __bn_sqr8x_mont: // Not adding AARCH64_SIGN_LINK_REGISTER here because __bn_sqr8x_mont is jumped to - // only from bn_mul_mont which has already signed the return address. + // only from bn_mul_mont_words which has already signed the return address. cmp x1,x2 b.ne __bn_mul4x_mont .Lsqr8x_mont: @@ -978,7 +978,7 @@ __bn_sqr8x_mont: .align 5 __bn_mul4x_mont: // Not adding AARCH64_SIGN_LINK_REGISTER here because __bn_mul4x_mont is jumped to - // only from bn_mul_mont or __bn_mul8x_mont which have already signed the + // only from bn_mul_mont_words or __bn_mul8x_mont which have already signed the // return address. stp x29,x30,[sp,#-128]! add x29,sp,#0 diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/armv8-mont-win.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/armv8-mont-win.S index 4091a5ada0..84f3473e5f 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/armv8-mont-win.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/armv8-mont-win.S @@ -6,13 +6,13 @@ #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_AARCH64) && defined(_WIN32) .text -.globl bn_mul_mont +.globl bn_mul_mont_words -.def bn_mul_mont +.def bn_mul_mont_words .type 32 .endef .align 5 -bn_mul_mont: +bn_mul_mont_words: AARCH64_SIGN_LINK_REGISTER tst x5,#7 b.eq __bn_sqr8x_mont @@ -220,7 +220,7 @@ Lcond_copy: .align 5 __bn_sqr8x_mont: // Not adding AARCH64_SIGN_LINK_REGISTER here because __bn_sqr8x_mont is jumped to - // only from bn_mul_mont which has already signed the return address. + // only from bn_mul_mont_words which has already signed the return address. cmp x1,x2 b.ne __bn_mul4x_mont Lsqr8x_mont: @@ -984,7 +984,7 @@ Lsqr8x_done: .align 5 __bn_mul4x_mont: // Not adding AARCH64_SIGN_LINK_REGISTER here because __bn_mul4x_mont is jumped to - // only from bn_mul_mont or __bn_mul8x_mont which have already signed the + // only from bn_mul_mont_words or __bn_mul8x_mont which have already signed the // return address. stp x29,x30,[sp,#-128]! add x29,sp,#0 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 6e549c71d4..89e439bae2 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 @@ -5,11 +5,11 @@ #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && defined(__APPLE__) .text -.globl _bn_mul_mont -.private_extern _bn_mul_mont +.globl _bn_mul_mont_words +.private_extern _bn_mul_mont_words .align 4 -_bn_mul_mont: -L_bn_mul_mont_begin: +_bn_mul_mont_words: +L_bn_mul_mont_words_begin: pushl %ebp pushl %ebx pushl %esi 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 21fbee22e6..edf98a27fb 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 @@ -5,12 +5,12 @@ #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && defined(__ELF__) .text -.globl bn_mul_mont -.hidden bn_mul_mont -.type bn_mul_mont,@function +.globl bn_mul_mont_words +.hidden bn_mul_mont_words +.type bn_mul_mont_words,@function .align 16 -bn_mul_mont: -.L_bn_mul_mont_begin: +bn_mul_mont_words: +.L_bn_mul_mont_words_begin: pushl %ebp pushl %ebx pushl %esi @@ -209,7 +209,7 @@ bn_mul_mont: popl %ebx popl %ebp ret -.size bn_mul_mont,.-.L_bn_mul_mont_begin +.size bn_mul_mont_words,.-.L_bn_mul_mont_words_begin .byte 77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105 .byte 112,108,105,99,97,116,105,111,110,32,102,111,114,32,120,56 .byte 54,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121 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 d154078964..f9d12bb0a8 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,10 +13,10 @@ section .text code align=64 %else section .text code %endif -global _bn_mul_mont +global _bn_mul_mont_words align 16 -_bn_mul_mont: -L$_bn_mul_mont_begin: +_bn_mul_mont_words: +L$_bn_mul_mont_words_begin: push ebp push ebx push esi diff --git a/naiveproxy/src/third_party/boringssl/src/gen/sources.bzl b/naiveproxy/src/third_party/boringssl/src/gen/sources.bzl index 9f976f0c37..dc70c3f1ad 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/sources.bzl +++ b/naiveproxy/src/third_party/boringssl/src/gen/sources.bzl @@ -584,6 +584,7 @@ crypto_headers = [ "include/openssl/safestack.h", "include/openssl/service_indicator.h", "include/openssl/sha.h", + "include/openssl/sha2.h", "include/openssl/siphash.h", "include/openssl/slhdsa.h", "include/openssl/span.h", @@ -670,7 +671,10 @@ crypto_internal_headers = [ "third_party/fiat/p256_32.h", "third_party/fiat/p256_64.h", "third_party/fiat/p256_64_msvc.h", - "third_party/fiat/p256_bedrock.c.inc", + "third_party/fiat/p256_field.c.inc", + "third_party/fiat/p256_field_32.br.c.inc", + "third_party/fiat/p256_field_64.br.c.inc", + "third_party/fiat/p256_point.br.c.inc", ] crypto_sources_asm = [ @@ -853,8 +857,10 @@ crypto_test_data = [ "crypto/hmac/hmac_tests.txt", "crypto/hpke/hpke_test_vectors.txt", "crypto/kyber/kyber_tests.txt", + "crypto/mldsa/mldsa_nist_keygen_44_tests.txt", "crypto/mldsa/mldsa_nist_keygen_65_tests.txt", "crypto/mldsa/mldsa_nist_keygen_87_tests.txt", + "crypto/mldsa/mldsa_nist_siggen_44_tests.txt", "crypto/mldsa/mldsa_nist_siggen_65_tests.txt", "crypto/mldsa/mldsa_nist_siggen_87_tests.txt", "crypto/mlkem/mlkem1024_decap_tests.txt", @@ -891,6 +897,14 @@ crypto_test_data = [ "crypto/pkcs8/test/unicode_password.p12", "crypto/pkcs8/test/windows.p12", "crypto/poly1305/poly1305_tests.txt", + "crypto/rsa/test/rsa511.pem", + "crypto/rsa/test/rsa511pub.pem", + "crypto/rsa/test/rsa512.pem", + "crypto/rsa/test/rsa512pub.pem", + "crypto/rsa/test/rsa8192.pem", + "crypto/rsa/test/rsa8192pub.pem", + "crypto/rsa/test/rsa8193.pem", + "crypto/rsa/test/rsa8193pub.pem", "crypto/siphash/siphash_tests.txt", "crypto/slhdsa/slhdsa_keygen.txt", "crypto/slhdsa/slhdsa_prehash.txt", @@ -1021,6 +1035,8 @@ crypto_test_data = [ "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/mldsa_44_standard_sign_test.txt", + "third_party/wycheproof_testvectors/mldsa_44_standard_verify_test.txt", "third_party/wycheproof_testvectors/mldsa_65_standard_sign_test.txt", "third_party/wycheproof_testvectors/mldsa_65_standard_verify_test.txt", "third_party/wycheproof_testvectors/mldsa_87_standard_sign_test.txt", diff --git a/naiveproxy/src/third_party/boringssl/src/gen/sources.cmake b/naiveproxy/src/third_party/boringssl/src/gen/sources.cmake index 978ada96b1..df53126ed1 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/sources.cmake +++ b/naiveproxy/src/third_party/boringssl/src/gen/sources.cmake @@ -600,6 +600,7 @@ set( include/openssl/safestack.h include/openssl/service_indicator.h include/openssl/sha.h + include/openssl/sha2.h include/openssl/siphash.h include/openssl/slhdsa.h include/openssl/span.h @@ -688,7 +689,10 @@ set( third_party/fiat/p256_32.h third_party/fiat/p256_64.h third_party/fiat/p256_64_msvc.h - third_party/fiat/p256_bedrock.c.inc + third_party/fiat/p256_field.c.inc + third_party/fiat/p256_field_32.br.c.inc + third_party/fiat/p256_field_64.br.c.inc + third_party/fiat/p256_point.br.c.inc ) set( @@ -879,8 +883,10 @@ set( crypto/hmac/hmac_tests.txt crypto/hpke/hpke_test_vectors.txt crypto/kyber/kyber_tests.txt + crypto/mldsa/mldsa_nist_keygen_44_tests.txt crypto/mldsa/mldsa_nist_keygen_65_tests.txt crypto/mldsa/mldsa_nist_keygen_87_tests.txt + crypto/mldsa/mldsa_nist_siggen_44_tests.txt crypto/mldsa/mldsa_nist_siggen_65_tests.txt crypto/mldsa/mldsa_nist_siggen_87_tests.txt crypto/mlkem/mlkem1024_decap_tests.txt @@ -917,6 +923,14 @@ set( crypto/pkcs8/test/unicode_password.p12 crypto/pkcs8/test/windows.p12 crypto/poly1305/poly1305_tests.txt + crypto/rsa/test/rsa511.pem + crypto/rsa/test/rsa511pub.pem + crypto/rsa/test/rsa512.pem + crypto/rsa/test/rsa512pub.pem + crypto/rsa/test/rsa8192.pem + crypto/rsa/test/rsa8192pub.pem + crypto/rsa/test/rsa8193.pem + crypto/rsa/test/rsa8193pub.pem crypto/siphash/siphash_tests.txt crypto/slhdsa/slhdsa_keygen.txt crypto/slhdsa/slhdsa_prehash.txt @@ -1047,6 +1061,8 @@ set( 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/mldsa_44_standard_sign_test.txt + third_party/wycheproof_testvectors/mldsa_44_standard_verify_test.txt third_party/wycheproof_testvectors/mldsa_65_standard_sign_test.txt third_party/wycheproof_testvectors/mldsa_65_standard_verify_test.txt third_party/wycheproof_testvectors/mldsa_87_standard_sign_test.txt diff --git a/naiveproxy/src/third_party/boringssl/src/gen/sources.gni b/naiveproxy/src/third_party/boringssl/src/gen/sources.gni index 4a7947c167..c6d3ef1806 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/sources.gni +++ b/naiveproxy/src/third_party/boringssl/src/gen/sources.gni @@ -584,6 +584,7 @@ crypto_headers = [ "include/openssl/safestack.h", "include/openssl/service_indicator.h", "include/openssl/sha.h", + "include/openssl/sha2.h", "include/openssl/siphash.h", "include/openssl/slhdsa.h", "include/openssl/span.h", @@ -670,7 +671,10 @@ crypto_internal_headers = [ "third_party/fiat/p256_32.h", "third_party/fiat/p256_64.h", "third_party/fiat/p256_64_msvc.h", - "third_party/fiat/p256_bedrock.c.inc", + "third_party/fiat/p256_field.c.inc", + "third_party/fiat/p256_field_32.br.c.inc", + "third_party/fiat/p256_field_64.br.c.inc", + "third_party/fiat/p256_point.br.c.inc", ] crypto_sources_asm = [ @@ -853,8 +857,10 @@ crypto_test_data = [ "crypto/hmac/hmac_tests.txt", "crypto/hpke/hpke_test_vectors.txt", "crypto/kyber/kyber_tests.txt", + "crypto/mldsa/mldsa_nist_keygen_44_tests.txt", "crypto/mldsa/mldsa_nist_keygen_65_tests.txt", "crypto/mldsa/mldsa_nist_keygen_87_tests.txt", + "crypto/mldsa/mldsa_nist_siggen_44_tests.txt", "crypto/mldsa/mldsa_nist_siggen_65_tests.txt", "crypto/mldsa/mldsa_nist_siggen_87_tests.txt", "crypto/mlkem/mlkem1024_decap_tests.txt", @@ -891,6 +897,14 @@ crypto_test_data = [ "crypto/pkcs8/test/unicode_password.p12", "crypto/pkcs8/test/windows.p12", "crypto/poly1305/poly1305_tests.txt", + "crypto/rsa/test/rsa511.pem", + "crypto/rsa/test/rsa511pub.pem", + "crypto/rsa/test/rsa512.pem", + "crypto/rsa/test/rsa512pub.pem", + "crypto/rsa/test/rsa8192.pem", + "crypto/rsa/test/rsa8192pub.pem", + "crypto/rsa/test/rsa8193.pem", + "crypto/rsa/test/rsa8193pub.pem", "crypto/siphash/siphash_tests.txt", "crypto/slhdsa/slhdsa_keygen.txt", "crypto/slhdsa/slhdsa_prehash.txt", @@ -1021,6 +1035,8 @@ crypto_test_data = [ "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/mldsa_44_standard_sign_test.txt", + "third_party/wycheproof_testvectors/mldsa_44_standard_verify_test.txt", "third_party/wycheproof_testvectors/mldsa_65_standard_sign_test.txt", "third_party/wycheproof_testvectors/mldsa_65_standard_verify_test.txt", "third_party/wycheproof_testvectors/mldsa_87_standard_sign_test.txt", diff --git a/naiveproxy/src/third_party/boringssl/src/gen/sources.json b/naiveproxy/src/third_party/boringssl/src/gen/sources.json index 6284d04bf4..8e07625b35 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/sources.json +++ b/naiveproxy/src/third_party/boringssl/src/gen/sources.json @@ -567,6 +567,7 @@ "include/openssl/safestack.h", "include/openssl/service_indicator.h", "include/openssl/sha.h", + "include/openssl/sha2.h", "include/openssl/siphash.h", "include/openssl/slhdsa.h", "include/openssl/span.h", @@ -652,7 +653,10 @@ "third_party/fiat/p256_32.h", "third_party/fiat/p256_64.h", "third_party/fiat/p256_64_msvc.h", - "third_party/fiat/p256_bedrock.c.inc" + "third_party/fiat/p256_field.c.inc", + "third_party/fiat/p256_field_32.br.c.inc", + "third_party/fiat/p256_field_64.br.c.inc", + "third_party/fiat/p256_point.br.c.inc" ], "asm": [ "crypto/curve25519/asm/x25519-asm-arm.S", @@ -833,8 +837,10 @@ "crypto/hmac/hmac_tests.txt", "crypto/hpke/hpke_test_vectors.txt", "crypto/kyber/kyber_tests.txt", + "crypto/mldsa/mldsa_nist_keygen_44_tests.txt", "crypto/mldsa/mldsa_nist_keygen_65_tests.txt", "crypto/mldsa/mldsa_nist_keygen_87_tests.txt", + "crypto/mldsa/mldsa_nist_siggen_44_tests.txt", "crypto/mldsa/mldsa_nist_siggen_65_tests.txt", "crypto/mldsa/mldsa_nist_siggen_87_tests.txt", "crypto/mlkem/mlkem1024_decap_tests.txt", @@ -871,6 +877,14 @@ "crypto/pkcs8/test/unicode_password.p12", "crypto/pkcs8/test/windows.p12", "crypto/poly1305/poly1305_tests.txt", + "crypto/rsa/test/rsa511.pem", + "crypto/rsa/test/rsa511pub.pem", + "crypto/rsa/test/rsa512.pem", + "crypto/rsa/test/rsa512pub.pem", + "crypto/rsa/test/rsa8192.pem", + "crypto/rsa/test/rsa8192pub.pem", + "crypto/rsa/test/rsa8193.pem", + "crypto/rsa/test/rsa8193pub.pem", "crypto/siphash/siphash_tests.txt", "crypto/slhdsa/slhdsa_keygen.txt", "crypto/slhdsa/slhdsa_prehash.txt", @@ -1001,6 +1015,8 @@ "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/mldsa_44_standard_sign_test.txt", + "third_party/wycheproof_testvectors/mldsa_44_standard_verify_test.txt", "third_party/wycheproof_testvectors/mldsa_65_standard_sign_test.txt", "third_party/wycheproof_testvectors/mldsa_65_standard_verify_test.txt", "third_party/wycheproof_testvectors/mldsa_87_standard_sign_test.txt", diff --git a/naiveproxy/src/third_party/boringssl/src/gen/sources.mk b/naiveproxy/src/third_party/boringssl/src/gen/sources.mk index 944b9dc32f..05e0f9f8fa 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/sources.mk +++ b/naiveproxy/src/third_party/boringssl/src/gen/sources.mk @@ -577,6 +577,7 @@ boringssl_crypto_headers := \ include/openssl/safestack.h \ include/openssl/service_indicator.h \ include/openssl/sha.h \ + include/openssl/sha2.h \ include/openssl/siphash.h \ include/openssl/slhdsa.h \ include/openssl/span.h \ @@ -662,7 +663,10 @@ boringssl_crypto_internal_headers := \ third_party/fiat/p256_32.h \ third_party/fiat/p256_64.h \ third_party/fiat/p256_64_msvc.h \ - third_party/fiat/p256_bedrock.c.inc + third_party/fiat/p256_field.c.inc \ + third_party/fiat/p256_field_32.br.c.inc \ + third_party/fiat/p256_field_64.br.c.inc \ + third_party/fiat/p256_point.br.c.inc boringssl_crypto_sources_asm := \ crypto/curve25519/asm/x25519-asm-arm.S \ @@ -841,8 +845,10 @@ boringssl_crypto_test_data := \ crypto/hmac/hmac_tests.txt \ crypto/hpke/hpke_test_vectors.txt \ crypto/kyber/kyber_tests.txt \ + crypto/mldsa/mldsa_nist_keygen_44_tests.txt \ crypto/mldsa/mldsa_nist_keygen_65_tests.txt \ crypto/mldsa/mldsa_nist_keygen_87_tests.txt \ + crypto/mldsa/mldsa_nist_siggen_44_tests.txt \ crypto/mldsa/mldsa_nist_siggen_65_tests.txt \ crypto/mldsa/mldsa_nist_siggen_87_tests.txt \ crypto/mlkem/mlkem1024_decap_tests.txt \ @@ -879,6 +885,14 @@ boringssl_crypto_test_data := \ crypto/pkcs8/test/unicode_password.p12 \ crypto/pkcs8/test/windows.p12 \ crypto/poly1305/poly1305_tests.txt \ + crypto/rsa/test/rsa511.pem \ + crypto/rsa/test/rsa511pub.pem \ + crypto/rsa/test/rsa512.pem \ + crypto/rsa/test/rsa512pub.pem \ + crypto/rsa/test/rsa8192.pem \ + crypto/rsa/test/rsa8192pub.pem \ + crypto/rsa/test/rsa8193.pem \ + crypto/rsa/test/rsa8193pub.pem \ crypto/siphash/siphash_tests.txt \ crypto/slhdsa/slhdsa_keygen.txt \ crypto/slhdsa/slhdsa_prehash.txt \ @@ -1009,6 +1023,8 @@ boringssl_crypto_test_data := \ 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/mldsa_44_standard_sign_test.txt \ + third_party/wycheproof_testvectors/mldsa_44_standard_verify_test.txt \ third_party/wycheproof_testvectors/mldsa_65_standard_sign_test.txt \ third_party/wycheproof_testvectors/mldsa_65_standard_verify_test.txt \ third_party/wycheproof_testvectors/mldsa_87_standard_sign_test.txt \ diff --git a/naiveproxy/src/third_party/boringssl/src/include/openssl/bn.h b/naiveproxy/src/third_party/boringssl/src/include/openssl/bn.h index 82099753bf..d35b06b4d1 100644 --- a/naiveproxy/src/third_party/boringssl/src/include/openssl/bn.h +++ b/naiveproxy/src/third_party/boringssl/src/include/openssl/bn.h @@ -917,16 +917,6 @@ struct bignum_st { int flags; }; -struct bn_mont_ctx_st { - // RR is R^2, reduced modulo |N|. It is used to convert to Montgomery form. It - // is guaranteed to have the same width as |N|. - BIGNUM RR; - // N is the modulus. It is always stored in minimal form, so |N.width| - // determines R. - BIGNUM N; - BN_ULONG n0[2]; // least significant words of (R*Ri-1)/N -}; - OPENSSL_EXPORT unsigned BN_num_bits_word(BN_ULONG l); #define BN_FLG_MALLOCED 0x01 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 ca1ca2f232..1e8e6ad7b4 100644 --- a/naiveproxy/src/third_party/boringssl/src/include/openssl/crypto.h +++ b/naiveproxy/src/third_party/boringssl/src/include/openssl/crypto.h @@ -15,7 +15,7 @@ #ifndef OPENSSL_HEADER_CRYPTO_H #define OPENSSL_HEADER_CRYPTO_H -#include // IWYU pragma: export +#include // IWYU pragma: export #include // Upstream OpenSSL defines |OPENSSL_malloc|, etc., in crypto.h rather than @@ -205,8 +205,7 @@ 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 -// incremented if multiple versions are defined on a single day. +// be a date in the form yyyymmdd. // // (This format exceeds a |uint32_t| in the year 4294.) OPENSSL_EXPORT uint32_t FIPS_version(void); diff --git a/naiveproxy/src/third_party/boringssl/src/include/openssl/dh.h b/naiveproxy/src/third_party/boringssl/src/include/openssl/dh.h index b9287b732a..4397d0e542 100644 --- a/naiveproxy/src/third_party/boringssl/src/include/openssl/dh.h +++ b/naiveproxy/src/third_party/boringssl/src/include/openssl/dh.h @@ -54,7 +54,7 @@ OPENSSL_EXPORT int DH_up_ref(DH *dh); // OPENSSL_DH_MAX_MODULUS_BITS is the maximum supported Diffie-Hellman group // modulus, in bits. -#define OPENSSL_DH_MAX_MODULUS_BITS 10000 +#define OPENSSL_DH_MAX_MODULUS_BITS 8192 // DH_bits returns the size of |dh|'s group modulus, in bits. OPENSSL_EXPORT unsigned DH_bits(const DH *dh); diff --git a/naiveproxy/src/third_party/boringssl/src/include/openssl/dsa.h b/naiveproxy/src/third_party/boringssl/src/include/openssl/dsa.h index 9b3d20c9a2..9b50286139 100644 --- a/naiveproxy/src/third_party/boringssl/src/include/openssl/dsa.h +++ b/naiveproxy/src/third_party/boringssl/src/include/openssl/dsa.h @@ -56,7 +56,7 @@ OPENSSL_EXPORT int DSA_up_ref(DSA *dsa); // OPENSSL_DSA_MAX_MODULUS_BITS is the maximum supported DSA group modulus, in // bits. -#define OPENSSL_DSA_MAX_MODULUS_BITS 10000 +#define OPENSSL_DSA_MAX_MODULUS_BITS 8192 // DSA_bits returns the size of |dsa|'s group modulus, in bits. OPENSSL_EXPORT unsigned DSA_bits(const DSA *dsa); diff --git a/naiveproxy/src/third_party/boringssl/src/include/openssl/ec.h b/naiveproxy/src/third_party/boringssl/src/include/openssl/ec.h index 6f1d3d5060..29dc86a15d 100644 --- a/naiveproxy/src/third_party/boringssl/src/include/openssl/ec.h +++ b/naiveproxy/src/third_party/boringssl/src/include/openssl/ec.h @@ -107,8 +107,8 @@ OPENSSL_EXPORT const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group); // EC_GROUP_order_bits returns the number of bits of the order of |group|. OPENSSL_EXPORT int EC_GROUP_order_bits(const EC_GROUP *group); -// EC_GROUP_get_cofactor sets |*cofactor| to the cofactor of |group| using -// |ctx|, if it's not NULL. It returns one on success and zero otherwise. +// EC_GROUP_get_cofactor sets |*cofactor| to the cofactor of |group|. It returns +// one on success and zero otherwise. |ctx| is ignored and may be NULL. OPENSSL_EXPORT int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx); @@ -116,7 +116,7 @@ OPENSSL_EXPORT int EC_GROUP_get_cofactor(const EC_GROUP *group, // |*out_p| to the order of the coordinate field and |*out_a| and |*out_b| to // the parameters of the curve when expressed as y² = x³ + ax + b. Any of the // output parameters can be NULL. It returns one on success and zero on -// error. +// error. |ctx| is ignored and may be NULL. OPENSSL_EXPORT int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *out_p, BIGNUM *out_a, BIGNUM *out_b, BN_CTX *ctx); @@ -169,12 +169,12 @@ OPENSSL_EXPORT int EC_POINT_is_at_infinity(const EC_GROUP *group, // EC_POINT_is_on_curve returns one if |point| is an element of |group| and // and zero otherwise or when an error occurs. This is different from OpenSSL, -// which returns -1 on error. If |ctx| is non-NULL, it may be used. +// which returns -1 on error. |ctx| is ignored and may be NULL. OPENSSL_EXPORT int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx); // EC_POINT_cmp returns zero if |a| is equal to |b|, greater than zero if -// not equal and -1 on error. If |ctx| is not NULL, it may be used. +// not equal and -1 on error. |ctx| is ignored and may be NULL. OPENSSL_EXPORT int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx); @@ -182,8 +182,8 @@ OPENSSL_EXPORT int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, // Point conversion. // EC_POINT_get_affine_coordinates_GFp sets |x| and |y| to the affine value of -// |point| using |ctx|, if it's not NULL. It returns one on success and zero -// otherwise. +// |point|. It returns one on success and zero otherwise. |ctx| is ignored and +// may be NULL. // // Either |x| or |y| may be NULL to skip computing that coordinate. This is // slightly faster in the common case where only the x-coordinate is needed. @@ -200,9 +200,8 @@ OPENSSL_EXPORT int EC_POINT_get_affine_coordinates(const EC_GROUP *group, BN_CTX *ctx); // EC_POINT_set_affine_coordinates_GFp sets the value of |point| to be -// (|x|, |y|). The |ctx| argument may be used if not NULL. It returns one -// on success or zero on error. It's considered an error if the point is not on -// the curve. +// (|x|, |y|). |ctx| is ignored and may be NULL. It returns one on success or +// zero on error. It's considered an error if the point is not on the curve. // // Note that the corresponding function in OpenSSL versions prior to 1.0.2s does // not check if the point is on the curve. This is a security-critical check, so @@ -226,7 +225,7 @@ OPENSSL_EXPORT int EC_POINT_set_affine_coordinates(const EC_GROUP *group, // EC_POINT_point2oct serialises |point| into the X9.62 form given by |form| // into, at most, |max_out| bytes at |buf|. It returns the number of bytes // written or zero on error if |buf| is non-NULL, else the number of bytes -// needed. The |ctx| argument may be used if not NULL. +// needed. |ctx| is ignored and may be NULL. OPENSSL_EXPORT size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, @@ -236,30 +235,31 @@ OPENSSL_EXPORT size_t EC_POINT_point2oct(const EC_GROUP *group, // EC_POINT_point2buf serialises |point| into the X9.62 form given by |form| to // a newly-allocated buffer and sets |*out_buf| to point to it. It returns the // length of the result on success or zero on error. The caller must release -// |*out_buf| with |OPENSSL_free| when done. +// |*out_buf| with |OPENSSL_free| when done. |ctx| is ignored and may be NULL. OPENSSL_EXPORT size_t EC_POINT_point2buf(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, uint8_t **out_buf, BN_CTX *ctx); // EC_POINT_point2cbb behaves like |EC_POINT_point2oct| but appends the -// serialised point to |cbb|. It returns one on success and zero on error. +// serialised point to |cbb|. It returns one on success and zero on error. |ctx| +// is ignored and may be NULL. OPENSSL_EXPORT int EC_POINT_point2cbb(CBB *out, const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, BN_CTX *ctx); // EC_POINT_oct2point sets |point| from |len| bytes of X9.62 format -// serialisation in |buf|. It returns one on success and zero on error. The -// |ctx| argument may be used if not NULL. It's considered an error if |buf| -// does not represent a point on the curve. +// serialisation in |buf|. It returns one on success and zero on error. |ctx| +// may be NULL. It's considered an error if |buf| does not represent a point on +// the curve. OPENSSL_EXPORT int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point, const uint8_t *buf, size_t len, BN_CTX *ctx); // EC_POINT_set_compressed_coordinates_GFp sets |point| to equal the point with // the given |x| coordinate and the y coordinate specified by |y_bit| (see -// X9.62). It returns one on success and zero otherwise. +// X9.62). It returns one on success and zero otherwise. |ctx| may be NULL. OPENSSL_EXPORT int EC_POINT_set_compressed_coordinates_GFp( const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, int y_bit, BN_CTX *ctx); @@ -268,23 +268,23 @@ OPENSSL_EXPORT int EC_POINT_set_compressed_coordinates_GFp( // Group operations. // EC_POINT_add sets |r| equal to |a| plus |b|. It returns one on success and -// zero otherwise. If |ctx| is not NULL, it may be used. +// zero otherwise. |ctx| is ignored and may be NULL. OPENSSL_EXPORT int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx); // EC_POINT_dbl sets |r| equal to |a| plus |a|. It returns one on success and -// zero otherwise. If |ctx| is not NULL, it may be used. +// zero otherwise. |ctx| is ignored and may be NULL. OPENSSL_EXPORT int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx); // EC_POINT_invert sets |a| equal to minus |a|. It returns one on success and -// zero otherwise. If |ctx| is not NULL, it may be used. +// zero otherwise. |ctx| is ignored and may be NULL. OPENSSL_EXPORT int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx); // EC_POINT_mul sets r = generator*n + q*m. It returns one on success and zero -// otherwise. If |ctx| is not NULL, it may be used. +// otherwise. |ctx| may be NULL. OPENSSL_EXPORT int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx); @@ -368,8 +368,8 @@ OPENSSL_EXPORT int EC_GROUP_set_generator(EC_GROUP *group, const BIGNUM *cofactor); // EC_GROUP_get_order sets |*order| to the order of |group|, if it's not -// NULL. It returns one on success and zero otherwise. |ctx| is ignored. Use -// |EC_GROUP_get0_order| instead. +// NULL. It returns one on success and zero otherwise. |ctx| is ignored and may +// be NULL. Use |EC_GROUP_get0_order| instead. OPENSSL_EXPORT int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx); diff --git a/naiveproxy/src/third_party/boringssl/src/include/openssl/ec_key.h b/naiveproxy/src/third_party/boringssl/src/include/openssl/ec_key.h index 1219cf1ee7..1133a37c90 100644 --- a/naiveproxy/src/third_party/boringssl/src/include/openssl/ec_key.h +++ b/naiveproxy/src/third_party/boringssl/src/include/openssl/ec_key.h @@ -130,12 +130,12 @@ OPENSSL_EXPORT int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, // EC_KEY_oct2key decodes |len| bytes from |in| as an EC public key in X9.62 // form. |key| must already have a group configured. On success, it sets the // public key in |key| to the result and returns one. Otherwise, it returns -// zero. +// zero. |ctx| may be NULL. OPENSSL_EXPORT int EC_KEY_oct2key(EC_KEY *key, const uint8_t *in, size_t len, BN_CTX *ctx); // EC_KEY_key2buf behaves like |EC_POINT_point2buf|, except it encodes the -// public key in |key|. +// public key in |key|. |ctx| is ignored and may be NULL. OPENSSL_EXPORT size_t EC_KEY_key2buf(const EC_KEY *key, point_conversion_form_t form, uint8_t **out_buf, BN_CTX *ctx); diff --git a/naiveproxy/src/third_party/boringssl/src/include/openssl/evp.h b/naiveproxy/src/third_party/boringssl/src/include/openssl/evp.h index 87e3ad25e8..988e1dac52 100644 --- a/naiveproxy/src/third_party/boringssl/src/include/openssl/evp.h +++ b/naiveproxy/src/third_party/boringssl/src/include/openssl/evp.h @@ -692,12 +692,10 @@ OPENSSL_EXPORT int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, // recovered from the signature when verifying. Otherwise the value gives the // size of the salt in bytes. // -// If unsure, use |RSA_PSS_SALTLEN_DIGEST|. +// If unsure, use |RSA_PSS_SALTLEN_DIGEST|, which is the default. Note this +// differs from OpenSSL, which defaults to |RSA_PSS_SALTLEN_AUTO|. // // Returns one on success or zero on error. -// -// TODO(davidben): The default is currently |RSA_PSS_SALTLEN_AUTO|. Switch it to -// |RSA_PSS_SALTLEN_DIGEST|. OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int salt_len); @@ -770,6 +768,14 @@ OPENSSL_EXPORT int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, // EC specific control functions. +// EVP_PKEY_get_ec_curve_nid returns |pkey|'s curve as a NID constant, such as +// |NID_X9_62_prime256v1|, or |NID_undef| if |pkey| is not an EC key. +OPENSSL_EXPORT int EVP_PKEY_get_ec_curve_nid(const EVP_PKEY *pkey); + +// EVP_PKEY_get_ec_point_conv_form returns |pkey|'s point conversion form as a +// |POINT_CONVERSION_*| constant, or zero if |pkey| is not an EC key. +OPENSSL_EXPORT int EVP_PKEY_get_ec_point_conv_form(const EVP_PKEY *pkey); + // EVP_PKEY_CTX_set_ec_paramgen_curve_nid sets the curve used for // |EVP_PKEY_keygen| or |EVP_PKEY_paramgen| operations to |nid|. It returns one // on success and zero on error. diff --git a/naiveproxy/src/third_party/boringssl/src/include/openssl/hpke.h b/naiveproxy/src/third_party/boringssl/src/include/openssl/hpke.h index ca107315e7..7ccc6c655d 100644 --- a/naiveproxy/src/third_party/boringssl/src/include/openssl/hpke.h +++ b/naiveproxy/src/third_party/boringssl/src/include/openssl/hpke.h @@ -16,7 +16,7 @@ #define OPENSSL_HEADER_HPKE_H #include -#include // IWYU pragma: export +#include // IWYU pragma: export #include #include @@ -42,12 +42,14 @@ extern "C" { // The following constants are KEM identifiers. #define EVP_HPKE_DHKEM_P256_HKDF_SHA256 0x0010 #define EVP_HPKE_DHKEM_X25519_HKDF_SHA256 0x0020 +#define EVP_HPKE_XWING 0x647a // The following functions are KEM algorithms which may be used with HPKE. Note // that, while some HPKE KEMs use KDFs internally, this is separate from the // |EVP_HPKE_KDF| selection. OPENSSL_EXPORT const EVP_HPKE_KEM *EVP_hpke_x25519_hkdf_sha256(void); OPENSSL_EXPORT const EVP_HPKE_KEM *EVP_hpke_p256_hkdf_sha256(void); +OPENSSL_EXPORT const EVP_HPKE_KEM *EVP_hpke_xwing(void); // EVP_HPKE_KEM_id returns the HPKE KEM identifier for |kem|, which // will be one of the |EVP_HPKE_KEM_*| constants. @@ -55,7 +57,7 @@ OPENSSL_EXPORT uint16_t EVP_HPKE_KEM_id(const EVP_HPKE_KEM *kem); // EVP_HPKE_MAX_PUBLIC_KEY_LENGTH is the maximum length of an encoded public key // for all KEMs currently supported by this library. -#define EVP_HPKE_MAX_PUBLIC_KEY_LENGTH 65 +#define EVP_HPKE_MAX_PUBLIC_KEY_LENGTH 1216 // EVP_HPKE_KEM_public_key_len returns the length of a public key for |kem|. // This value will be at most |EVP_HPKE_MAX_PUBLIC_KEY_LENGTH|. @@ -71,7 +73,7 @@ OPENSSL_EXPORT size_t EVP_HPKE_KEM_private_key_len(const EVP_HPKE_KEM *kem); // EVP_HPKE_MAX_ENC_LENGTH is the maximum length of "enc", the encapsulated // shared secret, for all KEMs currently supported by this library. -#define EVP_HPKE_MAX_ENC_LENGTH 65 +#define EVP_HPKE_MAX_ENC_LENGTH 1120 // EVP_HPKE_KEM_enc_len returns the length of the "enc", the encapsulated shared // secret, for |kem|. This value will be at most |EVP_HPKE_MAX_ENC_LENGTH|. diff --git a/naiveproxy/src/third_party/boringssl/src/include/openssl/mldsa.h b/naiveproxy/src/third_party/boringssl/src/include/openssl/mldsa.h index 8bc829bc1c..63dc91f325 100644 --- a/naiveproxy/src/third_party/boringssl/src/include/openssl/mldsa.h +++ b/naiveproxy/src/third_party/boringssl/src/include/openssl/mldsa.h @@ -318,6 +318,146 @@ OPENSSL_EXPORT int MLDSA87_parse_public_key( struct MLDSA87_public_key *public_key, CBS *in); +// ML-DSA-44. + +// MLDSA44_private_key contains an ML-DSA-44 private key. The contents of this +// object should never leave the address space since the format is unstable. +struct MLDSA44_private_key { + union { + uint8_t bytes[32 + 32 + 64 + 256 * 4 * (4 + 4 + 4)]; + uint32_t alignment; + } opaque; +}; + +// MLDSA44_public_key contains an ML-DSA-44 public key. The contents of this +// object should never leave the address space since the format is unstable. +struct MLDSA44_public_key { + union { + uint8_t bytes[32 + 64 + 256 * 4 * 4]; + uint32_t alignment; + } opaque; +}; + +// MLDSA44_prehash contains a pre-hash context for ML-DSA-44. The contents of +// this object should never leave the address space since the format is +// unstable. +struct MLDSA44_prehash { + union { + uint8_t bytes[200 + 4 + 4 + 4 * sizeof(size_t)]; + uint64_t alignment; + } opaque; +}; + +// MLDSA44_PRIVATE_KEY_BYTES is the number of bytes in an encoded ML-DSA-44 +// private key. +#define MLDSA44_PRIVATE_KEY_BYTES 2560 + +// MLDSA44_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-DSA-44 +// public key. +#define MLDSA44_PUBLIC_KEY_BYTES 1312 + +// MLDSA44_SIGNATURE_BYTES is the number of bytes in an encoded ML-DSA-44 +// signature. +#define MLDSA44_SIGNATURE_BYTES 2420 + +// MLDSA44_generate_key generates a random public/private key pair, writes the +// encoded public key to |out_encoded_public_key|, writes the seed to +// |out_seed|, and sets |out_private_key| to the private key. Returns 1 on +// success and 0 on allocation failure. +OPENSSL_EXPORT int MLDSA44_generate_key( + uint8_t out_encoded_public_key[MLDSA44_PUBLIC_KEY_BYTES], + uint8_t out_seed[MLDSA_SEED_BYTES], + struct MLDSA44_private_key *out_private_key); + +// MLDSA44_private_key_from_seed regenerates a private key from a seed value +// that was generated by |MLDSA44_generate_key|. Returns 1 on success and 0 on +// allocation failure or if |seed_len| is incorrect. +OPENSSL_EXPORT int MLDSA44_private_key_from_seed( + struct MLDSA44_private_key *out_private_key, const uint8_t *seed, + size_t seed_len); + +// MLDSA44_public_from_private sets |*out_public_key| to the public key that +// corresponds to |private_key|. Returns 1 on success and 0 on failure. +OPENSSL_EXPORT int MLDSA44_public_from_private( + struct MLDSA44_public_key *out_public_key, + const struct MLDSA44_private_key *private_key); + +// MLDSA44_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|. The |context| +// argument is also signed over and can be used to include implicit contextual +// information that isn't included in |msg|. The same value of |context| must be +// presented to |MLDSA44_verify| in order for the generated signature to be +// considered valid. |context| and |context_len| may be |NULL| and 0 to use an +// empty context (this is common). Returns 1 on success and 0 on failure. +OPENSSL_EXPORT int MLDSA44_sign( + uint8_t out_encoded_signature[MLDSA44_SIGNATURE_BYTES], + const struct MLDSA44_private_key *private_key, const uint8_t *msg, + size_t msg_len, const uint8_t *context, size_t context_len); + +// MLDSA44_verify verifies that |signature| constitutes a valid +// signature for the message |msg| of length |msg_len| using |public_key|. The +// value of |context| must equal the value that was passed to |MLDSA44_sign| +// when the signature was generated. Returns 1 on success or 0 on error. +OPENSSL_EXPORT int MLDSA44_verify(const struct MLDSA44_public_key *public_key, + const uint8_t *signature, + size_t signature_len, const uint8_t *msg, + size_t msg_len, const uint8_t *context, + size_t context_len); + +// MLDSA44_prehash_init initializes a pre-hashing state using |public_key|. The +// |context| argument can be used to include implicit contextual information +// that isn't included in the message. The same value of |context| must be +// presented to |MLDSA44_verify| in order for the generated signature to be +// considered valid. |context| and |context_len| may be |NULL| and 0 to use an +// empty context (this is common). Returns 1 on success and 0 on failure (if the +// context is too long). +OPENSSL_EXPORT int MLDSA44_prehash_init( + struct MLDSA44_prehash *out_state, + const struct MLDSA44_public_key *public_key, const uint8_t *context, + size_t context_len); + +// MLDSA44_prehash_update incorporates the given |msg| of length |msg_len| into +// the pre-hashing state. This can be called multiple times on successive chunks +// of the message. This should be called after |MLDSA44_prehash_init| and before +// |MLDSA44_prehash_finalize|. +OPENSSL_EXPORT void MLDSA44_prehash_update(struct MLDSA44_prehash *inout_state, + const uint8_t *msg, size_t msg_len); + +// MLDSA44_prehash_finalize extracts a pre-hashed message representative from +// the given pre-hashing state. This should be called after +// |MLDSA44_prehash_init| and |MLDSA44_prehash_update|. The resulting +// |out_msg_rep| should then be passed to |MLDSA44_sign_message_representative| +// to obtain a signature. +OPENSSL_EXPORT void MLDSA44_prehash_finalize( + uint8_t out_msg_rep[MLDSA_MU_BYTES], struct MLDSA44_prehash *inout_state); + +// MLDSA44_sign_message_representative generates a signature for the pre-hashed +// message |msg_rep| using |private_key| (following the randomized algorithm), +// and writes the encoded signature to |out_encoded_signature|. The |msg_rep| +// should be obtained via calls to |MLDSA44_prehash_init|, +// |MLDSA44_prehash_update| and |MLDSA44_prehash_finalize| using the public key +// from the same key pair, otherwise the signature will not verify. Returns 1 on +// success and 0 on failure. +OPENSSL_EXPORT int MLDSA44_sign_message_representative( + uint8_t out_encoded_signature[MLDSA44_SIGNATURE_BYTES], + const struct MLDSA44_private_key *private_key, + const uint8_t msg_rep[MLDSA_MU_BYTES]); + +// MLDSA44_marshal_public_key serializes |public_key| to |out| in the standard +// format for ML-DSA-44 public keys. It returns 1 on success or 0 on +// allocation error. +OPENSSL_EXPORT int MLDSA44_marshal_public_key( + CBB *out, const struct MLDSA44_public_key *public_key); + +// MLDSA44_parse_public_key parses a public key, in the format generated by +// |MLDSA44_marshal_public_key|, from |in| and writes the result to +// |out_public_key|. It returns 1 on success or 0 on parse error or if +// there are trailing bytes in |in|. +OPENSSL_EXPORT int MLDSA44_parse_public_key( + struct MLDSA44_public_key *public_key, CBS *in); + + #if defined(__cplusplus) } // extern C #endif diff --git a/naiveproxy/src/third_party/boringssl/src/include/openssl/rsa.h b/naiveproxy/src/third_party/boringssl/src/include/openssl/rsa.h index c80aea8545..d948b193eb 100644 --- a/naiveproxy/src/third_party/boringssl/src/include/openssl/rsa.h +++ b/naiveproxy/src/third_party/boringssl/src/include/openssl/rsa.h @@ -69,9 +69,7 @@ OPENSSL_EXPORT int RSA_up_ref(RSA *rsa); // Properties. // OPENSSL_RSA_MAX_MODULUS_BITS is the maximum supported RSA modulus, in bits. -// -// TODO(crbug.com/402677800): Reduce this to 8192. -#define OPENSSL_RSA_MAX_MODULUS_BITS 16384 +#define OPENSSL_RSA_MAX_MODULUS_BITS 8192 // RSA_bits returns the size of |rsa|, in bits. OPENSSL_EXPORT unsigned RSA_bits(const RSA *rsa); @@ -225,7 +223,11 @@ OPENSSL_EXPORT int RSA_generate_key_fips(RSA *rsa, int bits, BN_GENCB *cb); // It returns 1 on success or zero on error. // // The |padding| argument must be one of the |RSA_*_PADDING| values. If in -// doubt, use |RSA_PKCS1_OAEP_PADDING| for new protocols. +// doubt, use |RSA_PKCS1_OAEP_PADDING| for new protocols. When |padding| is +// |RSA_PKCS1_OAEP_PADDING|, this function has no way to set the OAEP or MGF-1 +// digest, so it is always SHA-1. For other OAEP parameters, wrap |rsa| in an +// |EVP_PKEY| and use |EVP_PKEY_encrypt| with |EVP_PKEY_CTX_set_rsa_padding| and +// related functions. OPENSSL_EXPORT int RSA_encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, const uint8_t *in, size_t in_len, int padding); @@ -237,7 +239,11 @@ OPENSSL_EXPORT int RSA_encrypt(RSA *rsa, size_t *out_len, uint8_t *out, // It returns 1 on success or zero on error. // // The |padding| argument must be one of the |RSA_*_PADDING| values. If in -// doubt, use |RSA_PKCS1_OAEP_PADDING| for new protocols. +// doubt, use |RSA_PKCS1_OAEP_PADDING| for new protocols. When |padding| is +// |RSA_PKCS1_OAEP_PADDING|, this function has no way to set the OAEP or MGF-1 +// digest, so it is always SHA-1. For other OAEP parameters, wrap |rsa| in an +// |EVP_PKEY| and use |EVP_PKEY_decrypt| with |EVP_PKEY_CTX_set_rsa_padding| and +// related functions. // // WARNING: Passing |RSA_PKCS1_PADDING| into this function is deprecated and // insecure. RSAES-PKCS1-v1_5 is vulnerable to a chosen-ciphertext attack. @@ -259,6 +265,11 @@ OPENSSL_EXPORT int RSA_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, // -1 on error. The |padding| argument must be one of the |RSA_*_PADDING| // values. If in doubt, use |RSA_PKCS1_OAEP_PADDING| for new protocols. // +// When |padding| is |RSA_PKCS1_OAEP_PADDING|, this function has no way to set +// the OAEP or MGF-1 digest, so it is always SHA-1. For other OAEP parameters, +// wrap |rsa| in an |EVP_PKEY| and use |EVP_PKEY_encrypt| with +// |EVP_PKEY_CTX_set_rsa_padding| and related functions. +// // WARNING: this function is dangerous because it breaks the usual return value // convention. Use |RSA_encrypt| instead. OPENSSL_EXPORT int RSA_public_encrypt(size_t flen, const uint8_t *from, @@ -272,6 +283,11 @@ OPENSSL_EXPORT int RSA_public_encrypt(size_t flen, const uint8_t *from, // |RSA_PKCS1_PADDING| into this function is deprecated and insecure. See // |RSA_decrypt|. // +// When |padding| is |RSA_PKCS1_OAEP_PADDING|, this function has no way to set +// the OAEP or MGF-1 digest, so it is always SHA-1. For other OAEP parameters, +// wrap |rsa| in an |EVP_PKEY| and use |EVP_PKEY_decrypt| with +// |EVP_PKEY_CTX_set_rsa_padding| and related functions. +// // WARNING: this function is dangerous because it breaks the usual return value // convention. Use |RSA_decrypt| instead. OPENSSL_EXPORT int RSA_private_decrypt(size_t flen, const uint8_t *from, @@ -305,7 +321,9 @@ OPENSSL_EXPORT int RSA_sign(int hash_nid, const uint8_t *digest, // length. This is recommended. #define RSA_PSS_SALTLEN_DIGEST (-1) // RSA_PSS_SALTLEN_AUTO indicates a maximum possible PSS salt length when -// signing, and automatically detecting the salt length when verifying. +// signing, and automatically detecting the salt length when verifying. This is +// not recommended. Neither the signing nor verifying behaviors are compliant +// with FIPS 186-5. #define RSA_PSS_SALTLEN_AUTO (-2) // RSA_sign_pss_mgf1 signs |digest_len| bytes from |digest| with the public key diff --git a/naiveproxy/src/third_party/boringssl/src/include/openssl/sha.h b/naiveproxy/src/third_party/boringssl/src/include/openssl/sha.h index 27435e50c5..4ac28ebf75 100644 --- a/naiveproxy/src/third_party/boringssl/src/include/openssl/sha.h +++ b/naiveproxy/src/third_party/boringssl/src/include/openssl/sha.h @@ -15,8 +15,13 @@ #ifndef OPENSSL_HEADER_SHA_H #define OPENSSL_HEADER_SHA_H -#include // IWYU pragma: export -#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export + +// `sha.h` historically included SHA-1 and SHA-2 hash functions. So, for +// backward compatibility `sha2.h` is included here. New uses of this header +// should include sha2.h unless SHA-1 family functions are required. +#include // IWYU pragma: export #if defined(__cplusplus) extern "C" { @@ -74,160 +79,6 @@ OPENSSL_EXPORT void CRYPTO_fips_186_2_prf( uint8_t *out, size_t out_len, const uint8_t xkey[SHA_DIGEST_LENGTH]); -// SHA-224. - -// SHA224_CBLOCK is the block size of SHA-224. -#define SHA224_CBLOCK 64 - -// SHA224_DIGEST_LENGTH is the length of a SHA-224 digest. -#define SHA224_DIGEST_LENGTH 28 - -// SHA224_Init initialises |sha| and returns 1. -OPENSSL_EXPORT int SHA224_Init(SHA256_CTX *sha); - -// SHA224_Update adds |len| bytes from |data| to |sha| and returns 1. -OPENSSL_EXPORT int SHA224_Update(SHA256_CTX *sha, const void *data, size_t len); - -// SHA224_Final adds the final padding to |sha| and writes the resulting digest -// to |out|, which must have at least |SHA224_DIGEST_LENGTH| bytes of space. It -// returns 1. -OPENSSL_EXPORT int SHA224_Final(uint8_t out[SHA224_DIGEST_LENGTH], - SHA256_CTX *sha); - -// SHA224 writes the digest of |len| bytes from |data| to |out| and returns -// |out|. There must be at least |SHA224_DIGEST_LENGTH| bytes of space in -// |out|. -OPENSSL_EXPORT uint8_t *SHA224(const uint8_t *data, size_t len, - uint8_t out[SHA224_DIGEST_LENGTH]); - - -// SHA-256. - -// SHA256_CBLOCK is the block size of SHA-256. -#define SHA256_CBLOCK 64 - -// SHA256_DIGEST_LENGTH is the length of a SHA-256 digest. -#define SHA256_DIGEST_LENGTH 32 - -// SHA256_Init initialises |sha| and returns 1. -OPENSSL_EXPORT int SHA256_Init(SHA256_CTX *sha); - -// SHA256_Update adds |len| bytes from |data| to |sha| and returns 1. -OPENSSL_EXPORT int SHA256_Update(SHA256_CTX *sha, const void *data, size_t len); - -// SHA256_Final adds the final padding to |sha| and writes the resulting digest -// to |out|, which must have at least |SHA256_DIGEST_LENGTH| bytes of space. It -// returns one on success and zero on programmer error. -OPENSSL_EXPORT int SHA256_Final(uint8_t out[SHA256_DIGEST_LENGTH], - SHA256_CTX *sha); - -// SHA256 writes the digest of |len| bytes from |data| to |out| and returns -// |out|. There must be at least |SHA256_DIGEST_LENGTH| bytes of space in -// |out|. -OPENSSL_EXPORT uint8_t *SHA256(const uint8_t *data, size_t len, - uint8_t out[SHA256_DIGEST_LENGTH]); - -// SHA256_Transform is a low-level function that performs a single, SHA-256 -// block transformation using the state from |sha| and |SHA256_CBLOCK| bytes -// from |block|. -OPENSSL_EXPORT void SHA256_Transform(SHA256_CTX *sha, - const uint8_t block[SHA256_CBLOCK]); - -// SHA256_TransformBlocks is a low-level function that takes |num_blocks| * -// |SHA256_CBLOCK| bytes of data and performs SHA-256 transforms on it to update -// |state|. You should not use this function unless you are implementing a -// derivative of SHA-256. -OPENSSL_EXPORT void SHA256_TransformBlocks(uint32_t state[8], - const uint8_t *data, - size_t num_blocks); - - -// SHA-384. - -// SHA384_CBLOCK is the block size of SHA-384. -#define SHA384_CBLOCK 128 - -// SHA384_DIGEST_LENGTH is the length of a SHA-384 digest. -#define SHA384_DIGEST_LENGTH 48 - -// SHA384_Init initialises |sha| and returns 1. -OPENSSL_EXPORT int SHA384_Init(SHA512_CTX *sha); - -// SHA384_Update adds |len| bytes from |data| to |sha| and returns 1. -OPENSSL_EXPORT int SHA384_Update(SHA512_CTX *sha, const void *data, size_t len); - -// SHA384_Final adds the final padding to |sha| and writes the resulting digest -// to |out|, which must have at least |SHA384_DIGEST_LENGTH| bytes of space. It -// returns one on success and zero on programmer error. -OPENSSL_EXPORT int SHA384_Final(uint8_t out[SHA384_DIGEST_LENGTH], - SHA512_CTX *sha); - -// SHA384 writes the digest of |len| bytes from |data| to |out| and returns -// |out|. There must be at least |SHA384_DIGEST_LENGTH| bytes of space in -// |out|. -OPENSSL_EXPORT uint8_t *SHA384(const uint8_t *data, size_t len, - uint8_t out[SHA384_DIGEST_LENGTH]); - - -// SHA-512. - -// SHA512_CBLOCK is the block size of SHA-512. -#define SHA512_CBLOCK 128 - -// SHA512_DIGEST_LENGTH is the length of a SHA-512 digest. -#define SHA512_DIGEST_LENGTH 64 - -// SHA512_Init initialises |sha| and returns 1. -OPENSSL_EXPORT int SHA512_Init(SHA512_CTX *sha); - -// SHA512_Update adds |len| bytes from |data| to |sha| and returns 1. -OPENSSL_EXPORT int SHA512_Update(SHA512_CTX *sha, const void *data, size_t len); - -// SHA512_Final adds the final padding to |sha| and writes the resulting digest -// to |out|, which must have at least |SHA512_DIGEST_LENGTH| bytes of space. It -// returns one on success and zero on programmer error. -OPENSSL_EXPORT int SHA512_Final(uint8_t out[SHA512_DIGEST_LENGTH], - SHA512_CTX *sha); - -// SHA512 writes the digest of |len| bytes from |data| to |out| and returns -// |out|. There must be at least |SHA512_DIGEST_LENGTH| bytes of space in -// |out|. -OPENSSL_EXPORT uint8_t *SHA512(const uint8_t *data, size_t len, - uint8_t out[SHA512_DIGEST_LENGTH]); - -// SHA512_Transform is a low-level function that performs a single, SHA-512 -// block transformation using the state from |sha| and |SHA512_CBLOCK| bytes -// from |block|. -OPENSSL_EXPORT void SHA512_Transform(SHA512_CTX *sha, - const uint8_t block[SHA512_CBLOCK]); - - -// SHA-512-256 -// -// See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf section 5.3.6 - -#define SHA512_256_DIGEST_LENGTH 32 - -// SHA512_256_Init initialises |sha| and returns 1. -OPENSSL_EXPORT int SHA512_256_Init(SHA512_CTX *sha); - -// SHA512_256_Update adds |len| bytes from |data| to |sha| and returns 1. -OPENSSL_EXPORT int SHA512_256_Update(SHA512_CTX *sha, const void *data, - size_t len); - -// SHA512_256_Final adds the final padding to |sha| and writes the resulting -// digest to |out|, which must have at least |SHA512_256_DIGEST_LENGTH| bytes of -// space. It returns one on success and zero on programmer error. -OPENSSL_EXPORT int SHA512_256_Final(uint8_t out[SHA512_256_DIGEST_LENGTH], - SHA512_CTX *sha); - -// SHA512_256 writes the digest of |len| bytes from |data| to |out| and returns -// |out|. There must be at least |SHA512_256_DIGEST_LENGTH| bytes of space in -// |out|. -OPENSSL_EXPORT uint8_t *SHA512_256(const uint8_t *data, size_t len, - uint8_t out[SHA512_256_DIGEST_LENGTH]); - - #if defined(__cplusplus) } // extern C #endif diff --git a/naiveproxy/src/third_party/boringssl/src/include/openssl/sha2.h b/naiveproxy/src/third_party/boringssl/src/include/openssl/sha2.h new file mode 100644 index 0000000000..286c41654e --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/include/openssl/sha2.h @@ -0,0 +1,184 @@ +// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. +// +// 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 OPENSSL_HEADER_SHA2_H +#define OPENSSL_HEADER_SHA2_H + +#include // IWYU pragma: export +#include // IWYU pragma: export + +#if defined(__cplusplus) +extern "C" { +#endif + + +// SHA-224. + +// SHA224_CBLOCK is the block size of SHA-224. +#define SHA224_CBLOCK 64 + +// SHA224_DIGEST_LENGTH is the length of a SHA-224 digest. +#define SHA224_DIGEST_LENGTH 28 + +// SHA224_Init initialises |sha| and returns 1. +OPENSSL_EXPORT int SHA224_Init(SHA256_CTX *sha); + +// SHA224_Update adds |len| bytes from |data| to |sha| and returns 1. +OPENSSL_EXPORT int SHA224_Update(SHA256_CTX *sha, const void *data, size_t len); + +// SHA224_Final adds the final padding to |sha| and writes the resulting digest +// to |out|, which must have at least |SHA224_DIGEST_LENGTH| bytes of space. It +// returns 1. +OPENSSL_EXPORT int SHA224_Final(uint8_t out[SHA224_DIGEST_LENGTH], + SHA256_CTX *sha); + +// SHA224 writes the digest of |len| bytes from |data| to |out| and returns +// |out|. There must be at least |SHA224_DIGEST_LENGTH| bytes of space in +// |out|. +OPENSSL_EXPORT uint8_t *SHA224(const uint8_t *data, size_t len, + uint8_t out[SHA224_DIGEST_LENGTH]); + + +// SHA-256. + +// SHA256_CBLOCK is the block size of SHA-256. +#define SHA256_CBLOCK 64 + +// SHA256_DIGEST_LENGTH is the length of a SHA-256 digest. +#define SHA256_DIGEST_LENGTH 32 + +// SHA256_Init initialises |sha| and returns 1. +OPENSSL_EXPORT int SHA256_Init(SHA256_CTX *sha); + +// SHA256_Update adds |len| bytes from |data| to |sha| and returns 1. +OPENSSL_EXPORT int SHA256_Update(SHA256_CTX *sha, const void *data, size_t len); + +// SHA256_Final adds the final padding to |sha| and writes the resulting digest +// to |out|, which must have at least |SHA256_DIGEST_LENGTH| bytes of space. It +// returns one on success and zero on programmer error. +OPENSSL_EXPORT int SHA256_Final(uint8_t out[SHA256_DIGEST_LENGTH], + SHA256_CTX *sha); + +// SHA256 writes the digest of |len| bytes from |data| to |out| and returns +// |out|. There must be at least |SHA256_DIGEST_LENGTH| bytes of space in +// |out|. +OPENSSL_EXPORT uint8_t *SHA256(const uint8_t *data, size_t len, + uint8_t out[SHA256_DIGEST_LENGTH]); + +// SHA256_Transform is a low-level function that performs a single, SHA-256 +// block transformation using the state from |sha| and |SHA256_CBLOCK| bytes +// from |block|. +OPENSSL_EXPORT void SHA256_Transform(SHA256_CTX *sha, + const uint8_t block[SHA256_CBLOCK]); + +// SHA256_TransformBlocks is a low-level function that takes |num_blocks| * +// |SHA256_CBLOCK| bytes of data and performs SHA-256 transforms on it to update +// |state|. You should not use this function unless you are implementing a +// derivative of SHA-256. +OPENSSL_EXPORT void SHA256_TransformBlocks(uint32_t state[8], + const uint8_t *data, + size_t num_blocks); + + +// SHA-384. + +// SHA384_CBLOCK is the block size of SHA-384. +#define SHA384_CBLOCK 128 + +// SHA384_DIGEST_LENGTH is the length of a SHA-384 digest. +#define SHA384_DIGEST_LENGTH 48 + +// SHA384_Init initialises |sha| and returns 1. +OPENSSL_EXPORT int SHA384_Init(SHA512_CTX *sha); + +// SHA384_Update adds |len| bytes from |data| to |sha| and returns 1. +OPENSSL_EXPORT int SHA384_Update(SHA512_CTX *sha, const void *data, size_t len); + +// SHA384_Final adds the final padding to |sha| and writes the resulting digest +// to |out|, which must have at least |SHA384_DIGEST_LENGTH| bytes of space. It +// returns one on success and zero on programmer error. +OPENSSL_EXPORT int SHA384_Final(uint8_t out[SHA384_DIGEST_LENGTH], + SHA512_CTX *sha); + +// SHA384 writes the digest of |len| bytes from |data| to |out| and returns +// |out|. There must be at least |SHA384_DIGEST_LENGTH| bytes of space in +// |out|. +OPENSSL_EXPORT uint8_t *SHA384(const uint8_t *data, size_t len, + uint8_t out[SHA384_DIGEST_LENGTH]); + + +// SHA-512. + +// SHA512_CBLOCK is the block size of SHA-512. +#define SHA512_CBLOCK 128 + +// SHA512_DIGEST_LENGTH is the length of a SHA-512 digest. +#define SHA512_DIGEST_LENGTH 64 + +// SHA512_Init initialises |sha| and returns 1. +OPENSSL_EXPORT int SHA512_Init(SHA512_CTX *sha); + +// SHA512_Update adds |len| bytes from |data| to |sha| and returns 1. +OPENSSL_EXPORT int SHA512_Update(SHA512_CTX *sha, const void *data, size_t len); + +// SHA512_Final adds the final padding to |sha| and writes the resulting digest +// to |out|, which must have at least |SHA512_DIGEST_LENGTH| bytes of space. It +// returns one on success and zero on programmer error. +OPENSSL_EXPORT int SHA512_Final(uint8_t out[SHA512_DIGEST_LENGTH], + SHA512_CTX *sha); + +// SHA512 writes the digest of |len| bytes from |data| to |out| and returns +// |out|. There must be at least |SHA512_DIGEST_LENGTH| bytes of space in +// |out|. +OPENSSL_EXPORT uint8_t *SHA512(const uint8_t *data, size_t len, + uint8_t out[SHA512_DIGEST_LENGTH]); + +// SHA512_Transform is a low-level function that performs a single, SHA-512 +// block transformation using the state from |sha| and |SHA512_CBLOCK| bytes +// from |block|. +OPENSSL_EXPORT void SHA512_Transform(SHA512_CTX *sha, + const uint8_t block[SHA512_CBLOCK]); + + +// SHA-512-256 +// +// See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf section 5.3.6 + +#define SHA512_256_DIGEST_LENGTH 32 + +// SHA512_256_Init initialises |sha| and returns 1. +OPENSSL_EXPORT int SHA512_256_Init(SHA512_CTX *sha); + +// SHA512_256_Update adds |len| bytes from |data| to |sha| and returns 1. +OPENSSL_EXPORT int SHA512_256_Update(SHA512_CTX *sha, const void *data, + size_t len); + +// SHA512_256_Final adds the final padding to |sha| and writes the resulting +// digest to |out|, which must have at least |SHA512_256_DIGEST_LENGTH| bytes of +// space. It returns one on success and zero on programmer error. +OPENSSL_EXPORT int SHA512_256_Final(uint8_t out[SHA512_256_DIGEST_LENGTH], + SHA512_CTX *sha); + +// SHA512_256 writes the digest of |len| bytes from |data| to |out| and returns +// |out|. There must be at least |SHA512_256_DIGEST_LENGTH| bytes of space in +// |out|. +OPENSSL_EXPORT uint8_t *SHA512_256(const uint8_t *data, size_t len, + uint8_t out[SHA512_256_DIGEST_LENGTH]); + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_SHA2_H 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 982d0d8b96..6d72829068 100644 --- a/naiveproxy/src/third_party/boringssl/src/include/openssl/ssl.h +++ b/naiveproxy/src/third_party/boringssl/src/include/openssl/ssl.h @@ -4936,7 +4936,7 @@ enum ssl_select_cert_result_t BORINGSSL_ENUM_INT { // ClientHelloOuter instead. From there, the handshake will proceed // without retry_configs, to signal to the client to disable ECH. // - // This value may only be returned when |SSL_ech_accepted| returnes one. It + // This value may only be returned when |SSL_ech_accepted| returns one. It // may be useful if the ClientHelloInner indicated a service which does not // support ECH, e.g. if it is a TLS-1.2 only service. ssl_select_cert_disable_ech = -2, 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 e1e3a9cb91..0cd8716d43 100644 --- a/naiveproxy/src/third_party/boringssl/src/include/openssl/x509.h +++ b/naiveproxy/src/third_party/boringssl/src/include/openssl/x509.h @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include // IWYU pragma: export diff --git a/naiveproxy/src/third_party/boringssl/src/infra/config/PRESUBMIT.py b/naiveproxy/src/third_party/boringssl/src/infra/config/PRESUBMIT.py new file mode 100644 index 0000000000..6d138da3e7 --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/infra/config/PRESUBMIT.py @@ -0,0 +1,24 @@ +# Copyright 2025 The BoringSSL 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. + +"""Enforces consistency in lucicfg definitions for BoringSSL's CI and CQ. + +Run by the presubmit API in depot_tools, e.g. by running `git cl presubmit`. +""" + +PRESUBMIT_VERSION = '2.0.0' + +def CheckLucicfgGenOutputMain(input_api, output_api): + return input_api.RunTests(input_api.canned_checks.CheckLucicfgGenOutput( + input_api, output_api, 'main.star')) diff --git a/naiveproxy/src/third_party/boringssl/src/infra/config/generated/commit-queue.cfg b/naiveproxy/src/third_party/boringssl/src/infra/config/generated/commit-queue.cfg index fac22b67a6..1fc09f672c 100644 --- a/naiveproxy/src/third_party/boringssl/src/infra/config/generated/commit-queue.cfg +++ b/naiveproxy/src/third_party/boringssl/src/infra/config/generated/commit-queue.cfg @@ -24,6 +24,7 @@ config_groups { gerrit_cq_ability { committer_list: "project-boringssl-committers" dry_run_access_list: "project-boringssl-tryjob-access" + new_patchset_run_access_list: "project-boringssl-tryjob-access" } tryjob { builders { @@ -245,6 +246,37 @@ config_groups { builders { name: "boringssl/try/win_arm64_msvc_compile" } + builders { + name: "chromium/try/tricium-clang-tidy" + disable_reuse: true + experiment_percentage: 100 + location_filters { + gerrit_host_regexp: ".*" + gerrit_project_regexp: ".*" + gerrit_ref_regexp: ".*" + path_regexp: ".+\\.h" + } + location_filters { + gerrit_host_regexp: ".*" + gerrit_project_regexp: ".*" + gerrit_ref_regexp: ".*" + path_regexp: ".+\\.c" + } + location_filters { + gerrit_host_regexp: ".*" + gerrit_project_regexp: ".*" + gerrit_ref_regexp: ".*" + path_regexp: ".+\\.cc" + } + location_filters { + gerrit_host_regexp: ".*" + gerrit_project_regexp: ".*" + gerrit_ref_regexp: ".*" + path_regexp: ".+\\.cpp" + } + owner_whitelist_group: "project-boringssl-tryjob-access" + mode_allowlist: "NEW_PATCHSET_RUN" + } retry_config { single_quota: 1 global_quota: 2 diff --git a/naiveproxy/src/third_party/boringssl/src/infra/config/generated/cr-buildbucket.cfg b/naiveproxy/src/third_party/boringssl/src/infra/config/generated/cr-buildbucket.cfg index d528ee96a5..49462acf41 100644 --- a/naiveproxy/src/third_party/boringssl/src/infra/config/generated/cr-buildbucket.cfg +++ b/naiveproxy/src/third_party/boringssl/src/infra/config/generated/cr-buildbucket.cfg @@ -495,9 +495,11 @@ buckets { ' },' ' "check_stack": true,' ' "cmake_args": {' - ' "BORINGSSL_ALLOW_CXX_RUNTIME": "1"' + ' "BORINGSSL_ALLOW_CXX_RUNTIME": "1",' + ' "RUST_BINDINGS": "x86_64-unknown-linux-gnu"' ' },' - ' "recipe": "boringssl"' + ' "recipe": "boringssl",' + ' "rust": true' '}' execution_timeout_secs: 1800 caches { @@ -536,9 +538,11 @@ buckets { ' "CMAKE_CXX_FLAGS": "-m32 -msse2",' ' "CMAKE_C_FLAGS": "-m32 -msse2",' ' "CMAKE_SYSTEM_NAME": "Linux",' - ' "CMAKE_SYSTEM_PROCESSOR": "x86"' + ' "CMAKE_SYSTEM_PROCESSOR": "x86",' + ' "RUST_BINDINGS": "i686-unknown-linux-gnu"' ' },' - ' "recipe": "boringssl"' + ' "recipe": "boringssl",' + ' "rust": true' '}' execution_timeout_secs: 1800 caches { @@ -1415,7 +1419,11 @@ buckets { ' "$gatekeeper": {' ' "group": "client.boringssl"' ' },' - ' "recipe": "boringssl"' + ' "cmake_args": {' + ' "RUST_BINDINGS": "x86_64-apple-darwin"' + ' },' + ' "recipe": "boringssl",' + ' "rust": true' '}' execution_timeout_secs: 3600 caches { @@ -1452,7 +1460,11 @@ buckets { ' "$gatekeeper": {' ' "group": "client.boringssl"' ' },' - ' "recipe": "boringssl"' + ' "cmake_args": {' + ' "RUST_BINDINGS": "aarch64-apple-darwin"' + ' },' + ' "recipe": "boringssl",' + ' "rust": true' '}' execution_timeout_secs: 3600 caches { @@ -1895,10 +1907,12 @@ buckets { ' "group": "client.boringssl"' ' },' ' "cmake_args": {' - ' "CMAKE_BUILD_TYPE": "Release"' + ' "CMAKE_BUILD_TYPE": "Release",' + ' "RUST_BINDINGS": "x86_64-pc-windows-msvc"' ' },' ' "msvc_target": "x64",' - ' "recipe": "boringssl"' + ' "recipe": "boringssl",' + ' "rust": true' '}' execution_timeout_secs: 1800 caches { @@ -2744,9 +2758,11 @@ buckets { '{' ' "check_stack": true,' ' "cmake_args": {' - ' "BORINGSSL_ALLOW_CXX_RUNTIME": "1"' + ' "BORINGSSL_ALLOW_CXX_RUNTIME": "1",' + ' "RUST_BINDINGS": "x86_64-unknown-linux-gnu"' ' },' - ' "recipe": "boringssl"' + ' "recipe": "boringssl",' + ' "rust": true' '}' execution_timeout_secs: 1800 service_account: "boringssl-try-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -2774,9 +2790,11 @@ buckets { ' "CMAKE_CXX_FLAGS": "-m32 -msse2",' ' "CMAKE_C_FLAGS": "-m32 -msse2",' ' "CMAKE_SYSTEM_NAME": "Linux",' - ' "CMAKE_SYSTEM_PROCESSOR": "x86"' + ' "CMAKE_SYSTEM_PROCESSOR": "x86",' + ' "RUST_BINDINGS": "i686-unknown-linux-gnu"' ' },' - ' "recipe": "boringssl"' + ' "recipe": "boringssl",' + ' "rust": true' '}' execution_timeout_secs: 1800 service_account: "boringssl-try-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -3400,7 +3418,11 @@ buckets { } properties: '{' - ' "recipe": "boringssl"' + ' "cmake_args": {' + ' "RUST_BINDINGS": "x86_64-apple-darwin"' + ' },' + ' "recipe": "boringssl",' + ' "rust": true' '}' execution_timeout_secs: 3600 caches { @@ -3426,7 +3448,11 @@ buckets { } properties: '{' - ' "recipe": "boringssl"' + ' "cmake_args": {' + ' "RUST_BINDINGS": "aarch64-apple-darwin"' + ' },' + ' "recipe": "boringssl",' + ' "rust": true' '}' execution_timeout_secs: 3600 caches { @@ -3873,10 +3899,12 @@ buckets { properties: '{' ' "cmake_args": {' - ' "CMAKE_BUILD_TYPE": "Release"' + ' "CMAKE_BUILD_TYPE": "Release",' + ' "RUST_BINDINGS": "x86_64-pc-windows-msvc"' ' },' ' "msvc_target": "x64",' - ' "recipe": "boringssl"' + ' "recipe": "boringssl",' + ' "rust": true' '}' execution_timeout_secs: 1800 caches { diff --git a/naiveproxy/src/third_party/boringssl/src/infra/config/generated/project.cfg b/naiveproxy/src/third_party/boringssl/src/infra/config/generated/project.cfg index 5d425643cd..093f6e516a 100644 --- a/naiveproxy/src/third_party/boringssl/src/infra/config/generated/project.cfg +++ b/naiveproxy/src/third_party/boringssl/src/infra/config/generated/project.cfg @@ -7,7 +7,7 @@ name: "boringssl" access: "group:all" lucicfg { - version: "1.44.1" + version: "1.45.6" package_dir: ".." config_dir: "generated" entry_point: "main.star" diff --git a/naiveproxy/src/third_party/boringssl/src/infra/config/main.star b/naiveproxy/src/third_party/boringssl/src/infra/config/main.star index e0e2020bb7..570837a111 100755 --- a/naiveproxy/src/third_party/boringssl/src/infra/config/main.star +++ b/naiveproxy/src/third_party/boringssl/src/infra/config/main.star @@ -44,6 +44,10 @@ luci.project( roles = acl.CQ_DRY_RUNNER, groups = "project-boringssl-tryjob-access", ), + acl.entry( + roles = acl.CQ_NEW_PATCHSET_RUN_TRIGGERER, + groups = "project-boringssl-tryjob-access", + ), acl.entry( roles = acl.SCHEDULER_OWNER, groups = "project-boringssl-admins", @@ -126,6 +130,17 @@ def ci_builder( short_name = None, execution_timeout = None, properties = {}): + """Defines a CI builder. + + Args: + name: The name to use for the builder. + host: The host to run on. + recipe: The recipe to run. + category: Category in which to display the builder in the console view. + short_name: The short name for the builder in the console view. + execution_timeout: Overrides the default timeout. + properties: Properties to pass to the recipe. + """ dimensions = dict(host["dimensions"]) dimensions["pool"] = "luci.flex.ci" caches = [swarming.cache("gocache"), swarming.cache("gopath")] @@ -166,6 +181,17 @@ def cq_builder( cq_enabled = True, execution_timeout = None, properties = {}): + """Defines a CQ builder. + + Args: + name: The name to use for the builder. + host: The host to run on. + recipe: The recipe to run. + cq_enabled: Whether the try builder is enabled by default. (If false, + the builder is includable_only.) + execution_timeout: Overrides the default timeout. + properties: Properties to pass to the recipe. + """ dimensions = dict(host["dimensions"]) dimensions["pool"] = "luci.flex.try" if execution_timeout == None: @@ -190,6 +216,21 @@ def cq_builder( includable_only = not cq_enabled, ) +luci.cq_tryjob_verifier( + cq_group = "main-cq", + builder = "chromium:try/tricium-clang-tidy", + owner_whitelist = ["project-boringssl-tryjob-access"], + experiment_percentage = 100, + disable_reuse = True, + mode_allowlist = [cq.MODE_NEW_PATCHSET_RUN], + location_filters = [ + cq.location_filter(path_regexp = r".+\.h"), + cq.location_filter(path_regexp = r".+\.c"), + cq.location_filter(path_regexp = r".+\.cc"), + cq.location_filter(path_regexp = r".+\.cpp"), + ], +) + def both_builders( name, host, @@ -201,6 +242,24 @@ def both_builders( cq_compile_only = None, execution_timeout = None, properties = {}): + """Defines both a CI builder and similarly-configured CQ builder. + + Args: + name: The name to use for both builders. + host: The host to run on. + recipe: The recipe to run. + category: Category in which to display the builder in the console view. + short_name: The short name for the builder in the console view. + cq_enabled: Whether the try builder is enabled by default. (If false, + the builder is includable_only.) + cq_compile_only: If cq_compile_only is specified, we generate both a + disabled builder that matches the CI builder, and a compile-only + builder. The compile-only builder is controlled by cq_enabled. + cq_compile_only also specifies the host to run on, because the + compile-only builder usually has weaker requirements. + execution_timeout: Overrides the default timeout. + properties: Properties to pass to the recipe. + """ ci_builder( name, host, @@ -211,11 +270,6 @@ def both_builders( properties = properties, ) - # If cq_compile_only is specified, we generate both a disabled builder that - # matches the CI builder, and a compile-only builder. The compile-only - # builder is controlled by cq_enabled. cq_compile_only also specifies the - # host to run on, because the compile-only builder usually has weaker - # requirements. cq_builder( name, host, @@ -362,7 +416,6 @@ both_builders( }, ) - # delocate works on aarch64. Test this by also building the static library mode # for android_aarch64_fips. Additionally, urandom_test doesn't work in shared # library builds, so this gives Android FIPS coverage for urandom_test. @@ -505,7 +558,10 @@ both_builders( # Pick one builder to build with the C++ runtime allowed. The default # configuration does not check pure virtuals "BORINGSSL_ALLOW_CXX_RUNTIME": "1", + "RUST_BINDINGS": "x86_64-unknown-linux-gnu", }, + # Also build and test the Rust code. + "rust": True, }, ) both_builders( @@ -533,7 +589,10 @@ both_builders( "CMAKE_ASM_FLAGS": "-m32 -msse2", "CMAKE_CXX_FLAGS": "-m32 -msse2", "CMAKE_C_FLAGS": "-m32 -msse2", + "RUST_BINDINGS": "i686-unknown-linux-gnu", }, + # Also build and test the Rust code. + "rust": True, }, ) both_builders( @@ -835,7 +894,19 @@ both_builders( short_name = "bzl", recipe = "boringssl_bazel", ) -both_builders("mac", MAC_X86_64_HOST, category = "mac", short_name = "dbg") +both_builders( + "mac", + MAC_X86_64_HOST, + category = "mac", + short_name = "dbg", + properties = { + "cmake_args": { + "RUST_BINDINGS": "x86_64-apple-darwin", + }, + # Also build and test the Rust code. + "rust": True, + }, +) both_builders( "mac_rel", MAC_X86_64_HOST, @@ -859,7 +930,19 @@ both_builders( }, }, ) -both_builders("mac_arm64", MAC_ARM64_HOST, category = "mac", short_name = "arm64") +both_builders( + "mac_arm64", + MAC_ARM64_HOST, + category = "mac", + short_name = "arm64", + properties = { + "cmake_args": { + "RUST_BINDINGS": "aarch64-apple-darwin", + }, + # Also build and test the Rust code. + "rust": True, + }, +) both_builders( "mac_arm64_bazel", MAC_ARM64_HOST, @@ -950,6 +1033,7 @@ both_builders( "msvc_target": "x64", }, ) + both_builders( "win64_rel", WIN_HOST, @@ -958,8 +1042,11 @@ both_builders( properties = { "cmake_args": { "CMAKE_BUILD_TYPE": "Release", + "RUST_BINDINGS": "x86_64-pc-windows-msvc", }, "msvc_target": "x64", + # Also build and test the Rust code. + "rust": True, }, ) both_builders( diff --git a/naiveproxy/src/third_party/boringssl/src/pki/path_builder.cc b/naiveproxy/src/third_party/boringssl/src/pki/path_builder.cc index d3b396de57..876cc9b09e 100644 --- a/naiveproxy/src/third_party/boringssl/src/pki/path_builder.cc +++ b/naiveproxy/src/third_party/boringssl/src/pki/path_builder.cc @@ -21,7 +21,7 @@ #include #include -#include +#include #include "cert_issuer_source.h" #include "certificate_policies.h" diff --git a/naiveproxy/src/third_party/boringssl/src/pki/simple_path_builder_delegate.cc b/naiveproxy/src/third_party/boringssl/src/pki/simple_path_builder_delegate.cc index 55888ad6d7..787061167a 100644 --- a/naiveproxy/src/third_party/boringssl/src/pki/simple_path_builder_delegate.cc +++ b/naiveproxy/src/third_party/boringssl/src/pki/simple_path_builder_delegate.cc @@ -118,14 +118,7 @@ bool SimplePathBuilderDelegate::IsPublicKeyAcceptable(EVP_PKEY *public_key, } if (pkey_id == EVP_PKEY_EC) { - // Extract the curve name. - EC_KEY *ec = EVP_PKEY_get0_EC_KEY(public_key); - if (!ec) { - return false; // Unexpected. - } - int curve_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); - - if (!IsAcceptableCurveForEcdsa(curve_nid)) { + if (!IsAcceptableCurveForEcdsa(EVP_PKEY_get_ec_curve_nid(public_key))) { errors->AddWarning(kUnacceptableCurveForEcdsa); return false; } diff --git a/naiveproxy/src/third_party/boringssl/src/pki/verify_signed_data.cc b/naiveproxy/src/third_party/boringssl/src/pki/verify_signed_data.cc index 668598cafb..e77dcc4ec9 100644 --- a/naiveproxy/src/third_party/boringssl/src/pki/verify_signed_data.cc +++ b/naiveproxy/src/third_party/boringssl/src/pki/verify_signed_data.cc @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include "cert_errors.h" #include "input.h" diff --git a/naiveproxy/src/third_party/boringssl/src/rust/Cargo.lock b/naiveproxy/src/third_party/boringssl/src/rust/Cargo.lock new file mode 100644 index 0000000000..d1c658f39b --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/rust/Cargo.lock @@ -0,0 +1,14 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bssl-crypto" +version = "0.2.0" +dependencies = [ + "bssl-sys", +] + +[[package]] +name = "bssl-sys" +version = "0.1.0" diff --git a/naiveproxy/src/third_party/boringssl/src/rust/Cargo.toml b/naiveproxy/src/third_party/boringssl/src/rust/Cargo.toml new file mode 100644 index 0000000000..a0689b3592 --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/rust/Cargo.toml @@ -0,0 +1,6 @@ +[workspace] +members = [ + "bssl-crypto", + "bssl-sys", +] +resolver = "3" diff --git a/naiveproxy/src/third_party/boringssl/src/rust/bssl-crypto/Cargo.lock b/naiveproxy/src/third_party/boringssl/src/rust/bssl-crypto/Cargo.lock new file mode 100644 index 0000000000..d1c658f39b --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/rust/bssl-crypto/Cargo.lock @@ -0,0 +1,14 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bssl-crypto" +version = "0.2.0" +dependencies = [ + "bssl-sys", +] + +[[package]] +name = "bssl-sys" +version = "0.1.0" diff --git a/naiveproxy/src/third_party/boringssl/src/rust/bssl-crypto/src/rsa.rs b/naiveproxy/src/third_party/boringssl/src/rust/bssl-crypto/src/rsa.rs index f41c3b13b7..84539f7941 100644 --- a/naiveproxy/src/third_party/boringssl/src/rust/bssl-crypto/src/rsa.rs +++ b/naiveproxy/src/third_party/boringssl/src/rust/bssl-crypto/src/rsa.rs @@ -326,6 +326,22 @@ mod test { .verify_pkcs1::(signed_msg, &sig) .is_ok()); } + + #[test] + fn no_rsa_pss_spki() { + // `from_der_subject_public_key_info` should not accept id-RSASSA-PSS. + const RSA_PSS_SPKI: &[u8] = b"\x30\x82\x01\x56\x30\x41\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0a\x30\x34\xa0\x0f\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\xa1\x1c\x30\x1a\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x08\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\xa2\x03\x02\x01\x20\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xcd\x00\x81\xea\x7b\x2a\xe1\xea\x06\xd5\x9f\x7c\x73\xd9\xff\xb9\x4a\x09\x61\x5c\x2e\x4b\xa7\xc6\x36\xce\xf0\x8d\xd3\x53\x3e\xc3\x18\x55\x25\xb0\x15\xc7\x69\xb9\x9a\x77\xd6\x72\x5b\xf9\xc3\x53\x2a\x9b\x6e\x5f\x66\x27\xd5\xfb\x85\x16\x07\x68\xd3\xdd\xa9\xcb\xd3\x59\x74\x51\x17\x17\xdc\x3d\x30\x9d\x2f\xc4\x7e\xe4\x1f\x97\xe3\x2a\xdb\x7f\x9d\xd8\x64\xa1\xc4\x76\x7a\x66\x6e\xcd\x71\xbc\x1a\xac\xf5\xe7\x51\x7f\x4b\x38\x59\x4f\xea\x9b\x05\xe4\x2d\x5a\xda\x99\x12\x00\x80\x13\xe4\x53\x16\xa4\xd9\xbb\x8e\xd0\x86\xb8\x8d\x28\x75\x8b\xac\xaf\x92\x2d\x46\xa8\x68\xb4\x85\xd2\x39\xc9\xba\xeb\x0e\x2b\x64\x59\x27\x10\xf4\x2b\x2d\x1e\xa0\xa4\xb4\x80\x2c\x0b\xec\xab\x32\x8f\x8a\x68\xb0\x07\x3b\xdb\x54\x6f\xee\xa9\x80\x9d\x28\x49\x91\x2b\x39\x0c\x15\x32\xbc\x7e\x29\xc7\x65\x8f\x81\x75\xfa\xe4\x6f\x34\x33\x2f\xf8\x7b\xca\xb3\xe4\x06\x49\xb9\x85\x77\x86\x9d\xa0\xea\x71\x83\x53\xf0\x72\x27\x54\x88\x69\x13\x64\x87\x60\xd1\x22\xbe\x67\x6e\x0f\xc4\x83\xdd\x20\xff\xc3\x1b\xda\x96\xa3\x19\x66\xc9\xaa\x2e\x75\xad\x03\xde\x47\xe1\xc4\x4f\x02\x03\x01\x00\x01"; + let key = PublicKey::from_der_subject_public_key_info(RSA_PSS_SPKI); + assert!(key.is_none()); + } + + #[test] + fn no_rsa_pss_pkcs8() { + // `from_der_private_key_info` should not accept id-RSASSA-PSS. + const RSA_PSS_PKCS8: &[u8] = b"\x30\x82\x04\xf0\x02\x01\x00\x30\x41\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0a\x30\x34\xa0\x0f\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\xa1\x1c\x30\x1a\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x08\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\xa2\x03\x02\x01\x20\x04\x82\x04\xa6\x30\x82\x04\xa2\x02\x01\x00\x02\x82\x01\x01\x00\xcd\x00\x81\xea\x7b\x2a\xe1\xea\x06\xd5\x9f\x7c\x73\xd9\xff\xb9\x4a\x09\x61\x5c\x2e\x4b\xa7\xc6\x36\xce\xf0\x8d\xd3\x53\x3e\xc3\x18\x55\x25\xb0\x15\xc7\x69\xb9\x9a\x77\xd6\x72\x5b\xf9\xc3\x53\x2a\x9b\x6e\x5f\x66\x27\xd5\xfb\x85\x16\x07\x68\xd3\xdd\xa9\xcb\xd3\x59\x74\x51\x17\x17\xdc\x3d\x30\x9d\x2f\xc4\x7e\xe4\x1f\x97\xe3\x2a\xdb\x7f\x9d\xd8\x64\xa1\xc4\x76\x7a\x66\x6e\xcd\x71\xbc\x1a\xac\xf5\xe7\x51\x7f\x4b\x38\x59\x4f\xea\x9b\x05\xe4\x2d\x5a\xda\x99\x12\x00\x80\x13\xe4\x53\x16\xa4\xd9\xbb\x8e\xd0\x86\xb8\x8d\x28\x75\x8b\xac\xaf\x92\x2d\x46\xa8\x68\xb4\x85\xd2\x39\xc9\xba\xeb\x0e\x2b\x64\x59\x27\x10\xf4\x2b\x2d\x1e\xa0\xa4\xb4\x80\x2c\x0b\xec\xab\x32\x8f\x8a\x68\xb0\x07\x3b\xdb\x54\x6f\xee\xa9\x80\x9d\x28\x49\x91\x2b\x39\x0c\x15\x32\xbc\x7e\x29\xc7\x65\x8f\x81\x75\xfa\xe4\x6f\x34\x33\x2f\xf8\x7b\xca\xb3\xe4\x06\x49\xb9\x85\x77\x86\x9d\xa0\xea\x71\x83\x53\xf0\x72\x27\x54\x88\x69\x13\x64\x87\x60\xd1\x22\xbe\x67\x6e\x0f\xc4\x83\xdd\x20\xff\xc3\x1b\xda\x96\xa3\x19\x66\xc9\xaa\x2e\x75\xad\x03\xde\x47\xe1\xc4\x4f\x02\x03\x01\x00\x01\x02\x82\x01\x00\x60\x29\x7a\xc7\x99\x1b\x16\x7a\x06\xd6\xb2\x47\x58\xb8\xcb\xe2\x08\xbe\xb9\xb2\xd9\xec\x97\x38\xbd\x80\xf9\x0a\x2e\x35\x00\x5d\xd7\xce\x29\x2d\x9e\x29\xba\x88\x5b\xd3\x16\xfe\xf1\xf2\x09\x13\xbc\x0a\xc9\x0d\x6b\x08\x08\xb2\x41\x4d\x82\x10\x44\x41\xd8\x62\x4a\x33\xce\x02\x33\xc8\xf7\x80\xa4\x8b\x37\x5a\xff\x02\xd7\x67\x12\x22\x8a\x70\x24\x84\xdb\x3f\x9e\xbe\xcc\xcf\xbb\xee\x17\x09\xdb\xa1\x82\x80\x0d\x94\x9e\x9e\x42\x16\xe0\xbf\xf3\x55\x83\x88\xf8\xbd\x90\xda\x37\x3a\x1d\x82\x74\x3e\xc3\xfb\xdd\x14\x27\xfd\x16\x82\x5a\x65\x7a\x31\x69\x12\xe8\x69\x53\x65\x11\x7c\xa2\xf8\x45\xc9\x09\x40\x5f\xca\xc5\x5f\x89\x5f\xc1\x5d\x20\x38\x6c\x26\xee\x78\xc9\xe9\x90\x75\x02\x9a\x17\x8a\x6c\x1e\x4c\xf0\xc2\x00\xe8\xa9\xcf\xb2\x7e\x9d\x15\x6f\x86\xe6\xc2\xad\xc2\x2b\x1a\x84\xa1\xcd\x5c\xa5\xb2\x79\x08\x75\xd7\x94\x07\xc8\x4b\x35\x23\x95\xcb\x81\xcc\x3f\xed\x5b\xb0\x43\xb6\x9e\xde\x0c\x07\x20\x45\x50\x02\x5c\xee\x8c\x5f\x44\x01\x70\xb6\x12\x0b\xb4\x8e\x0f\x74\x7b\xcd\x8f\x52\x21\x10\x85\x0d\xf0\x43\xc4\x28\xdf\xd1\x87\x05\x31\x02\x81\x81\x00\xf6\xf9\x61\xb4\x7c\xbc\x03\x5d\x3a\xed\xeb\xc7\xde\x85\x0a\x95\x6b\x65\xec\xdb\x9c\xf6\x07\x64\x06\x3f\x15\xaa\x48\x55\x3c\x58\xd9\x72\xfe\x66\x75\x05\x6e\x35\xdd\xfd\xc3\x7b\xf3\xb9\xf2\xf6\x22\xee\x27\x13\x37\x25\x68\x49\xc9\xbe\xf2\x17\x6f\xe8\xf7\xc3\xf8\xbb\x91\xba\x37\x4d\xd5\x3b\xaf\x3d\xec\x81\x4d\x2b\xde\xc1\x0c\x1f\xdc\x88\xcd\xd1\x68\x76\xf2\x6b\x1e\xdf\xa3\xf0\x94\x19\x7e\xdf\x4d\x42\xff\x1f\xb2\x97\x11\x03\xb8\x98\xca\x85\x9c\x42\x72\x87\x08\x6a\x84\x2a\xb4\x10\xbb\x69\xcf\x2d\x35\xaf\x6b\xe3\x02\x81\x81\x00\xd4\x7e\x72\x4a\x7f\xf4\x10\x48\xb2\x70\xc2\x52\x4a\x41\x01\x87\x8b\x73\x15\x9b\xb7\x3d\x3d\xbc\x18\x7b\x22\x0e\x63\x5b\x35\x34\xf9\x6e\x24\x3a\x18\x4d\x93\xf8\x60\xb6\xbf\xbb\x6b\x71\xc1\xed\x9a\x1e\x1f\x45\x85\x83\x02\x3c\x30\x1e\x96\xa6\x92\xc1\xa0\x8b\x53\xd0\xec\x9c\xa9\x10\x10\x0d\x80\x45\x1e\x3b\x7d\xc6\xa0\x1b\xac\x4a\xec\xef\x8d\xf7\x98\x84\x6b\xc2\x35\xa0\x8c\xbb\xa2\xcf\x4c\x06\x80\x4c\xc1\x12\x19\xe9\x56\x08\xc7\x14\xe3\xf1\x43\x0d\x49\x1f\xad\xbb\xa3\x2a\x57\x51\xa0\x4f\x97\x74\x58\x34\xc9\xa5\x02\x81\x80\x21\xf2\x45\x2b\xb9\xb9\x5d\xfd\x02\x8c\x91\x4b\xf7\x99\xf1\xca\x77\xe8\x9a\x95\xd5\x0d\x3c\x16\xd3\x84\xf8\x45\x5f\x8b\xd7\xaf\x9e\xb3\xdf\xa3\xd5\x91\xd9\x84\x2d\xef\x23\x5f\x76\x30\xa8\xe4\x8c\x08\x8f\xf6\x64\x2e\x10\x17\x94\x53\x5a\x93\x3e\x1e\x97\x6f\xa8\x50\x9f\xc7\x28\xb2\xda\x0c\x4a\x1a\x08\xd7\xfc\xf3\x7a\xba\xae\x1f\xf3\x00\x1a\xca\x1d\xc1\xbb\xb0\x5d\x9d\xff\xba\xa1\xa0\x9f\x7f\xb1\xee\xf3\x82\x37\xd9\xeb\xcc\xc7\x22\xb9\x33\x84\x36\xdd\xe7\x11\x91\x12\x79\x8c\x26\x80\x9c\x1a\x8d\xec\x43\x20\x61\x02\x81\x80\x1f\x75\x10\xaa\x62\xc2\xd8\xde\x4a\x3c\x53\x28\x27\x81\xf4\x1e\x02\xd0\xe8\xb4\x02\xae\x78\x43\x2e\x44\x9c\x48\x11\x01\x61\xa1\x14\x03\xf0\x2d\x01\x88\x0a\x8d\xcc\x93\x81\x52\xd7\x97\x21\xa4\x71\x1a\x60\x7a\xc4\x47\x1e\xbf\x96\x48\x10\xf9\x5b\xe4\x7a\x45\xe6\x04\x99\xe2\x9f\x4c\x97\x73\xc8\x37\x73\x40\x4f\x60\x66\x37\x72\x8c\x2d\x03\x51\xbb\x03\xc3\x26\xc8\xbb\x73\xa7\x21\xe7\xfa\x54\x40\xea\x21\x72\xbb\xa1\x46\x5f\xcc\x30\xdc\xb0\xd9\xf8\x99\x30\xe8\x15\xaa\x1f\x7f\x97\x29\xa8\x57\xe0\x0e\x03\x38\xdd\x59\x02\x81\x80\x4d\x1f\x0d\x75\x6f\xe7\x7e\x01\x09\x9a\x65\x2f\x50\xa8\x8b\x7b\x68\x5d\xc5\xbf\x00\x98\x1d\x5d\x23\x76\xfd\x0c\x6f\xe2\x9c\xd5\xb6\x38\x73\x44\x79\x30\x5a\x73\xad\x3c\x15\x99\xd3\x9e\xae\x3b\xae\x03\x5f\xbd\x6f\xed\x07\xc2\x8d\xe7\x05\x93\x38\x79\xa0\x6e\x48\xe6\xa6\x03\x68\x6e\xd8\xe2\x56\x0a\x5f\x6a\xf1\xf2\xc2\x4f\xaf\x4a\xa9\x60\xe3\x82\x18\x6f\x15\xee\xdc\xe9\xa2\x49\x1a\xe7\x30\x68\x0d\xd4\xcf\x77\x8b\x70\xfa\xa8\x68\x26\xab\x32\x23\x47\x7c\xc9\x13\x77\xb1\x9a\x6d\x5a\x2e\xae\xa2\x19\x76\x0b\xee\xd5"; + let key = PrivateKey::from_der_private_key_info(RSA_PSS_PKCS8); + assert!(key.is_none()); + } } // RSA generation is slow, but serialized keys are large. In order to use this diff --git a/naiveproxy/src/third_party/boringssl/src/rust/bssl-sys/Cargo.lock b/naiveproxy/src/third_party/boringssl/src/rust/bssl-sys/Cargo.lock new file mode 100644 index 0000000000..24f17f4a6e --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/rust/bssl-sys/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bssl-sys" +version = "0.1.0" 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 8f97e6af53..a55bdffaa1 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 @@ -1,9 +1,17 @@ #![no_std] +// unnecessary_transmutes, needed to work around a Rust bug, is not available in +// older Rusts. Stable lacks any way to condition code on Rust version, so the +// workaroud for a Rust bug below needs this additional Rust workaround. +#![allow(unknown_lints)] + #![allow(non_upper_case_globals)] #![allow(non_camel_case_types)] #![allow(non_snake_case)] +// Work around https://github.com/rust-lang/rust-bindgen/issues/2807 +#![allow(unnecessary_transmutes)] + use core::ffi::c_ulong; // Wrap the bindgen output in a module and re-export it, so we can override it diff --git a/naiveproxy/src/third_party/boringssl/src/rust/bssl-sys/wrapper.h b/naiveproxy/src/third_party/boringssl/src/rust/bssl-sys/wrapper.h index 6428234f8d..c092c954c9 100644 --- a/naiveproxy/src/third_party/boringssl/src/rust/bssl-sys/wrapper.h +++ b/naiveproxy/src/third_party/boringssl/src/rust/bssl-sys/wrapper.h @@ -64,6 +64,7 @@ #include #include #include +#include #include #include #include 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 4ce8d1802f..77d02fde50 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/handshake_client.cc +++ b/naiveproxy/src/third_party/boringssl/src/ssl/handshake_client.cc @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include "../crypto/internal.h" #include "internal.h" 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 6986141e0a..ecfcaa1284 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/handshake_server.cc +++ b/naiveproxy/src/third_party/boringssl/src/ssl/handshake_server.cc @@ -243,10 +243,9 @@ static TLS12ServerParams choose_params(SSL_HANDSHAKE *hs, // curve list. int key_type = EVP_PKEY_id(cred->pubkey.get()); if (key_type == EVP_PKEY_EC) { - EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(cred->pubkey.get()); uint16_t group_id; - if (!ssl_nid_to_group_id( - &group_id, EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key))) || + if (!ssl_nid_to_group_id(&group_id, + EVP_PKEY_get_ec_curve_nid(cred->pubkey.get())) || std::find(hs->peer_supported_group_list.begin(), hs->peer_supported_group_list.end(), group_id) == hs->peer_supported_group_list.end()) { diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/s3_both.cc b/naiveproxy/src/third_party/boringssl/src/ssl/s3_both.cc index a37a06f2a7..d30cabba2e 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/s3_both.cc +++ b/naiveproxy/src/third_party/boringssl/src/ssl/s3_both.cc @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include "../crypto/internal.h" #include "internal.h" diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/ssl_cert.cc b/naiveproxy/src/third_party/boringssl/src/ssl/ssl_cert.cc index 0b9ec48a9d..c0d510b324 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/ssl_cert.cc +++ b/naiveproxy/src/third_party/boringssl/src/ssl/ssl_cert.cc @@ -23,10 +23,12 @@ #include #include +#include #include #include +#include #include -#include +#include #include #include "../crypto/internal.h" @@ -488,12 +490,11 @@ bool ssl_check_leaf_certificate(SSL_HANDSHAKE *hs, EVP_PKEY *pkey, if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) { // Check the key's group and point format are acceptable. - EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey); uint16_t group_id; - if (!ssl_nid_to_group_id( - &group_id, EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key))) || + if (!ssl_nid_to_group_id(&group_id, EVP_PKEY_get_ec_curve_nid(pkey)) || !tls1_check_group_id(hs, group_id) || - EC_KEY_get_conv_form(ec_key) != POINT_CONVERSION_UNCOMPRESSED) { + EVP_PKEY_get_ec_point_conv_form(pkey) != + POINT_CONVERSION_UNCOMPRESSED) { OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECC_CERT); return false; } 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 4fe7ba0ca5..aa8ef8a0c5 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/ssl_lib.cc +++ b/naiveproxy/src/third_party/boringssl/src/ssl/ssl_lib.cc @@ -26,7 +26,9 @@ #include #include #include +#include #include +#include #include #include "../crypto/internal.h" @@ -2332,14 +2334,8 @@ int SSL_enable_tls_channel_id(SSL *ssl) { return 1; } -static int is_p256_key(EVP_PKEY *private_key) { - const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(private_key); - return ec_key != NULL && EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) == - NID_X9_62_prime256v1; -} - int SSL_CTX_set1_tls_channel_id(SSL_CTX *ctx, EVP_PKEY *private_key) { - if (!is_p256_key(private_key)) { + if (EVP_PKEY_get_ec_curve_nid(private_key) != NID_X9_62_prime256v1) { OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_NOT_P256); return 0; } @@ -2352,7 +2348,7 @@ int SSL_set1_tls_channel_id(SSL *ssl, EVP_PKEY *private_key) { if (!ssl->config) { return 0; } - if (!is_p256_key(private_key)) { + if (EVP_PKEY_get_ec_curve_nid(private_key) != NID_X9_62_prime256v1) { OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_NOT_P256); return 0; } 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 46906f9f3b..8e54853582 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/ssl_privkey.cc +++ b/naiveproxy/src/third_party/boringssl/src/ssl/ssl_privkey.cc @@ -154,8 +154,7 @@ bool ssl_pkey_supports_algorithm(const SSL *ssl, EVP_PKEY *pkey, // EC keys have a curve requirement. if (alg->pkey_type == EVP_PKEY_EC && (alg->curve == NID_undef || - EC_GROUP_get_curve_name( - EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey))) != alg->curve)) { + EVP_PKEY_get_ec_curve_nid(pkey) != alg->curve)) { return false; } } else if (!alg->tls12_ok) { diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/tls13_client.cc b/naiveproxy/src/third_party/boringssl/src/ssl/tls13_client.cc index eca654fa0a..e18ad11bab 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/tls13_client.cc +++ b/naiveproxy/src/third_party/boringssl/src/ssl/tls13_client.cc @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include "../crypto/internal.h" diff --git a/naiveproxy/src/third_party/boringssl/src/third_party/fiat/README.md b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/README.md index 4595ba67ab..3f981553b1 100644 --- a/naiveproxy/src/third_party/boringssl/src/third_party/fiat/README.md +++ b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/README.md @@ -29,7 +29,9 @@ Routines for which assembly-level optimization is not necessary are written in `bedrock_unverified_platform.c.inc` provides the platform functionality code thus translated expects. -The P256 coordinate subtraction function in 64-bit C code generated by Fiat -Cryptography has been manually replaced with a version written in Bedrock. -This is an early step towards using Bedrock more widely, both on its own and as -an alternative pathway from Fiat Cryptography to C. +The P256 point doubling and addition are implemented in this manner in +p256_coord.br.c.inc. This code originates from Fiat Cryptogaphy commit +b8890d810b812180fb224356e0f0b932afade414 file src/Bedrock/P256.v +Field arithmetic operations are dispatched in p256_field.c.inc to +platform-specific code including assembly, fiat-crypto-generated C, and +Bedrock-generated C. diff --git a/naiveproxy/src/third_party/boringssl/src/third_party/fiat/bedrock_unverified_platform.c.inc b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/bedrock_unverified_platform.c.inc index fbfe90f9dc..89fe7d05d4 100644 --- a/naiveproxy/src/third_party/boringssl/src/third_party/fiat/bedrock_unverified_platform.c.inc +++ b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/bedrock_unverified_platform.c.inc @@ -34,6 +34,10 @@ static inline void br_memset(br_word_t d, br_word_t v, br_word_t n) { OPENSSL_memset((void *)d, v, n); } +static inline void br_memcxor(uintptr_t d, uintptr_t s, uintptr_t n, uintptr_t mask) { + constant_time_conditional_memxor((void*)d, (void*)s, n, mask); +} + // CPU Arithmetic static inline br_word_t br_full_add(br_word_t x, br_word_t y, br_word_t carry, diff --git a/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_64.h b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_64.h index 21f7a98d03..437066a910 100644 --- a/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_64.h +++ b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_64.h @@ -1,6 +1,6 @@ #include #include "bedrock_unverified_platform.c.inc" -#include "p256_bedrock.c.inc" +#include "p256_field_64.br.c.inc" #include "../../crypto/internal.h" #if !defined(OPENSSL_NO_ASM) && defined(__GNUC__) && defined(__x86_64__) @@ -177,6 +177,7 @@ static FIAT_P256_FIAT_INLINE void fiat_p256_cmovznz_u64(uint64_t* out1, fiat_p25 * */ static FIAT_P256_FIAT_INLINE void fiat_p256_mul(fiat_p256_montgomery_domain_field_element out1, const fiat_p256_montgomery_domain_field_element arg1, const fiat_p256_montgomery_domain_field_element arg2) { + // NOTE: edited by hand, see third_party/fiat/README.md #if !defined(OPENSSL_NO_ASM) && defined(__GNUC__) && defined(__x86_64__) if (CRYPTO_is_BMI1_capable() && CRYPTO_is_BMI2_capable() && CRYPTO_is_ADX_capable()) { @@ -491,6 +492,7 @@ static FIAT_P256_FIAT_INLINE void fiat_p256_mul(fiat_p256_montgomery_domain_fiel * */ static FIAT_P256_FIAT_INLINE void fiat_p256_square(fiat_p256_montgomery_domain_field_element out1, const fiat_p256_montgomery_domain_field_element arg1) { + // NOTE: edited by hand, see third_party/fiat/README.md #if !defined(OPENSSL_NO_ASM) && defined(__GNUC__) && defined(__x86_64__) if (CRYPTO_is_BMI1_capable() && CRYPTO_is_BMI2_capable() && CRYPTO_is_ADX_capable()) { @@ -806,45 +808,8 @@ static FIAT_P256_FIAT_INLINE void fiat_p256_square(fiat_p256_montgomery_domain_f * */ static FIAT_P256_FIAT_INLINE void fiat_p256_add(fiat_p256_montgomery_domain_field_element out1, const fiat_p256_montgomery_domain_field_element arg1, const fiat_p256_montgomery_domain_field_element arg2) { - uint64_t x1; - fiat_p256_uint1 x2; - uint64_t x3; - fiat_p256_uint1 x4; - uint64_t x5; - fiat_p256_uint1 x6; - uint64_t x7; - fiat_p256_uint1 x8; - uint64_t x9; - fiat_p256_uint1 x10; - uint64_t x11; - fiat_p256_uint1 x12; - uint64_t x13; - fiat_p256_uint1 x14; - uint64_t x15; - fiat_p256_uint1 x16; - uint64_t x17; - fiat_p256_uint1 x18; - uint64_t x19; - uint64_t x20; - uint64_t x21; - uint64_t x22; - fiat_p256_addcarryx_u64(&x1, &x2, 0x0, (arg1[0]), (arg2[0])); - fiat_p256_addcarryx_u64(&x3, &x4, x2, (arg1[1]), (arg2[1])); - fiat_p256_addcarryx_u64(&x5, &x6, x4, (arg1[2]), (arg2[2])); - fiat_p256_addcarryx_u64(&x7, &x8, x6, (arg1[3]), (arg2[3])); - fiat_p256_subborrowx_u64(&x9, &x10, 0x0, x1, UINT64_C(0xffffffffffffffff)); - fiat_p256_subborrowx_u64(&x11, &x12, x10, x3, UINT32_C(0xffffffff)); - fiat_p256_subborrowx_u64(&x13, &x14, x12, x5, 0x0); - fiat_p256_subborrowx_u64(&x15, &x16, x14, x7, UINT64_C(0xffffffff00000001)); - fiat_p256_subborrowx_u64(&x17, &x18, x16, x8, 0x0); - fiat_p256_cmovznz_u64(&x19, x18, x9, x1); - fiat_p256_cmovznz_u64(&x20, x18, x11, x3); - fiat_p256_cmovznz_u64(&x21, x18, x13, x5); - fiat_p256_cmovznz_u64(&x22, x18, x15, x7); - out1[0] = x19; - out1[1] = x20; - out1[2] = x21; - out1[3] = x22; + // NOTE: edited by hand, see third_party/fiat/README.md + p256_coord_add((br_word_t)out1, (br_word_t)arg1, (br_word_t)arg2); } /* @@ -859,6 +824,7 @@ static FIAT_P256_FIAT_INLINE void fiat_p256_add(fiat_p256_montgomery_domain_fiel * */ static FIAT_P256_FIAT_INLINE void fiat_p256_sub(fiat_p256_montgomery_domain_field_element out1, const fiat_p256_montgomery_domain_field_element arg1, const fiat_p256_montgomery_domain_field_element arg2) { + // NOTE: edited by hand, see third_party/fiat/README.md p256_coord_sub((br_word_t)out1, (br_word_t)arg1, (br_word_t)arg2); } diff --git a/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_64_msvc.h b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_64_msvc.h index 0e56867922..aff43d3599 100644 --- a/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_64_msvc.h +++ b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_64_msvc.h @@ -18,7 +18,7 @@ /* if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256 */ #include "bedrock_unverified_platform.c.inc" -#include "p256_bedrock.c.inc" +#include "p256_field_64.br.c.inc" #include #include #if defined(_M_X64) @@ -773,45 +773,8 @@ static FIAT_P256_FIAT_INLINE void fiat_p256_square(fiat_p256_montgomery_domain_f * */ static FIAT_P256_FIAT_INLINE void fiat_p256_add(fiat_p256_montgomery_domain_field_element out1, const fiat_p256_montgomery_domain_field_element arg1, const fiat_p256_montgomery_domain_field_element arg2) { - uint64_t x1; - fiat_p256_uint1 x2; - uint64_t x3; - fiat_p256_uint1 x4; - uint64_t x5; - fiat_p256_uint1 x6; - uint64_t x7; - fiat_p256_uint1 x8; - uint64_t x9; - fiat_p256_uint1 x10; - uint64_t x11; - fiat_p256_uint1 x12; - uint64_t x13; - fiat_p256_uint1 x14; - uint64_t x15; - fiat_p256_uint1 x16; - uint64_t x17; - fiat_p256_uint1 x18; - uint64_t x19; - uint64_t x20; - uint64_t x21; - uint64_t x22; - fiat_p256_addcarryx_u64(&x1, &x2, 0x0, (arg1[0]), (arg2[0])); - fiat_p256_addcarryx_u64(&x3, &x4, x2, (arg1[1]), (arg2[1])); - fiat_p256_addcarryx_u64(&x5, &x6, x4, (arg1[2]), (arg2[2])); - fiat_p256_addcarryx_u64(&x7, &x8, x6, (arg1[3]), (arg2[3])); - fiat_p256_subborrowx_u64(&x9, &x10, 0x0, x1, UINT64_C(0xffffffffffffffff)); - fiat_p256_subborrowx_u64(&x11, &x12, x10, x3, UINT32_C(0xffffffff)); - fiat_p256_subborrowx_u64(&x13, &x14, x12, x5, 0x0); - fiat_p256_subborrowx_u64(&x15, &x16, x14, x7, UINT64_C(0xffffffff00000001)); - fiat_p256_subborrowx_u64(&x17, &x18, x16, x8, 0x0); - fiat_p256_cmovznz_u64(&x19, x18, x9, x1); - fiat_p256_cmovznz_u64(&x20, x18, x11, x3); - fiat_p256_cmovznz_u64(&x21, x18, x13, x5); - fiat_p256_cmovznz_u64(&x22, x18, x15, x7); - out1[0] = x19; - out1[1] = x20; - out1[2] = x21; - out1[3] = x22; + // NOTE: edited by hand, see third_party/fiat/README.md + p256_coord_add((br_word_t)out1, (br_word_t)arg1, (br_word_t)arg2); } /* diff --git a/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_bedrock.c.inc b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_bedrock.c.inc deleted file mode 100644 index fb8c3de2ca..0000000000 --- a/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_bedrock.c.inc +++ /dev/null @@ -1,21 +0,0 @@ -// Generated from Bedrock code in Fiat Cryptography. Avoid editing directly. - -static_assert(BR_WORD_MAX == UINT64_MAX, ""); - -static inline void p256_coord_sub(br_word_t out, br_word_t x, br_word_t y) { - br_word_t borrow, t0, t1, t2, t3, mask, carry, r0, r1, r2, r3; - borrow = br_full_sub(_br_load(x), _br_load(y), (br_word_t)0, &t0); - borrow = br_full_sub(_br_load(x+8), _br_load(y+8), borrow, &t1); - borrow = br_full_sub(_br_load((x+8)+8), _br_load((y+8)+8), borrow, &t2); - borrow = br_full_sub(_br_load(((x+8)+8)+8), _br_load(((y+8)+8)+8), borrow, &t3); - mask = br_value_barrier(0u-borrow); - carry = br_full_add(t0, mask, (br_word_t)0, &r0); - carry = br_full_add(t1, mask&0xffffffff, carry, &r1); - carry = br_full_add(t2, (br_word_t)0, carry, &r2); - carry = br_full_add(t3, mask&0xffffffff00000001, carry, &r3); - _br_store(out, r0); - _br_store(out+8, r1); - _br_store((out+8)+8, r2); - _br_store(((out+8)+8)+8, r3); - return; -} diff --git a/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_field.c.inc b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_field.c.inc new file mode 100644 index 0000000000..bbd25de846 --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_field.c.inc @@ -0,0 +1,26 @@ +#include +#include "bedrock_unverified_platform.c.inc" + +#if defined(BORINGSSL_HAS_UINT128) +#include "p256_64.h" +#elif defined(OPENSSL_64_BIT) +#include "p256_64_msvc.h" +#else +#include "p256_field_32.br.c.inc" +#include "p256_32.h" +// the 32-bit Bedrock-generated field halving calls Fiat-C code for add, sub +static inline void p256_coord_add(br_word_t out, br_word_t x, br_word_t y) { + fiat_p256_add((uint32_t*)out, (const uint32_t*)x, (const uint32_t*)y); +} +static inline void p256_coord_sub(br_word_t out, br_word_t x, br_word_t y) { + fiat_p256_sub((uint32_t*)out, (const uint32_t*)x, (const uint32_t*)y); +} +#endif + +// the Bedrock-generated point operations call Fiat-C or Fiat-x86 mul, sqr +static inline void p256_coord_mul(br_word_t out, br_word_t x, br_word_t y) { + fiat_p256_mul((br_word_t*)out, (const br_word_t*)x, (const br_word_t*)y); +} +static inline void p256_coord_sqr(br_word_t out, br_word_t x) { + fiat_p256_square((br_word_t*)out, (const br_word_t*)x); +} diff --git a/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_field_32.br.c.inc b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_field_32.br.c.inc new file mode 100644 index 0000000000..4fe7c1a380 --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_field_32.br.c.inc @@ -0,0 +1,73 @@ +// Generated from Bedrock code in Fiat Cryptography. Avoid editing directly. + +static inline br_word_t shrd(br_word_t lo, br_word_t hi, br_word_t n) { + br_word_t res; + res = lo>>(n&(sizeof(br_word_t)*8-1)); + if (n) { + res = (hi<<((((((0u-(br_word_t)1)>>27)&63)+1)-n)&(sizeof(br_word_t)*8-1)))|res; + } else { + /*skip*/ + } + return res; +} + +static inline br_word_t p256_coord_nonzero(br_word_t p_x) { + br_word_t nz; + nz = (((_br_load(p_x))|(_br_load(p_x+4)))|(_br_load((p_x+4)+4)))|(_br_load(((p_x+4)+4)+4)); + nz = nz|(_br_load((((p_x+4)+4)+4)+4)); + nz = nz|(_br_load(((((p_x+4)+4)+4)+4)+4)); + nz = nz|(_br_load((((((p_x+4)+4)+4)+4)+4)+4)); + nz = nz|(_br_load(((((((p_x+4)+4)+4)+4)+4)+4)+4)); + nz = br_broadcast_nonzero(nz); + return nz; +} + +static inline void u256_shr(br_word_t p_out, br_word_t p_x, br_word_t n) { + br_word_t x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7; + x0 = _br_load(p_x); + x1 = _br_load(p_x+4); + x2 = _br_load((p_x+4)+4); + x3 = _br_load(((p_x+4)+4)+4); + x4 = _br_load((((p_x+4)+4)+4)+4); + x5 = _br_load(((((p_x+4)+4)+4)+4)+4); + x6 = _br_load((((((p_x+4)+4)+4)+4)+4)+4); + x7 = _br_load(((((((p_x+4)+4)+4)+4)+4)+4)+4); + y0 = shrd(x0, x1, n); + y1 = shrd(x1, x2, n); + y2 = shrd(x2, x3, n); + y3 = shrd(x3, x4, n); + y4 = shrd(x4, x5, n); + y5 = shrd(x5, x6, n); + y6 = shrd(x6, x7, n); + y7 = x7>>(n&(sizeof(br_word_t)*8-1)); + _br_store(p_out, y0); + _br_store(p_out+4, y1); + _br_store((p_out+4)+4, y2); + _br_store(((p_out+4)+4)+4, y3); + _br_store((((p_out+4)+4)+4)+4, y4); + _br_store(((((p_out+4)+4)+4)+4)+4, y5); + _br_store((((((p_out+4)+4)+4)+4)+4)+4, y6); + _br_store(((((((p_out+4)+4)+4)+4)+4)+4)+4, y7); + return; +} + +static inline void u256_set_p256_minushalf_conditional(br_word_t p_out, br_word_t mask) { + br_word_t mh0, mh1, mh2, mh3, mh4, mh5, mh6, mh7; + mh0 = 0u-(br_word_t)1; + mh1 = mh0; + mh2 = mh0>>1; + mh3 = (br_word_t)0; + mh4 = (br_word_t)0; + mh5 = (br_word_t)1<<31; + mh6 = mh5; + mh7 = mh2; + _br_store(p_out, mask&mh0); + _br_store(p_out+4, mask&mh1); + _br_store((p_out+4)+4, mask&mh2); + _br_store(((p_out+4)+4)+4, mask&mh3); + _br_store((((p_out+4)+4)+4)+4, mask&mh4); + _br_store(((((p_out+4)+4)+4)+4)+4, mask&mh5); + _br_store((((((p_out+4)+4)+4)+4)+4)+4, mask&mh6); + _br_store(((((((p_out+4)+4)+4)+4)+4)+4)+4, mask&mh7); + return; +} diff --git a/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_field_64.br.c.inc b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_field_64.br.c.inc new file mode 100644 index 0000000000..756d237349 --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_field_64.br.c.inc @@ -0,0 +1,88 @@ +// Generated from Bedrock code in Fiat Cryptography. Avoid editing directly. + +static inline br_word_t shrd(br_word_t lo, br_word_t hi, br_word_t n) { + br_word_t res; + res = lo>>(n&(sizeof(br_word_t)*8-1)); + if (n) { + res = (hi<<((((((0u-(br_word_t)1)>>27)&63)+1)-n)&(sizeof(br_word_t)*8-1)))|res; + } else { + /*skip*/ + } + return res; +} + +static inline void p256_coord_add(br_word_t p_out, br_word_t p_x, br_word_t p_y) { + br_word_t r4, carry, t0, t1, t2, borrow, t3, r0, r1, r2, r3; + carry = br_full_add(_br_load(p_x), _br_load(p_y), (br_word_t)0, &t0); + carry = br_full_add(_br_load(p_x+8), _br_load(p_y+8), carry, &t1); + carry = br_full_add(_br_load((p_x+8)+8), _br_load((p_y+8)+8), carry, &t2); + carry = br_full_add(_br_load(((p_x+8)+8)+8), _br_load(((p_y+8)+8)+8), carry, &t3); + borrow = br_full_sub(t0, (br_word_t)0xffffffffffffffff, (br_word_t)0, &r0); + borrow = br_full_sub(t1, (br_word_t)0xffffffff, borrow, &r1); + borrow = br_full_sub(t2, (br_word_t)0, borrow, &r2); + borrow = br_full_sub(t3, (br_word_t)0xffffffff00000001, borrow, &r3); + borrow = br_full_sub(carry, (br_word_t)0, borrow, &r4); + r0 = br_cmov(borrow, t0, r0); + r1 = br_cmov(borrow, t1, r1); + r2 = br_cmov(borrow, t2, r2); + r3 = br_cmov(borrow, t3, r3); + _br_store(p_out, r0); + _br_store(p_out+8, r1); + _br_store((p_out+8)+8, r2); + _br_store(((p_out+8)+8)+8, r3); + return; +} + +static inline void p256_coord_sub(br_word_t out, br_word_t x, br_word_t y) { + br_word_t borrow, t0, t1, t2, t3, mask, carry, r0, r1, r2, r3; + borrow = br_full_sub(_br_load(x), _br_load(y), (br_word_t)0, &t0); + borrow = br_full_sub(_br_load(x+8), _br_load(y+8), borrow, &t1); + borrow = br_full_sub(_br_load((x+8)+8), _br_load((y+8)+8), borrow, &t2); + borrow = br_full_sub(_br_load(((x+8)+8)+8), _br_load(((y+8)+8)+8), borrow, &t3); + mask = br_value_barrier(0u-borrow); + carry = br_full_add(t0, mask, (br_word_t)0, &r0); + carry = br_full_add(t1, mask&0xffffffff, carry, &r1); + carry = br_full_add(t2, (br_word_t)0, carry, &r2); + carry = br_full_add(t3, mask&0xffffffff00000001, carry, &r3); + _br_store(out, r0); + _br_store(out+8, r1); + _br_store((out+8)+8, r2); + _br_store(((out+8)+8)+8, r3); + return; +} + +static inline br_word_t p256_coord_nonzero(br_word_t p_x) { + br_word_t nz; + nz = br_broadcast_nonzero((((_br_load(p_x))|(_br_load(p_x+8)))|(_br_load((p_x+8)+8)))|(_br_load(((p_x+8)+8)+8))); + return nz; +} + +static inline void u256_shr(br_word_t p_out, br_word_t p_x, br_word_t n) { + br_word_t x0, x1, x2, x3, y0, y1, y2, y3; + x0 = _br_load(p_x); + x1 = _br_load(p_x+8); + x2 = _br_load((p_x+8)+8); + x3 = _br_load(((p_x+8)+8)+8); + y0 = shrd(x0, x1, n); + y1 = shrd(x1, x2, n); + y2 = shrd(x2, x3, n); + y3 = x3>>(n&(sizeof(br_word_t)*8-1)); + _br_store(p_out, y0); + _br_store(p_out+8, y1); + _br_store((p_out+8)+8, y2); + _br_store(((p_out+8)+8)+8, y3); + return; +} + +static inline void u256_set_p256_minushalf_conditional(br_word_t p_out, br_word_t mask) { + br_word_t mh0, mh1, mh2, mh3; + mh0 = 0u-(br_word_t)1; + mh1 = mh0>>((br_word_t)33&(sizeof(br_word_t)*8-1)); + mh2 = mh0<<((br_word_t)63&(sizeof(br_word_t)*8-1)); + mh3 = (mh0<<((br_word_t)32&(sizeof(br_word_t)*8-1)))>>1; + _br_store(p_out, mask&mh0); + _br_store(p_out+8, mask&mh1); + _br_store((p_out+8)+8, mask&mh2); + _br_store(((p_out+8)+8)+8, mask&mh3); + return; +} diff --git a/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_point.br.c.inc b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_point.br.c.inc new file mode 100644 index 0000000000..84c873a4eb --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/p256_point.br.c.inc @@ -0,0 +1,115 @@ +// Generated from Bedrock code in Fiat Cryptography. Avoid editing directly. + +static inline br_word_t br_broadcast_odd(br_word_t x) { + br_word_t y; + x = br_value_barrier(x&1); + y = 0u-x; + return y; +} + +static inline void p256_coord_halve(br_word_t y, br_word_t x) { + br_word_t m, mmh; + uint8_t _br_stackalloc_mmh[32] = {0}; mmh = (br_word_t)&_br_stackalloc_mmh; + m = br_broadcast_odd(_br_load(x)); + u256_set_p256_minushalf_conditional(mmh, m); + u256_shr(y, x, (br_word_t)1); + p256_coord_sub(y, y, mmh); + return; +} + +static inline br_word_t p256_point_iszero(br_word_t p_P) { + br_word_t z, nz; + nz = p256_coord_nonzero((p_P+32)+32); + z = ~nz; + return z; +} + +static inline void p256_point_double(br_word_t out, br_word_t in1) { + br_word_t t2, tmp, A, D; + uint8_t _br_stackalloc_D[32] = {0}; D = (br_word_t)&_br_stackalloc_D; + uint8_t _br_stackalloc_A[32] = {0}; A = (br_word_t)&_br_stackalloc_A; + uint8_t _br_stackalloc_tmp[32] = {0}; tmp = (br_word_t)&_br_stackalloc_tmp; + p256_coord_add(D, in1+32, in1+32); + p256_coord_sqr(tmp, (in1+32)+32); + p256_coord_sqr(D, D); + p256_coord_mul((out+32)+32, (in1+32)+32, in1+32); + p256_coord_add((out+32)+32, (out+32)+32, (out+32)+32); + p256_coord_add(A, in1, tmp); + p256_coord_sub(tmp, in1, tmp); + uint8_t _br_stackalloc_t2[32] = {0}; t2 = (br_word_t)&_br_stackalloc_t2; + p256_coord_add(t2, tmp, tmp); + p256_coord_add(tmp, t2, tmp); + p256_coord_sqr(out+32, D); + p256_coord_mul(A, A, tmp); + p256_coord_mul(D, D, in1); + p256_coord_sqr(out, A); + p256_coord_add(tmp, D, D); + p256_coord_sub(out, out, tmp); + p256_coord_sub(D, D, out); + p256_coord_mul(D, D, A); + p256_coord_halve(out+32, out+32); + p256_coord_sub(out+32, D, out+32); + return; +} + +static inline br_word_t p256_point_add_nz_nz_neq(br_word_t p_out, br_word_t p_P, br_word_t p_Q) { + br_word_t z1z1, z2z2, u1, Hsqr, ok, different_x, different_y, u2, Hcub, s1, r, h, s2; + uint8_t _br_stackalloc_z1z1[32] = {0}; z1z1 = (br_word_t)&_br_stackalloc_z1z1; + uint8_t _br_stackalloc_z2z2[32] = {0}; z2z2 = (br_word_t)&_br_stackalloc_z2z2; + uint8_t _br_stackalloc_u1[32] = {0}; u1 = (br_word_t)&_br_stackalloc_u1; + uint8_t _br_stackalloc_u2[32] = {0}; u2 = (br_word_t)&_br_stackalloc_u2; + uint8_t _br_stackalloc_h[32] = {0}; h = (br_word_t)&_br_stackalloc_h; + uint8_t _br_stackalloc_s1[32] = {0}; s1 = (br_word_t)&_br_stackalloc_s1; + uint8_t _br_stackalloc_s2[32] = {0}; s2 = (br_word_t)&_br_stackalloc_s2; + uint8_t _br_stackalloc_r[32] = {0}; r = (br_word_t)&_br_stackalloc_r; + uint8_t _br_stackalloc_Hsqr[32] = {0}; Hsqr = (br_word_t)&_br_stackalloc_Hsqr; + uint8_t _br_stackalloc_Hcub[32] = {0}; Hcub = (br_word_t)&_br_stackalloc_Hcub; + p256_coord_sqr(z1z1, (p_P+32)+32); + p256_coord_mul(u2, p_Q, z1z1); + p256_coord_sqr(z2z2, (p_Q+32)+32); + p256_coord_mul(u1, p_P, z2z2); + p256_coord_sub(h, u2, u1); + p256_coord_mul(s2, (p_P+32)+32, z1z1); + p256_coord_mul((p_out+32)+32, h, (p_P+32)+32); + p256_coord_mul((p_out+32)+32, (p_out+32)+32, (p_Q+32)+32); + p256_coord_mul(s2, s2, p_Q+32); + p256_coord_mul(s1, (p_Q+32)+32, z2z2); + p256_coord_mul(s1, s1, p_P+32); + p256_coord_sub(r, s2, s1); + p256_coord_sqr(Hsqr, h); + p256_coord_sqr(p_out, r); + p256_coord_mul(Hcub, Hsqr, h); + p256_coord_mul(u2, u1, Hsqr); + different_x = p256_coord_nonzero(Hcub); + different_y = p256_coord_nonzero(p_out); + ok = br_value_barrier(different_x|different_y); + p256_coord_sub(p_out, p_out, Hcub); + p256_coord_sub(p_out, p_out, u2); + p256_coord_sub(p_out, p_out, u2); + p256_coord_sub(h, u2, p_out); + p256_coord_mul(s2, Hcub, s1); + p256_coord_mul(h, h, r); + p256_coord_sub(p_out+32, h, s2); + return ok; +} + +static inline void p256_point_add_vartime_if_doubling(br_word_t p_out, br_word_t p_P, br_word_t p_Q) { + br_word_t p_tmp, zeroP, zeroQ, ok, p_sel; + zeroP = p256_point_iszero(p_P); + zeroQ = p256_point_iszero(p_Q); + uint8_t _br_stackalloc_p_tmp[96] = {0}; p_tmp = (br_word_t)&_br_stackalloc_p_tmp; + ok = p256_point_add_nz_nz_neq(p_tmp, p_P, p_Q); + ok = br_declassify((zeroP|zeroQ)|ok); + uint8_t _br_stackalloc_p_sel[96] = {0}; p_sel = (br_word_t)&_br_stackalloc_p_sel; + br_memset(p_sel, (br_word_t)0, (br_word_t)96); + br_memcxor(p_sel, p_tmp, (br_word_t)96, (~zeroP)&(~zeroQ)); + br_memcxor(p_sel, p_P, (br_word_t)96, (~zeroP)&zeroQ); + br_memcxor(p_sel, p_Q, (br_word_t)96, zeroP&(~zeroQ)); + if (ok) { + /*skip*/ + } else { + p256_point_double(p_sel, p_P); + } + br_memcpy(p_out, p_sel, (br_word_t)96); + return; +} diff --git a/naiveproxy/src/third_party/brotli/README.chromium b/naiveproxy/src/third_party/brotli/README.chromium index 50f78e0c38..929ebad789 100644 --- a/naiveproxy/src/third_party/brotli/README.chromium +++ b/naiveproxy/src/third_party/brotli/README.chromium @@ -7,6 +7,7 @@ License: MIT License File: LICENSE Security Critical: yes Shipped: yes +CPEPrefix: cpe:/a:google:brotli Description: Brotli is a generic byte-level compression algorithm that is used at the diff --git a/naiveproxy/src/third_party/compiler-rt/src/lib/builtins/assembly.h b/naiveproxy/src/third_party/compiler-rt/src/lib/builtins/assembly.h index 714bcd4d5c..89372f18c8 100644 --- a/naiveproxy/src/third_party/compiler-rt/src/lib/builtins/assembly.h +++ b/naiveproxy/src/third_party/compiler-rt/src/lib/builtins/assembly.h @@ -205,6 +205,12 @@ #define PACBTI_LANDING #endif +#if defined(__ARM_FEATURE_PAUTH) +#define PAC_RETURN bxaut r12, lr, sp +#else +#define PAC_RETURN aut r12, lr, sp SEPARATOR bx lr +#endif + #else // !defined(__arm) #define DECLARE_FUNC_ENCODING #define DEFINE_CODE_STATE diff --git a/naiveproxy/src/third_party/googletest/BUILD.gn b/naiveproxy/src/third_party/googletest/BUILD.gn index 083cf7a8e9..7a792a60e7 100644 --- a/naiveproxy/src/third_party/googletest/BUILD.gn +++ b/naiveproxy/src/third_party/googletest/BUILD.gn @@ -129,7 +129,7 @@ source_set("gtest") { # googletest only needs `absl`, but this makes gn check happier. deps = [ "//third_party/abseil-cpp:absl_full" ] - if (is_nacl || !build_with_chromium) { + if (!build_with_chromium) { defines += [ "GTEST_DISABLE_PRINT_STACK_TRACE" ] sources -= [ "custom/gtest/internal/custom/stack_trace_getter.cc", diff --git a/naiveproxy/src/third_party/jni_zero/BUILD.gn b/naiveproxy/src/third_party/jni_zero/BUILD.gn index a5817ae9b2..87ac540172 100644 --- a/naiveproxy/src/third_party/jni_zero/BUILD.gn +++ b/naiveproxy/src/third_party/jni_zero/BUILD.gn @@ -36,6 +36,10 @@ component("jni_zero") { ] configs += [ ":jni_include_dir" ] + # TODO(crbug.com/40031409): Fix code that adds exit-time destructors and + # enable the diagnostic by removing this line. + configs += [ "//build/config/compiler:no_exit_time_destructors" ] + defines = [] if (enable_jni_multiplexing) { defines += [ "JNI_ZERO_MULTIPLEXING_ENABLED" ] diff --git a/naiveproxy/src/third_party/jni_zero/README.md b/naiveproxy/src/third_party/jni_zero/README.md index 461609fac1..2b6e41be32 100644 --- a/naiveproxy/src/third_party/jni_zero/README.md +++ b/naiveproxy/src/third_party/jni_zero/README.md @@ -16,11 +16,7 @@ JNI Zero generates boiler-plate code with the goal of making our code: 3. more optimizable. JNI Zero uses regular expressions to parse .java files, so don't do -anything too fancy. E.g.: - * Classes must be either explicitly imported, or are assumed to be in -the same package. To use `java.lang` classes, add an explicit import. - * Inner classes need to be referenced through the outer class. E.g.: - `void call(Outer.Inner inner)` +anything too fancy :). ### Exposing Native Methods @@ -42,30 +38,6 @@ functions can be put into a namespace using `@JNINamespace("your_namespace")`. ## Usage -### Writing Build Rules -1. Find or add a `generate_jni` target with your .java file, then add this - `generate_jni` target to your `srcjar_deps` of your `android_library` target: - - ```python - generate_jni("abcd_jni") { - sources = [ "path/to/java/sources/with/jni/Annotations.java" ] - } - - android_library("abcd_java") { - ... - # Allows the java files to see the generated `${OriginalClassName}Jni` - # classes. - srcjar_deps = [ ":abcd_jni" ] - } - - source_set("abcd") { - ... - # Allows the cpp files to include the generated `${OriginalClassName}_jni.h` - # headers. - deps = [ ":abcd_jni" ] - } - ``` - ### Calling Java -> Native - For each JNI method: @@ -82,18 +54,20 @@ To add JNI to a class: 1. Create a nested-interface annotated with `@NativeMethods` that contains the declaration of the corresponding static methods you wish to have implemented. -2. Call native functions using `${OriginalClassName}Jni.get().${method}` +2. Call native functions using `${OriginalClassName}Jni.get().${method}()` 3. In C++ code, #include the header `${OriginalClassName}_jni.h`. (The path will depend on the location of the `generate_jni` BUILD rule that lists your Java - source code.) Only include this header from a single `.cc` file as the - header defines functions. That `.cc` must implement your native code by - defining non-member functions named `JNI_${OriginalClassName}_${UpperCamelCaseMethod}` - for static methods and member functions named `${OriginalClassName}::${UpperCamelCaseMethod}` - for non-static methods. Member functions need be declared in the header - file as well. + source code.) -Example: -#### Java +Note: Include this header from only a single `.cc` file as the header defines +functions. That `.cc` must implement your native code by defining non-member +functions named `JNI_${OriginalClassName}_${UpperCamelCaseMethod}` for static +methods and member functions named +`${OriginalClassName}::${UpperCamelCaseMethod}` for non-static methods. Member +functions need be declared in the header file as well. + +#### Example: +**Java** ```java class MyClass { // Cannot be private. Must be package or public. @@ -122,7 +96,8 @@ class MyClass { } } ``` -#### C++ + +**C++** ```c++ #include "third_party/jni_zero/jni_zero.h" #include "//MyClass_jni.h" @@ -143,11 +118,6 @@ void MyClass::NonStatic(JNIEnv* env) { ... } ### Calling Native -> Java -Because the generated header files contain definitions as well as declarations, -the must not be `#included` by multiple sources. If there are Java functions -that need to be called by multiple sources, one source should be chosen to -expose the functions to the others via additional wrapper functions. - 1. Annotate some methods with `@CalledByNative`, the generator will now generate stubs in `${OriginalClassName}_jni.h` header to call into those java methods from cpp. @@ -162,11 +132,39 @@ expose the functions to the others via additional wrapper functions. Note: For test-only methods, use `@CalledByNativeForTesting` which will ensure that it is stripped in our release binaries. +Note: Because the generated header files contain definitions as well as declarations, +they must not be `#included` by multiple sources. If there are Java functions +that need to be called by multiple sources, one source should be chosen to +expose the functions to the others via additional wrapper functions. + +### Writing Build Rules +1. Find or add a `generate_jni` target with your .java file, then add its `_java` + subtarget to your `deps`. + + ```python + generate_jni("abcd_jni") { + sources = [ "path/to/java/sources/with/jni/Annotations.java" ] + } + + android_library("abcd_java") { + ... + # For the generated `${OriginalClassName}Jni` classes. + deps = [ ":abcd_jni_java" ] + } + + source_set("abcd") { + ... + # Allows the cpp files to include the generated `${OriginalClassName}_jni.h` + # headers. + deps = [ ":abcd_jni" ] + } + ``` + ### Automatic Type Conversions using @JniType -Normally, Java types map to C++ types from `` (e.g. `jstring` for -`java.lang.String`). The first thing most people do is convert the jni spec -types into standard C++ types. +Normally, Java types map to C++ types from `` (`jobject` for +reference types, `jint` for `int`, etc). The first thing most people do is +convert the jni spec types into standard C++ types. `@JniType` to the rescue. By annotating a parameter or a return type with `@JniType("cpp_type_here")` the generated code will automatically convert from @@ -190,7 +188,7 @@ class MyClass { #include "third_party/jni_zero/jni_zero.h" #include "//MyClass_jni.h" -void JNI_MyClass_Foo(JNIEnv* env, const JavaParamRef&, const JavaParamRef&, const JavaParamRef&, JavaParamRef&) {...} +void JNI_MyClass_Foo(JNIEnv* env, const JavaRef&, const JavaRef&, const JavaRef&, JavaRef&) {...} ``` #### After using `@JniType` @@ -216,19 +214,19 @@ void JNI_MyClass_Foo(JNIEnv* env, std::string&, std::vector>&, myMo #### Implementing Conversion Functions Conversion functions must be defined for all types that appear in `@JniType`. -Forgetting to add one will result in errors at link time. +Forgetting to `#include` the header that defines it will will result in a +compile error. ```c++ // The conversion function primary templates. template O FromJniType(JNIEnv*, const JavaRef&); template -O FromJniType(JNIEnv*, const JavaRef&); -template ScopedJavaLocalRef ToJniType(JNIEnv*, const O&); ``` An example conversion function can look like: + ```c++ #include "third_party/jni_zero/jni_zero.h" @@ -249,9 +247,6 @@ EXPORT ScopedJavaLocalRef ToJniType( } // namespace jni_zero ``` -If a conversion function is missing, you will get a linker error since we -forward declare the conversion functions before using them. - #### Array Conversion Functions Array conversion functions look different due to the partial specializations. @@ -277,9 +272,8 @@ and thus cannot be `nullptr`. This means some conversion functions that return non-nullable types have to handle the situation where the passed in java type is null. -You can get around this by having the conversion be to `std::optional` rather -than just `T` if `T` is not a nullable type. - +JNI Zero defines conversions functions for `std::optional` that will treat +`nullptr` as missing. ### Testing Mockable Natives @@ -312,9 +306,6 @@ public class AnimationFrameTimeHistogramTest { } ``` -If a native method is called without setting a mock in a unit test, an -`UnsupportedOperationException` will be thrown. - ### Special case: APK Splits Each APK split with its own native library has its own generated `GEN_JNI`, which is `_GEN_JNI`. In order to get your split's JNI to use the `` prefix, you @@ -325,58 +316,46 @@ your `Natives` interface with `@NativeMethods("test_module")`, and this would result in `test_module_GEN_JNI`. -### Testing for readiness: use `get()` +### How to Know if Native is Loaded? -JNI Generator automatically produces asserts that verify that the Natives interface can be safely -called. These checks are compiled out of Release builds, making these an excellent way to determine -whether your code is called safely. +You must call `System.loadLibrary("libname")` before making JNI calls, and it +is up to each application to do so. Using an app's `Application` subclass is a +good place to do this. -It is not sufficient, however, to use `Jni.get()` to guarantee native is initialized - it is -only a debugging tool to ensure that you're using native after native is loaded. +#### Chrome-specific Guidance -If you expect your code to be called by an external caller, it's often helpful to know _ahead of -time_ that the context is valid (ie. either native libraries are loaded or mocks are installed). -In this case it is helpful to call `get()` method, that performs all the Debug checks listed -above, but does not instantiate a new object for interfacing Native libraries. -Note that the unused value returned by the `get()` method will be optimized away in release builds -so there's no harm in ignoring it. + * Be careful of logic in early initialization where native has not yet been + loaded. + * For tests, JNI Zero's check to ensure that all C++ implementations of JNI + methods are included is disabled (due to too many violations). If you hit a + `UnsatisfiedLinkError`, it's likely that you are missing a `deps` entry onto + the code that implements that C++ side of a JNI method. -#### Addressing `Jni.get()` exceptions. - -When you identify a scenario leading to an exception, relocate (or defer) the appropriate call to +When you hit a scenario leading to an exception, relocate (or defer) the appropriate call to be made to a place where (or time when) you know the native libraries have been initialized (eg. `onStartWithNative`, `onNativeInitialized` etc). -Please avoid calling `LibraryLoader.isInitialized()` / `LibraryLoader.isLoaded()` in new code. -Using `LibraryLoader` calls makes unit-testing more difficult: -* this call can not verify whether Mock object is used, making the use of mocks more complicated, -* using `LibraryLoader.setLibrariesLoadedForNativeTests()` alters the state for subsequently -executed tests, inaccurately reporting flakiness and failures of these victim tests. -* Introducing `LibraryLoader.is*()` calls in your code immediately affects all callers, forcing -the authors of the code up the call stack to override `LibraryLoader` internal state in order to be -able to unit-test their code. +Avoid calling `LibraryLoader.isInitialized()` / `LibraryLoader.isLoaded()`, +because the tell you only whether `System.loadLibray()` has been called, and +often return "true" in Robolectric tests, which contain only a small number of +JNI methods. -However, if your code is going to be called both before and after native is initialized, you are -forced to call `LibraryLoader.isInitialized()` to be able to differentiate. Calling -`Jni.get()` only provides assertions, and will fail in debug builds if you call it when -native isn't ready. +One robust solution is to use your own "`sIsNativeReady`" flag that is set via +a `@CalledByNative` method. ### Java Objects and Garbage Collection All pointers to Java objects must be registered with JNI in order to prevent garbage collection from invalidating them. -For Strings & Arrays - it's common practice to use the `//base/android/jni_*` -helpers to convert them to `std::vectors` and `std::strings` as soon as -possible. - For other objects - use smart pointers to store them: * `ScopedJavaLocalRef<>` - When lifetime is the current function's scope. * `ScopedJavaGlobalRef<>` - When lifetime is longer than the current function's scope. - * `JavaObjectWeakGlobalRef<>` - Weak reference (do not prevent garbage + * `LeakedJavaGlobalRef<>` - For singletons (avoids having a destructor). + * `JavaObjectWeakGlobalRef<>` - Weak reference (does not prevent garbage collection). - * `JavaParamRef<>` - Use to accept any of the above as a parameter to a + * `JavaRef<>&` - Use to accept any of the above as a parameter to a function without creating a redundant registration. ### Additional Guidelines / Advice @@ -389,10 +368,6 @@ If a Java object "owns" a native one, store the pointer via `"long mNativeClassName"`. Ensure to eventually call a native method to delete the object. For example, have a `close()` that deletes the native object. -The best way to pass "compound" types across in either direction is to -create an inner class with PODs and a factory function. If possible, mark -all the fields as "final". - ## Build Rules * `generate_jni` - Given a set of Java files, generates a header file to call @@ -522,6 +497,18 @@ classes get the final switch numbers. These are modes which JNI provides currently, but we hope to remove. Please do not add any new uses of these. +#### Using the "native" Keyword + +E.g.: +``` +class Foo { + native someMethod(); +} +``` + +This is still supported by default, but is less efficient than `@NativeMethods` +interfaces. We plan to delete support for this. + #### Hashed Names This was our old release mode. `GEN_JNI` would call into `N`, just as it does for our current release mode, but instead of multipelxing, we'd just take a diff --git a/naiveproxy/src/third_party/jni_zero/codegen/called_by_native_header.py b/naiveproxy/src/third_party/jni_zero/codegen/called_by_native_header.py index d0a2bccf07..037d3ae786 100644 --- a/naiveproxy/src/third_party/jni_zero/codegen/called_by_native_header.py +++ b/naiveproxy/src/third_party/jni_zero/codegen/called_by_native_header.py @@ -139,5 +139,5 @@ def method_definition(sb, cbn): sb(f'{jobject_type} _ret2 = static_cast<{jobject_type}>(_ret);\n') with sb.statement(): - sb(f'return jni_zero::ScopedJavaLocalRef<{jobject_type}>(env, ' + sb(f'return jni_zero::ScopedJavaLocalRef<{jobject_type}>::Adopt(env, ' f'{return_rvalue})') diff --git a/naiveproxy/src/third_party/jni_zero/codegen/convert_type.py b/naiveproxy/src/third_party/jni_zero/codegen/convert_type.py index 22a1fc9667..fba3ac9fbd 100644 --- a/naiveproxy/src/third_party/jni_zero/codegen/convert_type.py +++ b/naiveproxy/src/third_party/jni_zero/codegen/convert_type.py @@ -93,9 +93,9 @@ def from_jni_expression(sb: common.StringBuilder, jtype = 'jobject' if release_ref: - rvalue = f'jni_zero::ScopedJavaLocalRef<{jtype}>(env, {rvalue})' + rvalue = f'jni_zero::ScopedJavaLocalRef<{jtype}>::Adopt(env, {rvalue})' else: - rvalue = f'jni_zero::JavaParamRef<{jtype}>(env, {rvalue})' + rvalue = f'jni_zero::JavaRef<{jtype}>::CreateLeaky(env, {rvalue})' if java_type.is_collection(): sb(f'jni_zero::FromJniCollection<{T}>') 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 2980233c63..0d73cf9371 100644 --- a/naiveproxy/src/third_party/jni_zero/codegen/natives_header.py +++ b/naiveproxy/src/third_party/jni_zero/codegen/natives_header.py @@ -16,7 +16,7 @@ def _return_type_cpp(java_type): return f'jni_zero::ScopedJavaLocalRef<{java_type.to_cpp()}>' -def _param_type_cpp(java_type, use_param_type): +def _param_type_cpp(java_type): if converted_type := java_type.converted_type: # Drop & when the type is obviously a pointer to avoid "const char *&". if not java_type.is_primitive() and not converted_type.endswith('*'): @@ -26,10 +26,7 @@ def _param_type_cpp(java_type, use_param_type): ret = java_type.to_cpp() if java_type.is_primitive(): return ret - if use_param_type: - return f'const jni_zero::JavaParamRef<{ret}>&' - else: - return f'const jni_zero::JavaRef<{ret}>&' + return f'const jni_zero::JavaRef<{ret}>&' def _impl_forward_declaration(sb, native, params): @@ -40,8 +37,8 @@ def _impl_forward_declaration(sb, native, params): with sb.param_list() as plist: plist.append('JNIEnv* env') if not native.static: - plist.append('const jni_zero::JavaParamRef& jcaller') - plist.extend(f'{_param_type_cpp(p.java_type, True)} {p.cpp_name()}' + plist.append('const jni_zero::JavaRef& jcaller') + plist.extend(f'{_param_type_cpp(p.java_type)} {p.cpp_name()}' for p in params) @@ -61,7 +58,7 @@ def _entry_point_example(sb, native): plist.append('JNIEnv* env') if not native.static: plist.append('const jni_zero::JavaRef& jcaller') - plist.extend(f'{_param_type_cpp(p.java_type, False)} {p.cpp_name()}' + plist.extend(f'{_param_type_cpp(p.java_type)} {p.cpp_name()}' for p in params) @@ -83,7 +80,7 @@ def _prep_param(sb, is_proxy, param): if is_proxy and java_type.to_cpp() != java_type.to_proxy().to_cpp(): # E.g. jobject -> jstring orig_name = f'static_cast<{java_type.to_cpp()}>({orig_name})' - return f'jni_zero::JavaParamRef<{java_type.to_cpp()}>(env, {orig_name})' + return f'jni_zero::JavaRef<{java_type.to_cpp()}>::CreateLeaky(env, {orig_name})' def entry_point_declaration(sb, jni_mode, jni_obj, native, gen_jni_class): @@ -148,7 +145,7 @@ def entry_point_method(sb, with sb.param_list() as plist: plist.append('env') if not native.static: - plist.append('jni_zero::JavaParamRef(env, jcaller)') + plist.append('jni_zero::JavaRef::CreateLeaky(env, jcaller)') plist.extend(param_rvalues) if return_type.is_void(): diff --git a/naiveproxy/src/third_party/jni_zero/common_apis.cc b/naiveproxy/src/third_party/jni_zero/common_apis.cc index bdd1b4555e..0c5569314b 100644 --- a/naiveproxy/src/third_party/jni_zero/common_apis.cc +++ b/naiveproxy/src/third_party/jni_zero/common_apis.cc @@ -61,7 +61,7 @@ ScopedJavaLocalRef MapGet(JNIEnv* env, return JNI_Map::Java_Map_get(env, map, key); } -ScopedJavaLocalRef MapSet(JNIEnv* env, +ScopedJavaLocalRef MapPut(JNIEnv* env, const JavaRef& map, const JavaRef& key, const JavaRef& value) { diff --git a/naiveproxy/src/third_party/jni_zero/common_apis.h b/naiveproxy/src/third_party/jni_zero/common_apis.h index 1a22c4b178..a9a28d7661 100644 --- a/naiveproxy/src/third_party/jni_zero/common_apis.h +++ b/naiveproxy/src/third_party/jni_zero/common_apis.h @@ -9,6 +9,7 @@ #include "third_party/jni_zero/java_refs.h" #include "third_party/jni_zero/jni_export.h" +#include "third_party/jni_zero/type_conversions.h" namespace jni_zero { // Wraps Collection.toArray(). @@ -34,20 +35,47 @@ JNI_ZERO_COMPONENT_BUILD_EXPORT ScopedJavaLocalRef ListSet( const JavaRef& list, jint idx, const JavaRef& value); +// Use ToJniType on the value. +template + requires(!internal::IsJavaRef) +inline ScopedJavaLocalRef ListSet(JNIEnv* env, + const JavaRef& list, + jint idx, + const V& value) { + return ListSet(env, list, idx, ToJniType(env, value)); +} JNI_ZERO_COMPONENT_BUILD_EXPORT void ListAdd(JNIEnv* env, const JavaRef& list, const JavaRef& value); +// Use ToJniType on the value. +template + requires(!internal::IsJavaRef) +inline ScopedJavaLocalRef ListAdd(JNIEnv* env, + const JavaRef& list, + const V& value) { + return ListAdd(env, list, ToJniType(env, value)); +} JNI_ZERO_COMPONENT_BUILD_EXPORT ScopedJavaLocalRef MapGet(JNIEnv* env, const JavaRef& map, const JavaRef& key); -JNI_ZERO_COMPONENT_BUILD_EXPORT ScopedJavaLocalRef SetMapAt( +JNI_ZERO_COMPONENT_BUILD_EXPORT ScopedJavaLocalRef MapPut( JNIEnv* env, const JavaRef& map, const JavaRef& key, const JavaRef& value); +// Use ToJniType on the key/value. +template + requires(!internal::IsJavaRef && !internal::IsJavaRef) +inline ScopedJavaLocalRef MapPut(JNIEnv* env, + const JavaRef& map, + const K& key, + const V& value) { + return MapPut(env, map, ToJniType(env, key), ToJniType(env, value)); +} + JNI_ZERO_COMPONENT_BUILD_EXPORT jint CollectionSize(JNIEnv* env, const JavaRef& collection); diff --git a/naiveproxy/src/third_party/jni_zero/default_conversions.cc b/naiveproxy/src/third_party/jni_zero/default_conversions.cc index bf316fd7d9..de2f1b7756 100644 --- a/naiveproxy/src/third_party/jni_zero/default_conversions.cc +++ b/naiveproxy/src/third_party/jni_zero/default_conversions.cc @@ -31,7 +31,7 @@ namespace jni_zero { CheckException(env); \ env->Set##J##ArrayRegion(arr, 0, array_jsize, \ reinterpret_cast(vec.data())); \ - return ScopedJavaLocalRef(env, arr); \ + return ScopedJavaLocalRef::Adopt(env, arr); \ } PRIMITIVE_ARRAY_CONVERSIONS(int64_t, jlong, Long) @@ -77,7 +77,7 @@ ScopedJavaLocalRef ToJniArray>( jbooleanArray j_array = env->NewBooleanArray(array_jsize); CheckException(env); env->SetBooleanArrayRegion(j_array, 0, array_jsize, arr.get()); - return ScopedJavaLocalRef(env, j_array); + return ScopedJavaLocalRef::Adopt(env, j_array); } } // namespace jni_zero #endif // JNI_ZERO_ENABLE_TYPE_CONVERSIONS diff --git a/naiveproxy/src/third_party/jni_zero/default_conversions.h b/naiveproxy/src/third_party/jni_zero/default_conversions.h index 62e962bb8e..8b21a08e3b 100644 --- a/naiveproxy/src/third_party/jni_zero/default_conversions.h +++ b/naiveproxy/src/third_party/jni_zero/default_conversions.h @@ -7,6 +7,7 @@ #include #include +#include #include #include "third_party/jni_zero/common_apis.h" @@ -62,9 +63,9 @@ inline ContainerType FromJniArray(JNIEnv* env, // Do not call FromJni for jobject->jobject. if constexpr (std::is_base_of_v, ElementType>) { if constexpr (has_push_back) { - ret.emplace_back(env, j_element); + ret.push_back(ElementType::Adopt(env, j_element)); } else if constexpr (has_insert) { - ret.emplace(env, j_element); + ret.insert(ElementType::Adopt(env, j_element)); } } else { auto element = ScopedJavaLocalRef::Adopt(env, j_element); @@ -99,7 +100,7 @@ ToJniArray(JNIEnv* env, const ContainerType& collection, jclass clazz) { } ++i; } - return ScopedJavaLocalRef(env, j_array); + return ScopedJavaLocalRef::Adopt(env, j_array); } #define DECLARE_PRIMITIVE_ARRAY_CONVERSIONS(T) \ diff --git a/naiveproxy/src/third_party/jni_zero/java_refs.cc b/naiveproxy/src/third_party/jni_zero/java_refs.cc index 9e288ccddb..25e01442eb 100644 --- a/naiveproxy/src/third_party/jni_zero/java_refs.cc +++ b/naiveproxy/src/third_party/jni_zero/java_refs.cc @@ -103,7 +103,7 @@ void ScopedJavaGlobalWeakRef::reset() { ScopedJavaLocalRef ScopedJavaGlobalWeakRef::get(JNIEnv* env) const { jobject real = obj_ ? real = env->NewLocalRef(obj_) : nullptr; - return ScopedJavaLocalRef(env, real); + return ScopedJavaLocalRef::Adopt(env, real); } void ScopedJavaGlobalWeakRef::Assign(const ScopedJavaGlobalWeakRef& other) { diff --git a/naiveproxy/src/third_party/jni_zero/java_refs.h b/naiveproxy/src/third_party/jni_zero/java_refs.h index 3a7eeb4956..b33463959b 100644 --- a/naiveproxy/src/third_party/jni_zero/java_refs.h +++ b/naiveproxy/src/third_party/jni_zero/java_refs.h @@ -9,14 +9,28 @@ #include +#include +#include #include #include #include "third_party/jni_zero/jni_export.h" #include "third_party/jni_zero/logging.h" +#if !defined(JNI_ZERO_ENABLE_COMPAT_API) && defined(WEBRTC_ANDROID) +#define JNI_ZERO_ENABLE_COMPAT_API 1 +#else +#define JNI_ZERO_ENABLE_COMPAT_API 0 +#endif + namespace jni_zero { +namespace internal { +template +concept IsJobject = + std::derived_from, std::remove_pointer_t>; +} + // 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. @@ -37,7 +51,8 @@ class JNI_ZERO_COMPONENT_BUILD_EXPORT ScopedJavaLocalFrame { }; // Forward declare the generic java reference template class. -template +template + requires internal::IsJobject class JavaRef; // Template specialization of JavaRef, which acts as the base class for all @@ -70,7 +85,15 @@ class JNI_ZERO_COMPONENT_BUILD_EXPORT JavaRef { // TODO(torne): replace usage and remove this. bool is_null() const { return obj_ == nullptr; } + // Create a JavaRef that is not automatically released. Used for JNI + // parameters (which should not be released). + static JavaRef CreateLeaky(JNIEnv* env, jobject obj) { + return JavaRef(env, obj); + } + +#if !JNI_ZERO_ENABLE_COMPAT_API protected: +#endif // Takes ownership of the |obj| reference passed; requires it to be a local // reference type. #if JNI_ZERO_DCHECK_IS_ON() @@ -80,6 +103,10 @@ class JNI_ZERO_COMPONENT_BUILD_EXPORT JavaRef { JavaRef(JNIEnv* env, jobject obj) : obj_(obj) {} #endif +#if JNI_ZERO_ENABLE_COMPAT_API + protected: +#endif + // Used for move semantics. obj_ must have been released first if non-null. void steal(JavaRef&& other) { obj_ = other.obj_; @@ -104,13 +131,14 @@ class JNI_ZERO_COMPONENT_BUILD_EXPORT JavaRef { }; // Forward declare the object array reader for the convenience function. -template +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 + requires internal::IsJobject class JavaRef : public JavaRef { public: constexpr JavaRef() {} @@ -127,44 +155,25 @@ class JavaRef : public JavaRef { // 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); } + // Create a JavaRef that is not automatically released. Used for JNI + // parameters (which should not be released). + static JavaRef CreateLeaky(JNIEnv* env, T obj) { + return JavaRef(env, obj); + } + +#if !JNI_ZERO_ENABLE_COMPAT_API protected: +#endif 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 use in new -// code. -// TODO(crbug.com/40425392): Remove all uses of JavaParamRef to use JavaRef -// instead. -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() {} - - 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 @@ -175,7 +184,7 @@ class JavaParamRef : public JavaRef { // 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 +template class ScopedJavaLocalRef : public JavaRef { public: // Take ownership of a bare jobject. This does not create a new reference. @@ -219,12 +228,6 @@ class ScopedJavaLocalRef : public JavaRef { 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. @@ -288,18 +291,18 @@ class ScopedJavaLocalRef : public JavaRef { // Alias for Release(). For use in templates when global refs are invalid. T ReleaseLocal() { return static_cast(JavaRef::ReleaseInternal()); } +#if !JNI_ZERO_ENABLE_COMPAT_API private: +#endif + ScopedJavaLocalRef(JNIEnv* env, T obj) : JavaRef(env, obj), env_(env) {} +#if JNI_ZERO_ENABLE_COMPAT_API + private: +#endif + // 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; @@ -313,7 +316,7 @@ class ScopedJavaLocalRef : public JavaRef { // 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 +template class ScopedJavaGlobalRef : public JavaRef { public: constexpr ScopedJavaGlobalRef() {} @@ -350,10 +353,6 @@ class ScopedJavaGlobalRef : public JavaRef { 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. @@ -396,19 +395,15 @@ class ScopedJavaGlobalRef : public JavaRef { template >> void Reset(const ScopedJavaGlobalRef& other) { - Reset(nullptr, other.obj()); + Reset(nullptr, other); } - void Reset(const JavaRef& other) { Reset(nullptr, other.obj()); } + void Reset(const JavaRef& other) { Reset(nullptr, other); } - // Deprecated. You can just use Reset(const JavaRef&). - void Reset(JNIEnv* env, const JavaParamRef& other) { - Reset(env, other.obj()); + void Reset(JNIEnv* env, const JavaRef& other) { + JavaRef::SetNewGlobalRef(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. @@ -456,7 +451,7 @@ class JNI_ZERO_COMPONENT_BUILD_EXPORT ScopedJavaGlobalWeakRef { }; // A global JavaRef that will never be released. -template +template class JNI_ZERO_COMPONENT_BUILD_EXPORT LeakedJavaGlobalRef : public JavaRef { public: constexpr LeakedJavaGlobalRef() = default; @@ -481,6 +476,11 @@ class JNI_ZERO_COMPONENT_BUILD_EXPORT LeakedJavaGlobalRef : public JavaRef { env, static_cast(env->NewLocalRef(j_obj))); } }; + +// TODO(crbug.com/40425392): Remove this alias. +template +using JavaParamRef = JavaRef; + } // namespace jni_zero #endif // JNI_ZERO_JAVA_REFS_H_ diff --git a/naiveproxy/src/third_party/jni_zero/jni_wrappers.h b/naiveproxy/src/third_party/jni_zero/jni_wrappers.h index 232c827555..ac7207867b 100644 --- a/naiveproxy/src/third_party/jni_zero/jni_wrappers.h +++ b/naiveproxy/src/third_party/jni_zero/jni_wrappers.h @@ -9,6 +9,7 @@ #include +#include #include #include diff --git a/naiveproxy/src/third_party/jni_zero/jni_zero.cc b/naiveproxy/src/third_party/jni_zero/jni_zero.cc index 64207247f0..2f1849ec0c 100644 --- a/naiveproxy/src/third_party/jni_zero/jni_zero.cc +++ b/naiveproxy/src/third_party/jni_zero/jni_zero.cc @@ -44,13 +44,16 @@ jclass LazyGetClassInternal(JNIEnv* env, const char* split_name, std::atomic* atomic_class_id) { jclass ret = nullptr; - ScopedJavaGlobalRef clazz( + auto local_ref = ScopedJavaLocalRef::Adopt( env, GetClassInternal(env, class_name, split_name)); - if (atomic_class_id->compare_exchange_strong(ret, clazz.obj(), + jclass global_ref = static_cast(env->NewGlobalRef(local_ref.obj())); + if (atomic_class_id->compare_exchange_strong(ret, global_ref, std::memory_order_acq_rel)) { // We intentionally leak the global ref since we are now storing it as a raw // pointer in |atomic_class_id|. - ret = clazz.Release(); + ret = global_ref; + } else { + env->DeleteGlobalRef(global_ref); } return ret; } @@ -180,12 +183,13 @@ void SetClassResolver(jclass (*resolver)(JNIEnv*, const char*, const char*)) { ScopedJavaLocalRef GetClass(JNIEnv* env, const char* class_name, const char* split_name) { - return ScopedJavaLocalRef( + return ScopedJavaLocalRef::Adopt( env, GetClassInternal(env, class_name, split_name)); } ScopedJavaLocalRef GetClass(JNIEnv* env, const char* class_name) { - return ScopedJavaLocalRef(env, GetClassInternal(env, class_name, "")); + return ScopedJavaLocalRef::Adopt( + env, GetClassInternal(env, class_name, "")); } template diff --git a/naiveproxy/src/third_party/jni_zero/jni_zero_internal.h b/naiveproxy/src/third_party/jni_zero/jni_zero_internal.h index 89a3c91633..3da6a8a961 100644 --- a/naiveproxy/src/third_party/jni_zero/jni_zero_internal.h +++ b/naiveproxy/src/third_party/jni_zero/jni_zero_internal.h @@ -2,10 +2,16 @@ // 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/393091624): Remove this and convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + #ifndef JNI_ZERO_JNI_ZERO_INTERNAL_H #define JNI_ZERO_JNI_ZERO_INTERNAL_H #include +#include #include "third_party/jni_zero/default_conversions.h" #include "third_party/jni_zero/jni_export.h" diff --git a/naiveproxy/src/third_party/jni_zero/logging.cc b/naiveproxy/src/third_party/jni_zero/logging.cc index 362909ab76..6852296969 100644 --- a/naiveproxy/src/third_party/jni_zero/logging.cc +++ b/naiveproxy/src/third_party/jni_zero/logging.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/393091624): Remove this and convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + #include "third_party/jni_zero/logging.h" #include diff --git a/naiveproxy/src/third_party/jni_zero/logging.h b/naiveproxy/src/third_party/jni_zero/logging.h index a04f592ae4..d3f709eac3 100644 --- a/naiveproxy/src/third_party/jni_zero/logging.h +++ b/naiveproxy/src/third_party/jni_zero/logging.h @@ -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/393091624): Remove this and convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + // IWYU pragma: private, include "third_party/jni_zero/jni_zero.h" #ifndef JNI_ZERO_LOGGING_H_ diff --git a/naiveproxy/src/third_party/jni_zero/parse.py b/naiveproxy/src/third_party/jni_zero/parse.py index 9195137abe..731a007fdf 100644 --- a/naiveproxy/src/third_party/jni_zero/parse.py +++ b/naiveproxy/src/third_party/jni_zero/parse.py @@ -134,7 +134,9 @@ def _parse_java_classes(contents): package = _parse_package(contents).replace('.', '/') outer_class = None null_marked = False - nested_classes = [] + # Use a set to avoid duplicates, which can happen due to method-scoped + # classes (which JNI Zero would ideally ignore, but that's harder). + nested_classes = set() for m in _CLASSES_REGEX.finditer(contents): preamble, class_name = m.groups() # Ignore annotations like @Foo("contains the words class Bar") @@ -144,12 +146,12 @@ def _parse_java_classes(contents): outer_class = java_types.JavaClass(f'{package}/{class_name}') null_marked = contents.find('@NullMarked', 0, m.start(2)) != -1 else: - nested_classes.append(outer_class.make_nested(class_name)) + nested_classes.add(outer_class.make_nested(class_name)) if outer_class is None: raise ParseError('No classes found.') - return outer_class, nested_classes, null_marked + return outer_class, sorted(nested_classes), null_marked _ANNOTATION_REGEX = re.compile( diff --git a/naiveproxy/src/third_party/jni_zero/test/BUILD.gn b/naiveproxy/src/third_party/jni_zero/test/BUILD.gn index 75c3a2e737..03f33879c8 100644 --- a/naiveproxy/src/third_party/jni_zero/test/BUILD.gn +++ b/naiveproxy/src/third_party/jni_zero/test/BUILD.gn @@ -23,7 +23,6 @@ android_library("stubs_java") { } android_library("test_java") { - srcjar_deps = [ ":test_jni" ] sources = [ "java/src/org/jni_zero/NullMarked.java", "java/src/org/jni_zero/SampleForAnnotationProcessor.java", @@ -33,6 +32,7 @@ android_library("test_java") { deps = [ ":stubs_java", + ":test_jni_java", "//third_party/jni_zero:jni_zero_java", ] } 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 7f641e0730..b96af08369 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 @@ -49,6 +49,7 @@ class SampleForTests { } public void doStuff() { + class TestDuplicateClassName {} // This will call CPPClass::Method() using nativePtr as a pointer to the object. This must // be done to: // * avoid leaks. @@ -60,6 +61,7 @@ class SampleForTests { // private native void thisShouldNotExist(); public void finishExample() { + class TestDuplicateClassName {} // We're done, so let's destroy nativePtr object. SampleForTestsJni.get().destroy(mNativeCPPObject, this, new byte[0]); } diff --git a/naiveproxy/src/third_party/jni_zero/type_conversions.h b/naiveproxy/src/third_party/jni_zero/type_conversions.h index 69cd810731..5586f6bb69 100644 --- a/naiveproxy/src/third_party/jni_zero/type_conversions.h +++ b/naiveproxy/src/third_party/jni_zero/type_conversions.h @@ -67,7 +67,8 @@ concept IsPrimitive = std::is_arithmetic::value; template concept HasSpecificSpecialization = requires(T t) { - requires IsMap || IsObjectContainer || IsOptional || IsPrimitive; + requires IsMap || IsObjectContainer || IsOptional || + IsPrimitive || IsJavaRef; }; // Used to allow for the c++ type to be non-primitive even if the java type is @@ -111,6 +112,14 @@ inline ScopedJavaLocalRef ToJniType(JNIEnv* env, T obj) { static_assert(sizeof(T) == 0, JNI_ZERO_CONVERSION_FAILED_MSG("ToJniType")); } +template + requires(internal::IsJavaRef) +inline ScopedJavaLocalRef ToJniType(JNIEnv* env, const T& val) { + // Might want to change this to an identity function, but maybe it's useful + // for catching coding errors? + static_assert(sizeof(T) == 0, "Type does not require conversion."); +} + // 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. diff --git a/naiveproxy/src/third_party/libc++/src/.clang-format b/naiveproxy/src/third_party/libc++/src/.clang-format index fe2f2ef011..9557b955cd 100644 --- a/naiveproxy/src/third_party/libc++/src/.clang-format +++ b/naiveproxy/src/third_party/libc++/src/.clang-format @@ -16,8 +16,11 @@ AllowShortLambdasOnASingleLine: All AttributeMacros: [ '_ALIGNAS_TYPE', '_ALIGNAS', + '_LIBCPP_ACQUIRE_CAPABILITY', + '_LIBCPP_ACQUIRE_SHARED_CAPABILITY', '_LIBCPP_ALIGNOF', '_LIBCPP_ALWAYS_INLINE', + '_LIBCPP_CAPABILITY', '_LIBCPP_CONSTEXPR_SINCE_CXX14', '_LIBCPP_CONSTEXPR_SINCE_CXX17', '_LIBCPP_CONSTEXPR_SINCE_CXX20', @@ -30,6 +33,7 @@ AttributeMacros: [ '_LIBCPP_DEPRECATED_IN_CXX20', '_LIBCPP_DEPRECATED_IN_CXX23', '_LIBCPP_DEPRECATED', + '_LIBCPP_DIAGNOSE_NULLPTR_IF', '_LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION', '_LIBCPP_EXPORTED_FROM_ABI', '_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS', @@ -41,9 +45,13 @@ AttributeMacros: [ '_LIBCPP_NO_UNIQUE_ADDRESS', '_LIBCPP_NOALIAS', '_LIBCPP_OVERRIDABLE_FUNC_VIS', + '_LIBCPP_RELEASE_CAPABILITY', + '_LIBCPP_REQUIRES_CAPABILITY', + '_LIBCPP_SCOPED_LOCKABLE', '_LIBCPP_STANDALONE_DEBUG', '_LIBCPP_TEMPLATE_DATA_VIS', - '_LIBCPP_THREAD_SAFETY_ANNOTATION', + '_LIBCPP_TRY_ACQUIRE_CAPABILITY', + '_LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY', '_LIBCPP_USING_IF_EXISTS', '_LIBCPP_WEAK', ] diff --git a/naiveproxy/src/third_party/libc++/src/CMakeLists.txt b/naiveproxy/src/third_party/libc++/src/CMakeLists.txt index dffdd7a3c7..85514cc754 100644 --- a/naiveproxy/src/third_party/libc++/src/CMakeLists.txt +++ b/naiveproxy/src/third_party/libc++/src/CMakeLists.txt @@ -225,14 +225,6 @@ set(LIBCXX_ABI_DEFINES "" CACHE STRING "A semicolon separated list of ABI macros set(LIBCXX_EXTRA_SITE_DEFINES "" CACHE STRING "Extra defines to add into __config_site") option(LIBCXX_USE_COMPILER_RT "Use compiler-rt instead of libgcc" OFF) -# C Library options ----------------------------------------------------------- - -set(LIBCXX_SUPPORTED_C_LIBRARIES system llvm-libc) -set(LIBCXX_LIBC "system" CACHE STRING "Specify C library to use. Supported values are ${LIBCXX_SUPPORTED_C_LIBRARIES}.") -if (NOT "${LIBCXX_LIBC}" IN_LIST LIBCXX_SUPPORTED_C_LIBRARIES) - message(FATAL_ERROR "Unsupported C library: '${LIBCXX_LIBC}'. Supported values are ${LIBCXX_SUPPORTED_C_LIBRARIES}.") -endif() - # ABI Library options --------------------------------------------------------- if (MSVC) set(LIBCXX_DEFAULT_ABI_LIBRARY "vcruntime") diff --git a/naiveproxy/src/third_party/libc++/src/cmake/Modules/HandleLibC.cmake b/naiveproxy/src/third_party/libc++/src/cmake/Modules/HandleLibC.cmake deleted file mode 100644 index 1b0564ae6f..0000000000 --- a/naiveproxy/src/third_party/libc++/src/cmake/Modules/HandleLibC.cmake +++ /dev/null @@ -1,39 +0,0 @@ -#=============================================================================== -# Define targets for linking against the selected C library -# -# After including this file, the following targets are defined: -# - libcxx-libc-headers: An interface target that allows getting access to the -# headers of the selected C library. -# - libcxx-libc-shared: A target representing the selected shared C library. -# - libcxx-libc-static: A target representing the selected static C library. -#=============================================================================== - -# Link against a system-provided libc -if (LIBCXX_LIBC STREQUAL "system") - add_library(libcxx-libc-headers INTERFACE) - - add_library(libcxx-libc-static INTERFACE) - add_library(libcxx-libc-shared INTERFACE) - -# Link against the in-tree LLVM libc -elseif (LIBCXX_LIBC STREQUAL "llvm-libc") - add_library(libcxx-libc-headers INTERFACE) - target_link_libraries(libcxx-libc-headers INTERFACE libc-headers) - if(CXX_SUPPORTS_NOSTDLIBINC_FLAG) - target_compile_options(libcxx-libc-headers INTERFACE "-nostdlibinc") - endif() - - add_library(libcxx-libc-static INTERFACE) - if (TARGET libc) - target_link_libraries(libcxx-libc-static INTERFACE libc) - endif() - if (TARGET libm) - target_link_libraries(libcxx-libc-static INTERFACE libm) - endif() - if (CXX_SUPPORTS_NOLIBC_FLAG) - target_link_options(libcxx-libc-static INTERFACE "-nolibc") - endif() - - # TODO: There's no support for building LLVM libc as a shared library yet. - add_library(libcxx-libc-shared INTERFACE) -endif() diff --git a/naiveproxy/src/third_party/libc++/src/cmake/caches/AMDGPU.cmake b/naiveproxy/src/third_party/libc++/src/cmake/caches/AMDGPU.cmake index e7bf3f5389..5d09a1db8d 100644 --- a/naiveproxy/src/third_party/libc++/src/cmake/caches/AMDGPU.cmake +++ b/naiveproxy/src/third_party/libc++/src/cmake/caches/AMDGPU.cmake @@ -15,9 +15,9 @@ set(LIBCXX_ENABLE_UNICODE OFF CACHE BOOL "") set(LIBCXX_ENABLE_WIDE_CHARACTERS OFF CACHE BOOL "") set(LIBCXX_HAS_TERMINAL_AVAILABLE OFF CACHE BOOL "") set(LIBCXX_INSTALL_LIBRARY ON CACHE BOOL "") -set(LIBCXX_LIBC "llvm-libc" CACHE STRING "") set(LIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY ON CACHE BOOL "") set(LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") +set(RUNTIMES_USE_LIBC "llvm-libc" CACHE STRING "") # Configuration options for libcxxabi. set(LIBCXXABI_BAREMETAL ON CACHE BOOL "") diff --git a/naiveproxy/src/third_party/libc++/src/cmake/caches/AndroidNDK.cmake b/naiveproxy/src/third_party/libc++/src/cmake/caches/AndroidNDK.cmake index 298518781e..1a04b7fbb2 100644 --- a/naiveproxy/src/third_party/libc++/src/cmake/caches/AndroidNDK.cmake +++ b/naiveproxy/src/third_party/libc++/src/cmake/caches/AndroidNDK.cmake @@ -33,5 +33,5 @@ set(CMAKE_CXX_COMPILER_WORKS ON CACHE BOOL "") # Use adb to push tests to a locally-connected device (e.g. emulator) and run # them. -set(LIBCXX_TEST_CONFIG "llvm-libc++-android-ndk.cfg.in" CACHE STRING "") -set(LIBCXXABI_TEST_CONFIG "llvm-libc++abi-android-ndk.cfg.in" CACHE STRING "") +set(LIBCXX_TEST_CONFIG "llvm-libc++-android.cfg.in" CACHE STRING "") +set(LIBCXXABI_TEST_CONFIG "llvm-libc++abi-android.cfg.in" CACHE STRING "") diff --git a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-hardening-mode-extensive-observe-semantic.cmake b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-hardening-mode-extensive-observe-semantic.cmake new file mode 100644 index 0000000000..c843c02977 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-hardening-mode-extensive-observe-semantic.cmake @@ -0,0 +1,2 @@ +set(LIBCXX_HARDENING_MODE "extensive" CACHE STRING "") +set(LIBCXX_TEST_PARAMS "assertion_semantic=observe" CACHE STRING "") diff --git a/naiveproxy/src/third_party/libc++/src/cmake/caches/NVPTX.cmake b/naiveproxy/src/third_party/libc++/src/cmake/caches/NVPTX.cmake index 9ff02e3e08..46fa6e7a1b 100644 --- a/naiveproxy/src/third_party/libc++/src/cmake/caches/NVPTX.cmake +++ b/naiveproxy/src/third_party/libc++/src/cmake/caches/NVPTX.cmake @@ -15,9 +15,9 @@ set(LIBCXX_ENABLE_UNICODE OFF CACHE BOOL "") set(LIBCXX_ENABLE_WIDE_CHARACTERS OFF CACHE BOOL "") set(LIBCXX_HAS_TERMINAL_AVAILABLE OFF CACHE BOOL "") set(LIBCXX_INSTALL_LIBRARY ON CACHE BOOL "") -set(LIBCXX_LIBC "llvm-libc" CACHE STRING "") set(LIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY ON CACHE BOOL "") set(LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") +set(RUNTIMES_USE_LIBC "llvm-libc" CACHE STRING "") # Configuration options for libcxxabi. set(LIBCXXABI_BAREMETAL ON CACHE BOOL "") diff --git a/naiveproxy/src/third_party/libc++/src/docs/ABIGuarantees.rst b/naiveproxy/src/third_party/libc++/src/docs/ABIGuarantees.rst new file mode 100644 index 0000000000..c7d5afe108 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/docs/ABIGuarantees.rst @@ -0,0 +1,210 @@ +.. _ABIGuarantees: + +======================= +libc++'s ABI Guarantees +======================= + +libc++ provides multiple types of ABI guarantees. These include stability of the layout of structs, the linking of TUs +built against different versions and configurations of the library, and more. This document describes what guarantees +libc++ provides in these different areas as well as what options exist for vendors to affect these guarantees. + +Note that all of the guarantees listed below come with an asterisk that there may be circumstances where we deem it +worth it to break that guarantee. These breaks are communicated to vendors by CCing #libcxx-vendors on GitHub. If you +are a vendor, please ask to be added to that group to be notified about changes that potentially affect you. + +ABI flags +========= +All the ABI flags listed below can be added to the ``__config_site`` header by the vendor to opt in to an ABI breaking +change. These flags should never be set by the user. When porting libc++ to a new platform, vendord should consider +which flags to enable, assuming that ABI stability is relevant to them. Please contact the libc++ team on Discord or +through other means to be able to make an informed decision on which flags make sense to enable, and to avoid enabling +flags which may not be stable. Flags can be enabled via the ``LIBCXX_ABI_DEFINES`` CMake option. + + +Stability of the Layout of Structs +================================== + +The layout of any user-observable struct is kept stable across versions of the library and any user-facing options +documented :ref:`here `. There are a lot of structs that have internal names, but are none +the less observable by users; for example through public aliases to these types or because they affect the layout of +other types. + +There are multiple ABI flags which affect the layout of certain structs: + +``_LIBCPP_ABI_ALTERNATE_STRING_LAYOUT`` +--------------------------------------- +This changes the internal layout of ``basic_string`` to move the section that is used for the internal buffer to the +front, making it eight byte aligned instead of being unaligned, improving the performance of some operations +significantly. + +``_LIBCPP_ABI_NO_ITERATOR_BASES`` +--------------------------------- +This removes the ``iterator`` base class from ``back_insert_iterator``, ``front_insert_iterator``, ``insert_iterator``, +``istream_iterator``, ``ostream_iterator``, ``ostreambuf_iterator``, ``reverse_iterator``, and ``raw_storage_iterator``. +This doesn't directly affect the layout of these types in most cases, but may result in more padding being used when +they are used in combination, for example ``reverse_iterator>``. + +``_LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION`` +------------------------------------------------- +This changes the index type used inside ``variant`` to the smallest required type to reduce the datasize of variants in +most cases. + +``_LIBCPP_ABI_OPTIMIZED_FUNCTION`` +---------------------------------- +This significantly restructures how ``function`` is written to provide better performance, but is currently not ABI +stable. + +``_LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT`` +----------------------------------------------------- +This changes the layout of ``random_device`` to only holds state with 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 ``random_device``, one needs to retain the same object layout to remain ABI compatible. This flag +removes these workarounds for platforms that don't care about ABI compatibility. + +``_LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING`` +------------------------------------------ +This removes artificial padding from ``_LIBCPP_COMPRESSED_PAIR`` and ``_LIBCPP_COMPRESSED_TRIPLE``. + +These macros are used inside the associative and unordered containers, ``deque``, ``forward_list``, ``future``, +``list``, ``basic_string``, ``function``, ``shared_ptr``, ``unique_ptr``, and ``vector`` to stay ABI compatible with the +legacy ``__compressed_pair`` type. ``__compressed_pair`` had historically been used to reduce storage requirements in +the case of empty types, but has been replaced by ``[[no_unique_address]]``. ``[[no_unique_address]]`` is significantly +lighter in terms of compile time and debug information, and also improves the layout of structs further. However, to +keep ABI stability, the additional improvements in layout had to be reverted by introducing artificial padding. This +flag removes that artificial padding. + +``_LIBCPP_ABI_IOS_ALLOW_ARBITRARY_FILL_VALUE`` +---------------------------------------------- +``basic_ios`` uses ``WEOF`` to indicate that the fill value is uninitialized. However, on platforms where the size of +``char_type`` is equal to or greater than the size of ``int_type`` and ``char_type`` is unsigned, +``char_traits::eq_int_type()`` cannot distinguish between ``WEOF`` and ``WCHAR_MAX``. This flag changes +``basic_ios`` to instead track whether the fill value has been initialized using a separate boolean. + + +Linking TUs which have been compiled against different releases of libc++ +========================================================================= +libc++ supports linking TUs which have been compiled against different releases of libc++ by marking symbols with +hidden visibility and changing the mangling of header-only functions in every release. + + +Linking TUs which have been compiled with different flags affecting code gen +============================================================================ +There are a lot of compiler (and library) flags which change the code generated for functions. This includes flags like +``-O1``, which are guaranteed by the compiler to not change the observable behaviour of a correct program, as well as +flags like ``-fexceptions``, which **do** change the observable behaviour. libc++ allows linking of TUs which have been +compiled with specific flags only and makes no guarantees for any of the flags not listed below. + +The flags allowed (in any combination) are: +- ``-f[no-]exceptions`` +- ``-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE{_FAST,_EXTENSIVE,_DEBUG,_NONE}`` + +Note that this does not provide any guarantees about user-defined functions, but only that the libc++ functions linked +behave as the flags say. + + +Availability of symbols in the built library (both static and shared) +===================================================================== +In general, libc++ does not make any guarantees about forwards-compatibility. That is, a TU compiled against new headers +may not work with an older library. Vendors who require such support can leverage availability markup. On the other +hand, backwards compatibility is generally guaranteed. + +There are multiple ABI flags that change the symbols exported from the built library: + +``_LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON`` +------------------------------------------------- +This removes ``__basic_string_common::__throw_length_error()`` and +``__basic_string_common::__throw_out_of_range()``. These symbols have been used by ``basic_string`` in the past, +but are not referenced from the headers anymore. + +``_LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON`` +------------------------------------------------ +This removes ``__vector_base_common::__throw_length_error()`` and +``__vector_base_common::__throw_out_of_range()``. These symbols have been used by ``vector`` in the past, but are +not referenced from the headers anymore. + +``_LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10`` +---------------------------------------------- +This removes ``__itoa::__u32toa()`` and ``__iota::__u64toa``. These symbols have been used by ``to_chars`` in the past, +but are not referenced from the headers anymore. + +``_LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION`` +------------------------------------------------------- +This replaces the symbols that are exported for ``basic_string`` to avoid exporting functions which are likely to be +inlined as well as explicitly moving paths to the built library which are slow, improving fast-path inlining of multiple +functions. This flag is currently unstable. + + +Stability of the traits of a type +================================= +Whether a particular trait of a type is kept stable depends heavily on the type in question and the trait. The most +important trait of a type to keep stable is the triviality for the purpose of calls, since that directly affects the +function call ABI. Which types are considered non-trivial for the purpose of calls is defined in the +`Itanium ABI `_. +``is_trivially_copyable`` should also be kept stable usually, since many programs depend on this trait for their own +layouting. This isn't as rigid as the previous requirement though. + +There are multiple ABI flags that change traits of a struct: + +``_LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI`` +--------------------------------------------- +This flag adds ``[[clang::trivial_abi]]`` to ``unique_ptr``, which makes it trivial for the purpose of calls. + +``_LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI`` +--------------------------------------------- +This flag adds ``[[clang::trivial_abi]]`` to ``shared_ptr``, which makes it trivial for the purpose of calls. + + +Types that public aliases reference +=================================== +There are a lot of aliases that reference types with library internal names. For example, containers contain an +``iterator`` alias to a type with a library internal name. These have to always reference the same type, since the +mangling of user-defined function overloads would change otherwise. A notable exception to this are the alias templates +to type traits. There doesn't seem to be anybody who relies on these names staying the same, so it is OK to change what +these aliases actually reference. + +There are multiple ABI flags which change which type an alias references: + +``_LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE`` +----------------------------------------- +This changes ``deque::iterator`` to avoid requiring complete types for ``deque``. + +``_LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE`` +------------------------------------------------- +This changes the unordered container's ``size_types`` aliases. + +``_LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY`` and ``_LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW`` +----------------------------------------------------------------------------------------------- +This changes the ``iterator`` and ``const_iterator`` of ``array`` and ``string_view`` respectively to reference +``__wrap_iter`` instead, which makes it less likely for users to depend on non-portable implementation details. This is +especially useful because enabling bounded iterators hardening requires code not to make these assumptions. + +``_LIBCPP_ABI_BOUNDED_ITERATORS``, ``_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING``, ``_LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR``, and ``_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY`` +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +These flags change the ``iterator`` member of various classes to reference hardened iterators instead. See the +:ref:`hardening documentation ` for more details. + + +Meaning of values +================= +The meaning of specific values can usually not be changed, since programs compiled against older versions of the headers +may check for these values. These specific values don't have to be hard-coded, but can also depend on user input. + +There are multiple ABI flags that change the meaning of particular values: + +``_LIBCPP_ABI_REGEX_CONSTANTS_NONZERO`` +--------------------------------------- +This changes the value of ``regex_constants::syntax_option-type::ECMAScript`` to be standards-conforming. + +``_LIBCPP_ABI_FIX_CITYHASH_IMPLEMENTATION`` +------------------------------------------- +This flag fixes the implementation of CityHash used for ``hash``. The incorrect implementation of +CityHash has the problem that it drops some bits on the floor. Fixing the implementation changes the hash of values, +resulting in an ABI break. + +inline namespaces +================= +Inline namespaces which contain types that are observable by the user need to be kept the same, since they affect +mangling. Almost all of libc++'s symbols are inside an inline namespace. By default that namespace is ``__1``, but can +be changed by the vendor by setting `LIBCXX_ABI_NAMESPACE` during CMake configuration. There is also +``_LIBCPP_ABI_NO_FILESYSTEM_INLINE_NAMESPACE`` to remove the ``__fs`` namespace from surrounding the ``filesystem`` +namespace. This shortens the mangling of the filesystem symbols a bit. diff --git a/naiveproxy/src/third_party/libc++/src/docs/FeatureTestMacroTable.rst b/naiveproxy/src/third_party/libc++/src/docs/FeatureTestMacroTable.rst index a89d403878..a36848ebd2 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/FeatureTestMacroTable.rst +++ b/naiveproxy/src/third_party/libc++/src/docs/FeatureTestMacroTable.rst @@ -198,6 +198,10 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_char8_t`` ``201907L`` ---------------------------------------------------------- ----------------- + ``__cpp_lib_common_reference`` ``202302L`` + ---------------------------------------------------------- ----------------- + ``__cpp_lib_common_reference_wrapper`` ``202302L`` + ---------------------------------------------------------- ----------------- ``__cpp_lib_concepts`` ``202002L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_constexpr_algorithms`` ``201806L`` @@ -376,7 +380,7 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_ranges_iota`` ``202202L`` ---------------------------------------------------------- ----------------- - ``__cpp_lib_ranges_join_with`` *unimplemented* + ``__cpp_lib_ranges_join_with`` ``202202L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_ranges_repeat`` ``202207L`` ---------------------------------------------------------- ----------------- @@ -420,11 +424,15 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_constexpr_algorithms`` ``202306L`` ---------------------------------------------------------- ----------------- + ``__cpp_lib_constexpr_forward_list`` ``202502L`` + ---------------------------------------------------------- ----------------- + ``__cpp_lib_constexpr_list`` ``202502L`` + ---------------------------------------------------------- ----------------- ``__cpp_lib_constexpr_new`` ``202406L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_constexpr_queue`` ``202502L`` ---------------------------------------------------------- ----------------- - ``__cpp_lib_constrained_equality`` *unimplemented* + ``__cpp_lib_constrained_equality`` ``202411L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_copyable_function`` *unimplemented* ---------------------------------------------------------- ----------------- diff --git a/naiveproxy/src/third_party/libc++/src/docs/Hardening.rst b/naiveproxy/src/third_party/libc++/src/docs/Hardening.rst index 17808841bd..1cdb3605c3 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Hardening.rst +++ b/naiveproxy/src/third_party/libc++/src/docs/Hardening.rst @@ -39,6 +39,8 @@ modes are: Enabling hardening has no impact on the ABI. +.. _notes-for-users: + Notes for users --------------- @@ -72,6 +74,10 @@ to control the level by passing **one** of the following options to the compiler pre-built components. Most libc++ code is header-based, so a user-provided value for ``_LIBCPP_HARDENING_MODE`` will be mostly respected. +In some cases, users might want to override the assertion semantic used by the +library. This can be done similarly to setting the hardening mode; please refer +to the :ref:`relevant section `. + Notes for vendors ----------------- @@ -260,6 +266,68 @@ 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. +This default behavior can be customized by users via :ref:`assertion semantics +`; it can also be completely overridden by vendors by +providing a :ref:`custom assertion failure handler +`. + +.. _assertion-semantics: + +Assertion semantics +------------------- + +.. warning:: + + Assertion semantics are currently an experimental feature. + +.. note:: + + Assertion semantics are not available in the C++03 mode. + +What happens when an assertion fails depends on the assertion semantic being +used. Four assertion semantics are available, based on C++26 Contracts +evaluation semantics: + +- ``ignore`` evaluates the assertion but has no effect if it fails (note that it + differs from the Contracts ``ignore`` semantic which would not evaluate + the assertion at all); +- ``observe`` logs an error (indicating, if possible on the platform, that the + error is fatal) but continues execution; +- ``quick-enforce`` terminates the program as fast as possible via a trap + instruction. It is the default semantic for the production modes (``fast`` and + ``extensive``); +- ``enforce`` logs an error and then terminates the program. It is the default + semantic for the ``debug`` mode. + +Notes: + +- Continuing execution after a hardening check fails results in undefined + behavior; the ``observe`` semantic is meant to make adopting hardening easier + but should not be used outside of the adoption period; +- C++26 wording for Library Hardening precludes a conforming Hardened + implementation from using the Contracts ``ignore`` semantic when evaluating + hardened preconditions in the Library. Libc++ allows using this semantic for + hardened preconditions, but please be aware that using ``ignore`` does not + produce a conforming "Hardened" implementation, unlike the other semantics + above. + +The default assertion semantics are as follows: + +- ``fast``: ``quick-enforce``; +- ``extensive``: ``quick-enforce``; +- ``debug``: ``enforce``. + +The default assertion semantics can be overridden by passing **one** of the +following options to the compiler: + +- ``-D_LIBCPP_ASSERTION_SEMANTIC=_LIBCPP_ASSERTION_SEMANTIC_IGNORE`` +- ``-D_LIBCPP_ASSERTION_SEMANTIC=_LIBCPP_ASSERTION_SEMANTIC_OBSERVE`` +- ``-D_LIBCPP_ASSERTION_SEMANTIC=_LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE`` +- ``-D_LIBCPP_ASSERTION_SEMANTIC=_LIBCPP_ASSERTION_SEMANTIC_ENFORCE`` + +All the :ref:`same notes ` apply to setting this macro as for +setting ``_LIBCPP_HARDENING_MODE``. + .. _override-assertion-handler: Overriding the assertion failure handler diff --git a/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes.rst b/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes.rst index 9feea5fffc..acfcd367de 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/21.rst +.. include:: ReleaseNotes/22.rst .. Make sure to reference the non-live release notes in a toctree to avoid Sphinx errors. .. toctree:: :hidden: ReleaseNotes/20 + ReleaseNotes/21 .. 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/21.rst b/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes/21.rst index 6cbc0baf29..91123ffa3e 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes/21.rst +++ b/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes/21.rst @@ -10,7 +10,7 @@ Written by the `Libc++ Team `_ .. warning:: - These are in-progress notes for the upcoming libc++ 20.0.0 release. + These are in-progress notes for the upcoming libc++ 21.0.0 release. Release notes for previous releases can be found on `the Download Page `_. @@ -18,7 +18,7 @@ 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 +part of the LLVM Compiler Infrastructure, release 21.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 @@ -42,11 +42,19 @@ Implemented Papers - P0767R1: Deprecate POD (`Github `__) - P1361R2: Integration of chrono with text formatting (`Github `__) - P2255R2: A type trait to detect reference binding to temporary (implemented the type traits only) (`Github `__) +- P2372R3: Fixing locale handling in chrono formatters (`Github `__) - P2562R1: ``constexpr`` Stable Sorting (`Github `__) - P0472R3: Put std::monostate in (`Github `__) - P1222R4: A Standard ``flat_set`` (`Github `__) - P2897R7: ``aligned_accessor``: An mdspan accessor expressing pointer over-alignment (`Github `__) - P3247R2: Deprecate the notion of trivial types (`Github `__) +- P3372R3: ``constexpr`` containers and adaptors (`Github `__) (``forward_list``, ``list``, ``priority_queue``, ``flat_map``, and ``flat_set`` are implemented) +- P2441R2: ``views::join_with`` (`Github `__) +- P2711R1: Making multi-param constructors of ``views`` ``explicit`` (`Github `__) +- P2770R0: Stashing stashing ``iterators`` for proper flattening (`Github `__) +- P2655R3: ``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type (`Github `__) +- P2944R3: Comparisons for ``reference_wrapper`` (`Github `__) +- P3379R0: Constrain ``std::expected equality`` operators (`Github `__) Improvements and New Features ----------------------------- @@ -70,12 +78,24 @@ Improvements and New Features - The segmented iterator optimization for ``std::for_each`` has been backported to C++11. Previously it was only available in C++23 and later. -- The ``std::for_each_n`` algorithm has been optimized for segmented iterators, resulting in a performance improvement of - up to 17.7x for ``std::deque`` iterators, and up to 13.9x for ``std::join_view>>`` iterators. +- The ``std::for_each_n``, ``std::ranges::for_each`` and ``std::ranges::for_each_n`` algorithms have been optimized for + segmented iterators, resulting in a performance improvement of up to 17.7x for ``std::deque`` iterators, and up + to 13.9x for ``std::join_view>>`` iterators. - The ``bitset::to_string`` function has been optimized, resulting in a performance improvement of up to 8.3x for bitsets with uniformly distributed zeros and ones, and up to 13.5x and 16.1x for sparse and dense bitsets, respectively. +- The ``flat_map::insert`` and ``flat_set::insert_range`` have been optimized, resulting in a performance improvement of up + to 10x for inserting elements into a ``flat_map`` when the input range is a ``flat_map`` or a ``zip_view``. + +- ``ctype::tolower`` and ``ctype::toupper`` have been optimized, resulting in a 2x performance improvement. + +- As an experimental feature, Hardening now supports assertion semantics that allow customizing how a hardening + assertion failure is handled. The four available semantics, modeled on C++26 Contracts, are ``ignore``, ``observe``, + ``quick-enforce`` and ``enforce``. The ``observe`` semantic is intended to make it easier to adopt Hardening in + production but should not be used outside of this scenario. Please refer to the :ref:`Hardening documentation + ` for details. + Deprecations and Removals ------------------------- @@ -89,7 +109,7 @@ Deprecations and Removals - libc++ no longer adds ``constexpr`` to ``std::hash>::operator()``, as the ``constexpr`` addition since C++20 was an unintended extension. -- TODO: The non-conforming extension ``packaged_task::result_type`` has been removed in LLVM 21. +- The non-conforming extension ``packaged_task::result_type`` has been removed in LLVM 21. Potentially breaking changes ---------------------------- @@ -99,6 +119,11 @@ Potentially breaking changes - User-defined specializations of ``std::common_reference`` are diagnosed now. To customize the common reference type, ``std::basic_common_reference`` should be specialized instead. +- ``std::function`` used to have allocator support, which was removed from the Standard by `http://wg21.link/p0302r1` + due to issues with its design and inconsistent support from implementations. Previously, libc++ would provide + allocator-aware APIs in ``std::function`` in C++11 and C++14, but ignores the allocator argument in all places but + one. Starting in this release, the allocator argument is always ignored. + Announcements About Future Releases ----------------------------------- diff --git a/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes/22.rst b/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes/22.rst new file mode 100644 index 0000000000..15bf46d44b --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes/22.rst @@ -0,0 +1,59 @@ +=========================================== +Libc++ 22.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++ 22.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 22.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++ 22.0.0? +============================== + +Implemented Papers +------------------ + +- P2321R2: ``zip`` (`Github `__) (The paper is partially implemented. ``zip_transform_view`` is implemented in this release) + +Improvements and New Features +----------------------------- + +Deprecations and Removals +------------------------- + +Potentially breaking changes +---------------------------- + +Announcements About Future Releases +----------------------------------- + +ABI Affecting Changes +--------------------- + +Build System Changes +-------------------- diff --git a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx17Issues.csv b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx17Issues.csv index 3ca3e22845..15f4b28575 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx17Issues.csv +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx17Issues.csv @@ -158,14 +158,14 @@ "`LWG2683 `__","filesystem::copy() says ""no effects""","2016-06 (Oulu)","|Complete|","","" "`LWG2684 `__","priority_queue lacking comparator typedef","2016-06 (Oulu)","|Complete|","","" "`LWG2685 `__","shared_ptr deleters must not throw on move construction","2016-06 (Oulu)","|Complete|","","" -"`LWG2687 `__","LWG2687: {inclusive,exclusive}_scan misspecified","2016-06 (Oulu)","|Complete|","","" +"`LWG2687 `__","{inclusive,exclusive}_scan misspecified","2016-06 (Oulu)","|Complete|","","" "`LWG2688 `__","clamp misses preconditions and has extraneous condition on result","2016-06 (Oulu)","|Complete|","","" "`LWG2689 `__","Parallel versions of std::copy and std::move shouldn't be in order","2016-06 (Oulu)","|Nothing To Do|","","" "`LWG2698 `__","Effect of assign() on iterators/pointers/references","2016-06 (Oulu)","|Complete|","","" "`LWG2704 `__","recursive_directory_iterator's members should require '``*this`` is dereferenceable'","2016-06 (Oulu)","|Complete|","","" "`LWG2706 `__","Error reporting for recursive_directory_iterator::pop() is under-specified","2016-06 (Oulu)","|Complete|","","" "`LWG2707 `__","path construction and assignment should have ""string_type&&"" overloads","2016-06 (Oulu)","|Complete|","","" -"`LWG2709 `__","LWG2709: offsetof is unnecessarily imprecise","2016-06 (Oulu)","|Nothing To Do|","","" +"`LWG2709 `__","offsetof is unnecessarily imprecise","2016-06 (Oulu)","|Nothing To Do|","","" "`LWG2710 `__","""Effects: Equivalent to ..."" doesn't count ""Synchronization:"" as determined semantics","2016-06 (Oulu)","|Complete|","","" "`LWG2711 `__","path is convertible from approximately everything under the sun","2016-06 (Oulu)","|Complete|","","" "`LWG2716 `__","Specification of shuffle and sample disallows lvalue URNGs","2016-06 (Oulu)","|Complete|","","" 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 cb3248a415..98b49f92bd 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx20Issues.csv +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx20Issues.csv @@ -237,7 +237,7 @@ "`LWG3310 `__","Replace ``SIZE_MAX``\ with ``numeric_limits::max()``\ ","2020-02 (Prague)","|Complete|","16","" "`LWG3313 `__","``join_view::iterator::operator--``\ is incorrectly constrained","2020-02 (Prague)","|Complete|","14","" "`LWG3314 `__","Is stream insertion behavior locale dependent when ``Period::type``\ is ``micro``\ ?","2020-02 (Prague)","|Complete|","16","" -"`LWG3315 `__","LWG3315: Correct Allocator Default Behavior","2020-02 (Prague)","|Complete|","","" +"`LWG3315 `__","Correct Allocator Default Behavior","2020-02 (Prague)","|Complete|","","" "`LWG3316 `__","Correctly define epoch for ``utc_clock``\ / ``utc_timepoint``\ ","2020-02 (Prague)","","","" "`LWG3317 `__","Incorrect ``operator<<``\ for floating-point durations","2020-02 (Prague)","|Complete|","16","" "`LWG3318 `__","Clarify whether clocks can represent time before their epoch","2020-02 (Prague)","","","" @@ -294,7 +294,7 @@ "`LWG3389 `__","A move-only iterator still does not have a ``counted_iterator``\ ","2020-02 (Prague)","|Complete|","15","" "`LWG3390 `__","``make_move_iterator()``\ cannot be used to construct a ``move_iterator``\ for a move-only iterator","2020-02 (Prague)","|Complete|","14","" "`LWG3393 `__","Missing/incorrect feature test macro for coroutines","2020-02 (Prague)","|Complete|","14","" -"`LWG3395 `__","LWG3395: Definition for three-way comparison needs to be updated (US 152)","2020-02 (Prague)","|Nothing To Do|","","" +"`LWG3395 `__","Definition for three-way comparison needs to be updated (US 152)","2020-02 (Prague)","|Nothing To Do|","","" "`LWG3396 `__","Clarify point of reference for ``source_location::current()``\ (DE 169)","2020-02 (Prague)","|Nothing To Do|","16","" "`LWG3397 `__","``ranges::basic_istream_view::iterator``\ should not provide ``iterator_category``\ ","2020-02 (Prague)","|Complete|","16","" "`LWG3398 `__","``tuple_element_t``\ is also wrong for ``const subrange``\ ","2020-02 (Prague)","|Complete|","14","" 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 4430b78533..e692bb2dc0 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx20Papers.csv +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx20Papers.csv @@ -200,7 +200,7 @@ "`P2328R1 `__","join_view should join all views of ranges","2021-06 (Virtual)","|Complete|","15","" "`P2367R0 `__","Remove misuses of list-initialization from Clause 24","2021-06 (Virtual)","|Complete|","15","" "","","","","","" -"`P2372R3 `__","Fixing locale handling in chrono formatters","2021-10 (Virtual)","|In Progress|","","" +"`P2372R3 `__","Fixing locale handling in chrono formatters","2021-10 (Virtual)","|Complete|","21","" "`P2415R2 `__","What is a ``view``","2021-10 (Virtual)","|Complete|","14","" "`P2418R2 `__","Add support for ``std::generator``-like types to ``std::format``","2021-10 (Virtual)","|Complete|","15","" "`P2432R1 `__","Fix ``istream_view``","2021-10 (Virtual)","|Complete|","16","" 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 b5c8861155..189f8452e0 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx23Issues.csv +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx23Issues.csv @@ -170,7 +170,7 @@ "`LWG3687 `__","``expected`` move constructor should move","2022-07 (Virtual)","|Complete|","16","" "`LWG3692 `__","``zip_view::iterator``'s ``operator<=>`` is overconstrained","2022-07 (Virtual)","|Complete|","20","" "`LWG3701 `__","Make ``formatter, charT>`` requirement explicit","2022-07 (Virtual)","|Complete|","15","" -"`LWG3702 `__","Should ``zip_transform_view::iterator`` remove ``operator<``","2022-07 (Virtual)","","","" +"`LWG3702 `__","Should ``zip_transform_view::iterator`` remove ``operator<``","2022-07 (Virtual)","|Complete|","22","" "`LWG3703 `__","Missing requirements for ``expected`` requires ``is_void``","2022-07 (Virtual)","|Complete|","16","" "`LWG3704 `__","LWG 2059 added overloads that might be ill-formed for sets","2022-07 (Virtual)","","","" "`LWG3705 `__","Hashability shouldn't depend on basic_string's allocator","2022-07 (Virtual)","|Complete|","16","" @@ -194,7 +194,7 @@ "`LWG3569 `__","``join_view`` fails to support ranges of ranges with non-default_initializable iterators","2022-11 (Kona)","","","" "`LWG3594 `__","``inout_ptr`` — inconsistent ``release()`` in destructor","2022-11 (Kona)","|Complete|","19","" "`LWG3597 `__","Unsigned integer types don't model advanceable","2022-11 (Kona)","","","" -"`LWG3600 `__","Making ``istream_iterator`` copy constructor trivial is an ABI break","2022-11 (Kona)","|Nothing To Do|","","" +"`LWG3600 `__","Making ``istream_iterator`` copy constructor trivial is an ABI break","2022-11 (Kona)","|Complete|","","" "`LWG3629 `__","``make_error_code`` and ``make_error_condition`` are customization points","2022-11 (Kona)","|Complete|","16","" "`LWG3636 `__","``formatter::format`` should be ``const``-qualified","2022-11 (Kona)","|Complete|","16","" "`LWG3646 `__","``std::ranges::view_interface::size`` returns a signed type","2022-11 (Kona)","|Complete|","16","" @@ -213,7 +213,7 @@ "`LWG3753 `__","Clarify entity vs. freestanding entity","2022-11 (Kona)","","","" "`LWG3754 `__","Class template expected synopsis contains declarations that do not match the detailed description","2022-11 (Kona)","|Nothing To Do|","","" "`LWG3755 `__","``tuple-for-each`` can call ``user-defined`` ``operator,``","2022-11 (Kona)","|Complete|","17","" -"`LWG3757 `__","What's the effect of ``std::forward_like(x)``?","2022-11 (Kona)","|Nothing To Do|","","" +"`LWG3757 `__","What's the effect of ``std::forward_like(x)``?","2022-11 (Kona)","|Complete|","","" "`LWG3759 `__","``ranges::rotate_copy`` should use ``std::move``","2022-11 (Kona)","|Complete|","15","" "`LWG3760 `__","``cartesian_product_view::iterator``'s ``parent_`` is never valid","2022-11 (Kona)","","","" "`LWG3761 `__","``cartesian_product_view::iterator::operator-`` should pass by reference","2022-11 (Kona)","","","" @@ -222,7 +222,7 @@ "`LWG3765 `__","``const_sentinel`` should be constrained","2022-11 (Kona)","","","" "`LWG3766 `__","``view_interface::cbegin`` is underconstrained","2022-11 (Kona)","","","" "`LWG3770 `__","``const_sentinel_t`` is missing","2022-11 (Kona)","","","" -"`LWG3773 `__","``views::zip_transform`` still requires ``F`` to be ``copy_constructible`` when empty pack","2022-11 (Kona)","","","" +"`LWG3773 `__","``views::zip_transform`` still requires ``F`` to be ``copy_constructible`` when empty pack","2022-11 (Kona)","|Complete|","22","" "`LWG3774 `__","```` should include ````","2022-11 (Kona)","","","" "`LWG3775 `__","Broken dependencies in the ``Cpp17Allocator`` requirements","2022-11 (Kona)","","","" "`LWG3778 `__","``vector`` missing exception specifications","2022-11 (Kona)","|Complete|","3.7","" @@ -234,7 +234,7 @@ "`LWG3792 `__","``__cpp_lib_constexpr_algorithms`` should also be defined in ````","2022-11 (Kona)","|Complete|","16","" "`LWG3795 `__","Self-move-assignment of ``std::future`` and ``std::shared_future`` have unimplementable postconditions","2022-11 (Kona)","","","" "`LWG3796 `__","``movable-box`` as member should use ``default-initialization`` instead of ``copy-initialization``","2022-11 (Kona)","","","" -"`LWG3798 `__","Rvalue reference and ``iterator_category``","2022-11 (Kona)","|Partial|","","``join_with_view``, ``zip_transform_view``, and ``adjacent_transform_view`` haven't been done yet since these types aren't implemented yet" +"`LWG3798 `__","Rvalue reference and ``iterator_category``","2022-11 (Kona)","|Partial|","","``adjacent_transform_view`` hasn't been done yet since this type isn't implemented yet" "`LWG3801 `__","``cartesian_product_view::iterator::distance-from`` ignores the size of last underlying range","2022-11 (Kona)","","","" "`LWG3814 `__","Add freestanding items requested by NB comments","2022-11 (Kona)","","","" "`LWG3816 `__","``flat_map`` and ``flat_multimap`` should impose sequence container requirements","2022-11 (Kona)","","","" 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 c26363bcda..f1d8e9a2bd 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx23Papers.csv +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx23Papers.csv @@ -47,7 +47,7 @@ "`P2273R3 `__","Making ``std::unique_ptr`` constexpr","2022-02 (Virtual)","|Complete|","16","" "`P2387R3 `__","Pipe support for user-defined range adaptors","2022-02 (Virtual)","|Complete|","19","" "`P2440R1 `__","``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right``","2022-02 (Virtual)","|Partial|","","Only ``ranges::iota`` is implemented." -"`P2441R2 `__","``views::join_with``","2022-02 (Virtual)","|In Progress|","","" +"`P2441R2 `__","``views::join_with``","2022-02 (Virtual)","|Complete|","21","" "`P2442R1 `__","Windowing range adaptors: ``views::chunk`` and ``views::slide``","2022-02 (Virtual)","","","" "`P2443R1 `__","``views::chunk_by``","2022-02 (Virtual)","|Complete|","18","" "","","","","","" @@ -60,7 +60,7 @@ "`P1642R11 `__","Freestanding ``[utilities]``, ``[ranges]``, and ``[iterators]``","2022-07 (Virtual)","","","" "`P1899R3 `__","``stride_view``","2022-07 (Virtual)","","","" "`P2093R14 `__","Formatted output","2022-07 (Virtual)","|Complete|","18","" -"`P2165R4 `__","Compatibility between ``tuple``, ``pair`` and ``tuple-like`` objects","2022-07 (Virtual)","|Partial|","","Only the part for ``zip_view`` is implemented." +"`P2165R4 `__","Compatibility between ``tuple``, ``pair`` and ``tuple-like`` objects","2022-07 (Virtual)","|Partial|","","Changes of ``tuple``, ``adjacent_view``, and ``cartesian_product_view`` are not yet implemented." "`P2278R4 `__","``cbegin`` should always return a constant iterator","2022-07 (Virtual)","","","" "`P2286R8 `__","Formatting Ranges","2022-07 (Virtual)","|Complete|","16","" "`P2291R3 `__","Add Constexpr Modifiers to Functions ``to_chars`` and ``from_chars`` for Integral Types in ```` Header","2022-07 (Virtual)","|Complete|","16","" @@ -103,9 +103,9 @@ "`P2708R1 `__","No Further Fundamentals TSes","2022-11 (Kona)","|Nothing To Do|","","" "","","","","","" "`P0290R4 `__","``apply()`` for ``synchronized_value``","2023-02 (Issaquah)","","","" -"`P2770R0 `__","Stashing stashing ``iterators`` for proper flattening","2023-02 (Issaquah)","|Partial|","","``join_with_view`` hasn't been done yet since this type isn't implemented yet" +"`P2770R0 `__","Stashing stashing ``iterators`` for proper flattening","2023-02 (Issaquah)","|Complete|","21","" "`P2164R9 `__","``views::enumerate``","2023-02 (Issaquah)","","","" -"`P2711R1 `__","Making multi-param constructors of ``views`` ``explicit``","2023-02 (Issaquah)","|In Progress|","","``join_with_view`` hasn't been done yet since this type isn't implemented yet" +"`P2711R1 `__","Making multi-param constructors of ``views`` ``explicit``","2023-02 (Issaquah)","|Complete|","21","" "`P2609R3 `__","Relaxing Ranges Just A Smidge","2023-02 (Issaquah)","|Complete|","20","Implemented as a DR in C++20. Other implementations will do the same." "`P2713R1 `__","Escaping improvements in ``std::format``","2023-02 (Issaquah)","|Complete|","19","" "`P2675R1 `__","``format``'s width estimation is too approximate and not forward compatible","2023-02 (Issaquah)","|Complete|","17","" @@ -113,7 +113,7 @@ "`P2693R1 `__","Formatting ``thread::id`` and ``stacktrace``","2023-02 (Issaquah)","|Partial|","","The formatter for ``stacktrace`` is not implemented, since ``stacktrace`` is not implemented yet" "`P2679R2 `__","Fixing ``std::start_lifetime_as`` for arrays","2023-02 (Issaquah)","","","" "`P2674R1 `__","A trait for implicit lifetime types","2023-02 (Issaquah)","|Complete|","20","" -"`P2655R3 `__","``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type","2023-02 (Issaquah)","","","" +"`P2655R3 `__","``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type","2023-02 (Issaquah)","|Complete|","21","The paper is implemented as a DR to C++20" "`P2652R2 `__","Disallow User Specialization of ``allocator_traits``","2023-02 (Issaquah)","|Complete|","19","" "`P2787R1 `__","``pmr::generator`` - Promise Types are not Values","2023-02 (Issaquah)","","","" "`P2614R2 `__","Deprecate ``numeric_limits::has_denorm``","2023-02 (Issaquah)","|Complete|","18","" 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 fdf381862d..c6225127a7 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx2cIssues.csv +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx2cIssues.csv @@ -36,7 +36,7 @@ "`LWG3970 `__","[mdspan.syn] Missing definition of ``full_extent_t`` and ``full_extent``","2023-11 (Kona)","","","" "`LWG3973 `__","Monadic operations should be ADL-proof","2023-11 (Kona)","","","" "`LWG3974 `__","``mdspan::operator[]`` should not copy ``OtherIndexTypes``","2023-11 (Kona)","","","" -"`LWG3987 `__","Including ```` doesn't provide ``std::begin``/``end``","2023-11 (Kona)","","","" +"`LWG3987 `__","Including `` doesn't provide `std::begin`/`end`","2023-11 (Kona)","|Complete|","","" "`LWG3990 `__","Program-defined specializations of ``std::tuple`` and ``std::variant`` can't be properly supported","2023-11 (Kona)","|Complete|","21","" "`LWG4001 `__","``iota_view`` should provide ``empty``","2023-11 (Kona)","|Complete|","19","" "","","","","","" @@ -45,7 +45,7 @@ "`LWG3950 `__","``std::basic_string_view`` comparison operators are overspecified","2024-03 (Tokyo)","|Complete|","18","" "`LWG3975 `__","Specializations of ``basic_format_context`` should not be permitted","2024-03 (Tokyo)","|Nothing To Do|","","" "`LWG3984 `__","``ranges::to``'s recursion branch may be ill-formed","2024-03 (Tokyo)","|Complete|","19","" -"`LWG4011 `__","``""Effects: Equivalent to return""`` in ``[span.elem]``","2024-03 (Tokyo)","|Nothing To Do|","","" +"`LWG4011 `__","""`Effects`: Equivalent to return"" in ``[span.elem]``","2024-03 (Tokyo)","|Nothing To Do|","","" "`LWG4012 `__","``common_view::begin/end`` are missing the ``simple-view`` check","2024-03 (Tokyo)","","","" "`LWG4013 `__","``lazy_split_view::outer-iterator::value_type`` should not provide default constructor","2024-03 (Tokyo)","","","" "`LWG4016 `__","container-insertable checks do not match what container-inserter does","2024-03 (Tokyo)","|Complete|","20","" @@ -66,7 +66,7 @@ "`LWG4060 `__","``submdspan`` preconditions do not forbid creating invalid pointer","2024-06 (St. Louis)","","","" "`LWG4061 `__","Should ``std::basic_format_context`` be default-constructible/copyable/movable?","2024-06 (St. Louis)","|Complete|","19","" "`LWG4071 `__","``reference_wrapper`` comparisons are not SFINAE-friendly","2024-06 (St. Louis)","|Complete|","19","" -"`LWG4074 `__","``compatible-joinable-ranges`` is underconstrained","2024-06 (St. Louis)","","","" +"`LWG4074 `__","``compatible-joinable-ranges`` is underconstrained","2024-06 (St. Louis)","|Complete|","21","" "`LWG4076 `__","``concat_view`` should be freestanding","2024-06 (St. Louis)","","","" "`LWG4079 `__","Missing Preconditions in ``concat_view::iterator``\`s conversion constructor","2024-06 (St. Louis)","","","" "`LWG4082 `__","``views::concat(r)`` is well-formed when ``r`` is an ``output_range``","2024-06 (St. Louis)","","","" @@ -83,7 +83,7 @@ "`LWG3900 `__","The ``allocator_arg_t`` overloads of ``generator::promise_type::operator new`` should not be constrained","2024-11 (Wrocław)","","","" "`LWG3918 `__","``std::uninitialized_move/_n`` and guaranteed copy elision","2024-11 (Wrocław)","","","" "`LWG4014 `__","LWG 3809 changes behavior of some existing ``std::subtract_with_carry_engine code``","2024-11 (Wrocław)","","","" -"`LWG4024 `__","Underspecified destruction of objects created in ``std::make_shared_for_overwrite``/``std::allocate_shared_for_overwrite``","2024-11 (Wrocław)","","16","" +"`LWG4024 `__","Underspecified destruction of objects created in ``std::make_shared_for_overwrite``/``std::allocate_shared_for_overwrite``","2024-11 (Wrocław)","|Complete|","16","" "`LWG4027 `__","``possibly-const-range`` should prefer returning ``const R&``","2024-11 (Wrocław)","","","" "`LWG4044 `__","Confusing requirements for ``std::print`` on POSIX platforms","2024-11 (Wrocław)","","","" "`LWG4064 `__","Clarify that ``std::launder`` is not needed when using the result of ``std::memcpy``","2024-11 (Wrocław)","","","" @@ -92,13 +92,13 @@ "`LWG4085 `__","``ranges::generate_random``'s helper lambda should specify the return type","2024-11 (Wrocław)","","","" "`LWG4088 `__","``println`` ignores the locale imbued in ``std::ostream``","2024-11 (Wrocław)","|Complete|","18","" "`LWG4112 `__","``has-arrow`` should required ``operator->()`` to be ``const``-qualified","2024-11 (Wrocław)","","","" -"`LWG4113 `__","Disallow ``has_unique_object_representations``","2024-11 (Wrocław)","","","" +"`LWG4113 `__","Disallow ``has_unique_object_representations``","2024-11 (Wrocław)","|Complete|","","" "`LWG4119 `__","``generator::promise_type::yield_value(ranges::elements_of)``'s nested ``generator`` may be ill-formed","2024-11 (Wrocław)","","","" "`LWG4124 `__","Cannot format ``zoned_time`` with resolution coarser than ``seconds``","2024-11 (Wrocław)","","","" "`LWG4126 `__","Some feature-test macros for fully freestanding features are not yet marked freestanding","2024-11 (Wrocław)","","","" "`LWG4134 `__","Issue with Philox algorithm specification","2024-11 (Wrocław)","","","" "`LWG4135 `__","The helper lambda of ``std::erase`` for list should specify return type as ``bool``","2024-11 (Wrocław)","|Complete|","21","" -"`LWG4140 `__","Useless default constructors for bit reference types","2024-11 (Wrocław)","|Nothing To Do|","","" +"`LWG4140 `__","Useless default constructors for bit reference types","2024-11 (Wrocław)","|Complete|","","" "`LWG4141 `__","Improve prohibitions on ""additional storage""","2024-11 (Wrocław)","","","" "`LWG4142 `__","``format_parse_context::check_dynamic_spec`` should require at least one type","2024-11 (Wrocław)","","","" "`LWG4144 `__","Disallow ``unique_ptr``","2024-11 (Wrocław)","","","" @@ -106,22 +106,48 @@ "`LWG4148 `__","``unique_ptr::operator*`` should not allow dangling references","2024-11 (Wrocław)","","","" "`LWG4153 `__","Fix extra ""-1"" for ``philox_engine::max()``","2024-11 (Wrocław)","","","" "`LWG4154 `__","The Mandates for ``std::packaged_task``'s constructor from a callable entity should consider decaying","2024-11 (Wrocław)","","","" -"`LWG4157 `__","The resolution of LWG3465 was damaged by P2167R3","2024-11 (Wrocław)","","20","" +"`LWG4157 `__","The resolution of LWG3465 was damaged by P2167R3","2024-11 (Wrocław)","|Complete|","20","" "`LWG4164 `__","Missing guarantees for ``forward_list`` modifiers","2024-11 (Wrocław)","|Complete|","21","" "`LWG4169 `__","``std::atomic``'s default constructor should be constrained","2024-11 (Wrocław)","","","" "`LWG4170 `__","``contiguous_iterator`` should require ``to_address(I{})``","2024-11 (Wrocław)","","","" "","","","","","" -"`LWG3578 `__","Iterator SCARYness in the context of associative container merging","2025-02 (Hagenberg)","","","" -"`LWG3956 `__","``chrono::parse`` uses ``from_stream`` as a customization point","2025-02 (Hagenberg)","","","" -"`LWG4172 `__","``unique_lock`` self-move-assignment is broken","2025-02 (Hagenberg)","","","" -"`LWG4175 `__","``get_env()`` specified in terms of ``as_const()`` but this doesn't work with rvalue senders","2025-02 (Hagenberg)","","","" -"`LWG4179 `__","Wrong range in ``[alg.search]``","2025-02 (Hagenberg)","","","" -"`LWG4186 `__","``regex_traits::transform_primary`` mistakenly detects ``typeid`` of a function","2025-02 (Hagenberg)","","","" -"`LWG4189 `__","``cache_latest_view`` should be freestanding","2025-02 (Hagenberg)","","","" -"`LWG4191 `__","P1467 changed the return type of ``pow(complex, int)``","2025-02 (Hagenberg)","","","" -"`LWG4196 `__","Complexity of ``inplace_merge()`` is incorrect","2025-02 (Hagenberg)","","","" +"`LWG3578 `__","Iterator SCARYness in the context of associative container merging","2025-02 (Hagenberg)","","","" +"`LWG3956 `__","``chrono::parse`` uses ``from_stream`` as a customization point","2025-02 (Hagenberg)","","","" +"`LWG4172 `__","``unique_lock`` self-move-assignment is broken","2025-02 (Hagenberg)","","","" +"`LWG4175 `__","``get_env()`` specified in terms of ``as_const()`` but this doesn't work with rvalue senders","2025-02 (Hagenberg)","","","" +"`LWG4179 `__","Wrong range in ``[alg.search]``","2025-02 (Hagenberg)","","","" +"`LWG4186 `__","``regex_traits::transform_primary`` mistakenly detects ``typeid`` of a function","2025-02 (Hagenberg)","","","" +"`LWG4189 `__","``cache_latest_view`` should be freestanding","2025-02 (Hagenberg)","","","" +"`LWG4191 `__","P1467 changed the return type of ``pow(complex, int)``","2025-02 (Hagenberg)","","","" +"`LWG4196 `__","Complexity of ``inplace_merge()`` is incorrect","2025-02 (Hagenberg)","","","" +"","","","","","" +"`LWG4198 `__","``schedule_from`` isn't starting the schedule sender if decay-copying results throws","2025-06 (Sofia)","","","" +"`LWG4202 `__","``enable-sender`` should be a variable template","2025-06 (Sofia)","","","" +"`LWG4203 `__","Constraints on ``get-state`` functions are incorrect","2025-06 (Sofia)","","","" +"`LWG4204 `__","specification of ``as-sndr2(Sig)`` in [exec.let] is incomplete","2025-06 (Sofia)","","","" +"`LWG4205 `__","``let_[*].transform_env`` is specified in terms of the ``let_*`` sender itself instead of its child","2025-06 (Sofia)","","","" +"`LWG4208 `__","Wording needs to ensure that in ``connect(sndr, rcvr)`` that ``rcvr`` expression is only evaluated once","2025-06 (Sofia)","","","" +"`LWG4209 `__","``default_domain::transform_env`` should be returning ``FWD-ENV(env)``","2025-06 (Sofia)","","","" +"`LWG4188 `__","``ostream::sentry`` destructor should handle exceptions","2025-06 (Sofia)","","","" +"`LWG4200 `__","The ``operation_state`` concept can be simplified","2025-06 (Sofia)","","","" +"`LWG4201 `__","``with-await-transform::await_transform`` should not use a deduced return type","2025-06 (Sofia)","","","" +"`LWG4217 `__","Clarify ``mdspan`` layout mapping requirements for ``rank == 0``","2025-06 (Sofia)","","","" +"`LWG4222 `__","``expected`` constructor from a single value missing a constraint","2025-06 (Sofia)","","","" +"`LWG4224 `__","Philox engines should be freestanding","2025-06 (Sofia)","","","" +"`LWG4227 `__","Missing ``noexcept`` operator in [exec.when.all]","2025-06 (Sofia)","","","" +"`LWG4231 `__","``datapar::chunk`` should use ``simd-size-type`` instead of ``size_t``","2025-06 (Sofia)","","","" +"`LWG4232 `__","``datapar::resize`` does not resize","2025-06 (Sofia)","","","" +"`LWG4233 `__","The helper lambda of ``std::erase`` for ``hive`` should specify return type as ``bool``","2025-06 (Sofia)","","","" +"`LWG4234 `__","Including ```` doesn't provide ``std::begin/end``","2025-06 (Sofia)","","","" +"`LWG4235 `__","``cache_latest_view`` and ``to_input_view`` miss ``reserve_hint``","2025-06 (Sofia)","","","" +"`LWG4236 `__","``chunk_view::outer-iterator::value_type`` should provide ``reserve_hint``","2025-06 (Sofia)","","","" +"`LWG4239 `__","``flat_map``'s transparent comparator no longer works for string literals","2025-06 (Sofia)","","","" +"`LWG4242 `__","``ranges::distance`` does not work with volatile iterators","2025-06 (Sofia)","","","" +"`LWG4245 `__","Operators that interact with ``counted_iterator`` and ``default_sentinel_t`` should be ``noexcept``","2025-06 (Sofia)","","","" +"`LWG4247 `__","Header ```` is not yet freestanding","2025-06 (Sofia)","","","" "","","","","","" "`LWG3343 `__","Ordering of calls to ``unlock()`` and ``notify_all()`` in Effects element of ``notify_all_at_thread_exit()`` should be reversed","Not Adopted Yet","|Complete|","16","" -"`LWG4139 `__","§[time.zone.leap] recursive constraint in <=>","Not Adopted Yet","|Complete|","20","" -"`LWG3456 `__","Pattern used by std::from_chars is underspecified (option B)","Not Adopted Yet","|Complete|","20","" +"`LWG4139 `__","§[time.zone.leap] recursive constraint in ``<=>``","Not Adopted Yet","|Complete|","20","" +"`LWG3456 `__","Pattern used by ``std::from_chars`` is underspecified (option B)","Not Adopted Yet","|Complete|","20","" +"`LWG3882 `__","``tuple`` relational operators have confused friendships","Not Adopted Yet","|Complete|","21","The comparsion operators are constrained harder than the proposed resolution. libstdc++ and MSVC STL do the same." "","","","","","" 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 3809446a57..e8b0c9559f 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx2cPapers.csv +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx2cPapers.csv @@ -59,7 +59,7 @@ "`P2248R8 `__","Enabling list-initialization for algorithms","2024-03 (Tokyo)","","","" "`P2810R4 `__","``is_debugger_present`` ``is_replaceable``","2024-03 (Tokyo)","","","" "`P1068R11 `__","Vector API for random number generation","2024-03 (Tokyo)","","","" -"`P2944R3 `__","Comparisons for ``reference_wrapper``","2024-03 (Tokyo)","|Partial|","","Implemented changes to ``reference_wrapper`` and ``pair``" +"`P2944R3 `__","Comparisons for ``reference_wrapper``","2024-03 (Tokyo)","|Complete|","21","" "`P2642R6 `__","Padded ``mdspan`` layouts","2024-03 (Tokyo)","","","" "`P3029R1 `__","Better ``mdspan``'s CTAD","2024-03 (Tokyo)","|Complete|","19","" "","","","","","" @@ -104,7 +104,7 @@ "`P3137R3 `__","``views::to_input``","2025-02 (Hagenberg)","","","" "`P0472R3 `__","Put ``std::monostate`` in ````","2025-02 (Hagenberg)","|Complete|","21","" "`P3349R1 `__","Converting contiguous iterators to pointers","2025-02 (Hagenberg)","","","" -"`P3372R3 `__","constexpr containers and adaptors","2025-02 (Hagenberg)","","","" +"`P3372R3 `__","constexpr containers and adaptors","2025-02 (Hagenberg)","|In Progress|","","" "`P3378R2 `__","constexpr exception types","2025-02 (Hagenberg)","","","" "`P3441R2 `__","Rename ``simd_split`` to ``simd_chunk``","2025-02 (Hagenberg)","","","" "`P3287R3 `__","Exploration of namespaces for ``std::simd``","2025-02 (Hagenberg)","","","" @@ -117,3 +117,43 @@ "`P0447R28 `__","Introduction of ``std::hive`` to the standard library","2025-02 (Hagenberg)","","","" "`P3019R14 `__","``indirect`` and ``polymorphic``: Vocabulary Types for Composite Class Design","2025-02 (Hagenberg)","","","" "","","","","","" +"`P2996R13 `__","Reflection for C++26","2025-06 (Sofia)","","","" +"`P3394R4 `__","Annotations for Reflection","2025-06 (Sofia)","","","" +"`P3293R3 `__","Splicing a base class subobject","2025-06 (Sofia)","","","" +"`P3491R3 `__","``define_static_{string,object,array}``","2025-06 (Sofia)","","","" +"`P3096R12 `__","Function Parameter Reflection in Reflection for C++26","2025-06 (Sofia)","","","" +"`P2988R12 `__","``std::optional``","2025-06 (Sofia)","","","" +"`P3348R4 `__","C++26 should refer to C23 not C17","2025-06 (Sofia)","","","" +"`P3037R6 `__","``constexpr`` ``std::shared_ptr`` and friends","2025-06 (Sofia)","","","" +"`P3284R4 `__","``write_env`` and ``unstoppable`` Sender Adaptors","2025-06 (Sofia)","","","" +"`P3179R9 `__","Parallel Range Algorithms","2025-06 (Sofia)","","","" +"`P3709R2 `__","Reconsider parallel ``ranges::rotate_copy`` and ``ranges::reverse_copy``","2025-06 (Sofia)","","","" +"`P3641R0 `__","Rename ``std::observable`` to ``std::observable_checkpoint``, and add a feature-test macro","2025-06 (Sofia)","","","" +"`P3044R2 `__","sub-``string_view`` from ``string``","2025-06 (Sofia)","","","" +"`P2876R3 `__","Proposal to extend ``std::simd`` with more constructors and accessors","2025-06 (Sofia)","","","" +"`P3480R6 `__","``std::simd`` is a range","2025-06 (Sofia)","","","" +"`P2664R11 `__","Extend ``std::simd`` with permutation API","2025-06 (Sofia)","","","" +"`P3691R1 `__","Reconsider naming of the namespace for ``std::simd``","2025-06 (Sofia)","","","" +"`P3383R3 `__","``mdspan.at()``","2025-06 (Sofia)","","","" +"`P2927R3 `__","Inspecting ``exception_ptr``","2025-06 (Sofia)","","","" +"`P3748R0 `__","Inspecting ``exception_ptr`` should be constexpr","2025-06 (Sofia)","","","" +"`P2830R10 `__","Standardized Constexpr Type Ordering","2025-06 (Sofia)","","","" +"`P3570R2 `__","optional variants in sender/receiver","2025-06 (Sofia)","","","" +"`P3481R5 `__","``std::execution::bulk()`` issues","2025-06 (Sofia)","","","" +"`P3433R1 `__","Allocator Support for Operation States","2025-06 (Sofia)","","","" +"`P3149R11 `__","``async_scope`` - Creating scopes for non-sequential concurrency","2025-06 (Sofia)","","","" +"`P3682R0 `__","Remove ``std::execution::split``","2025-06 (Sofia)","","","" +"`P2079R10 `__","Parallel scheduler","2025-06 (Sofia)","","","" +"`P3557R3 `__","High-Quality Sender Diagnostics with Constexpr Exceptions","2025-06 (Sofia)","","","" +"`P3560R2 `__","Error Handling in Reflection","2025-06 (Sofia)","","","" +"`P3503R3 `__","Make type-erased allocator use in ``promise`` and ``packaged_task`` consistent","2025-06 (Sofia)","","","" +"`P3008R6 `__","Atomic floating-point min/max","2025-06 (Sofia)","","","" +"`P3111R8 `__","Atomic Reduction Operations","2025-06 (Sofia)","","","" +"`P3060R3 `__","Add ``std::views::indices(n)``","2025-06 (Sofia)","","","" +"`P2319R5 `__","Prevent ``path`` presentation problems","2025-06 (Sofia)","","","" +"`P3223R2 `__","Making ``std::istream::ignore`` less surprising","2025-06 (Sofia)","","","" +"`P2781R9 `__","``std::constant_wrapper``","2025-06 (Sofia)","","","" +"`P3697R1 `__","Minor additions to C++26 standard library hardening","2025-06 (Sofia)","","","" +"`P3552R3 `__","Add a Coroutine Task Type","2025-06 (Sofia)","","","" +"`P1317R2 `__","Remove return type deduction in ``std::apply``","2025-06 (Sofia)","","","" +"","","","","","" diff --git a/naiveproxy/src/third_party/libc++/src/docs/UserDocumentation.rst b/naiveproxy/src/third_party/libc++/src/docs/UserDocumentation.rst index dbacb44735..415a599168 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/UserDocumentation.rst +++ b/naiveproxy/src/third_party/libc++/src/docs/UserDocumentation.rst @@ -72,6 +72,11 @@ when ``-fexperimental-library`` is passed: * ``std::chrono::tzdb`` and related time zone functionality * ```` +Additionally, assertion semantics are an experimental feature that can be used +to customize the behavior of Hardening (see :ref:`here `). +Assertion semantics mirror the evaluation semantics of C++26 Contracts but are +not a standard feature. + .. note:: Experimental libraries are experimental. * The contents of the ```` headers and the associated static @@ -82,6 +87,8 @@ when ``-fexperimental-library`` is passed: version has shipped. The full policy is explained :ref:`here `. +.. _libcxx-configuration-macros: + Libc++ Configuration Macros =========================== @@ -112,11 +119,6 @@ enable or disable extended libc++ behavior. ensure that the appropriate experimental library (usually ``libc++experimental.a``) is linked into their program. -**_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS**: - This macro is used to enable -Wthread-safety annotations on libc++'s - ``std::mutex`` and ``std::lock_guard``. By default, these annotations are - disabled and must be manually enabled by the user. - **_LIBCPP_HARDENING_MODE**: This macro is used to choose the :ref:`hardening mode `. diff --git a/naiveproxy/src/third_party/libc++/src/docs/VendorDocumentation.rst b/naiveproxy/src/third_party/libc++/src/docs/VendorDocumentation.rst index 959a28607d..aede8f9a81 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/VendorDocumentation.rst +++ b/naiveproxy/src/third_party/libc++/src/docs/VendorDocumentation.rst @@ -582,3 +582,8 @@ situations will give the same result: $ clang++ -stdlib=libc++ helloworld.cpp -lcxxrt .. _`libcxxrt`: https://github.com/libcxxrt/libcxxrt + +libc++'s ABI guarantees +======================= + +Libc++ provides several ABI guarantees, which are documented :ref:`here `. diff --git a/naiveproxy/src/third_party/libc++/src/docs/index.rst b/naiveproxy/src/third_party/libc++/src/docs/index.rst index a8b0d5ce1e..a44c316153 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/index.rst +++ b/naiveproxy/src/third_party/libc++/src/docs/index.rst @@ -37,6 +37,7 @@ Getting Started with libc++ ReleaseNotes UserDocumentation VendorDocumentation + ABIGuarantees Contributing CodingGuidelines TestingLibcxx @@ -132,9 +133,9 @@ velocity, libc++ drops support for older compilers as newer ones are released. Compiler Versions Restrictions Support policy ============ =================== ========================== ===================== Clang 19, 20, 21-git latest two stable releases per `LLVM's release page `_ and the development version -AppleClang 15 latest stable release per `Xcode's release page `_ +AppleClang 16.4 latest stable release per `Xcode's release page `_ Open XL 17.1.3 (AIX) latest stable release per `Open XL's documentation page `_ -GCC 14 In C++11 or later only latest stable release per `GCC's release page `_ +GCC 15 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 43cefd5600..51444ec668 100644 --- a/naiveproxy/src/third_party/libc++/src/include/CMakeLists.txt +++ b/naiveproxy/src/third_party/libc++/src/include/CMakeLists.txt @@ -381,6 +381,7 @@ set(files __format/enable_insertable.h __format/escaped_output_table.h __format/extended_grapheme_cluster_table.h + __format/fmt_pair_like.h __format/format_arg.h __format/format_arg_store.h __format/format_args.h @@ -403,6 +404,7 @@ set(files __format/indic_conjunct_break_table.h __format/parser_std_format_spec.h __format/range_default_formatter.h + __format/range_format.h __format/range_formatter.h __format/unicode.h __format/width_estimation_table.h @@ -498,6 +500,7 @@ set(files __iterator/ostreambuf_iterator.h __iterator/permutable.h __iterator/prev.h + __iterator/product_iterator.h __iterator/projected.h __iterator/ranges_iterator_traits.h __iterator/readable_traits.h @@ -510,13 +513,18 @@ set(files __iterator/unreachable_sentinel.h __iterator/wrap_iter.h __locale + __locale_dir/check_grouping.h + __locale_dir/get_c_locale.h __locale_dir/locale_base_api.h - __locale_dir/locale_base_api/android.h __locale_dir/locale_base_api/bsd_locale_fallbacks.h __locale_dir/locale_base_api/ibm.h __locale_dir/locale_base_api/musl.h __locale_dir/locale_base_api/openbsd.h + __locale_dir/messages.h + __locale_dir/money.h + __locale_dir/num.h __locale_dir/pad_and_output.h + __locale_dir/scan_keyword.h __locale_dir/support/apple.h __locale_dir/support/bsd_like.h __locale_dir/support/freebsd.h @@ -525,6 +533,10 @@ set(files __locale_dir/support/no_locale/characters.h __locale_dir/support/no_locale/strtonum.h __locale_dir/support/windows.h + __locale_dir/time.h + __locale_dir/wbuffer_convert.h + __locale_dir/wstring_convert.h + __log_hardening_failure __math/abs.h __math/copysign.h __math/error_functions.h @@ -706,6 +718,7 @@ set(files __ranges/iota_view.h __ranges/istream_view.h __ranges/join_view.h + __ranges/join_with_view.h __ranges/lazy_split_view.h __ranges/movable_box.h __ranges/non_propagating_cache.h @@ -726,6 +739,7 @@ set(files __ranges/transform_view.h __ranges/view_interface.h __ranges/views.h + __ranges/zip_transform_view.h __ranges/zip_view.h __split_buffer __std_mbstate_t.h @@ -769,16 +783,14 @@ set(files __tuple/make_tuple_types.h __tuple/sfinae_helpers.h __tuple/tuple_element.h - __tuple/tuple_indices.h __tuple/tuple_like.h __tuple/tuple_like_ext.h __tuple/tuple_like_no_subrange.h __tuple/tuple_size.h __tuple/tuple_types.h __type_traits/add_cv_quals.h - __type_traits/add_lvalue_reference.h __type_traits/add_pointer.h - __type_traits/add_rvalue_reference.h + __type_traits/add_reference.h __type_traits/aligned_storage.h __type_traits/aligned_union.h __type_traits/alignment_of.h @@ -800,6 +812,7 @@ set(files __type_traits/extent.h __type_traits/has_unique_object_representation.h __type_traits/has_virtual_destructor.h + __type_traits/integer_traits.h __type_traits/integral_constant.h __type_traits/invoke.h __type_traits/is_abstract.h @@ -850,7 +863,6 @@ set(files __type_traits/is_same.h __type_traits/is_scalar.h __type_traits/is_signed.h - __type_traits/is_signed_integer.h __type_traits/is_specialization.h __type_traits/is_standard_layout.h __type_traits/is_swappable.h @@ -864,7 +876,6 @@ set(files __type_traits/is_unbounded_array.h __type_traits/is_union.h __type_traits/is_unsigned.h - __type_traits/is_unsigned_integer.h __type_traits/is_valid_expansion.h __type_traits/is_void.h __type_traits/is_volatile.h @@ -935,6 +946,7 @@ set(files __vector/vector_bool.h __vector/vector_bool_formatter.h __verbose_abort + __verbose_trap algorithm any array @@ -1560,6 +1572,7 @@ set(files __cxx03/__utility/unreachable.h __cxx03/__variant/monostate.h __cxx03/__verbose_abort + __cxx03/__verbose_trap __cxx03/algorithm __cxx03/array __cxx03/atomic @@ -1699,13 +1712,18 @@ 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) -target_link_libraries(cxx-headers INTERFACE libcxx-libc-headers libcxx-abi-headers) +target_link_libraries(cxx-headers INTERFACE runtimes-libc-headers libcxx-abi-headers) add_dependencies(cxx-headers generate-cxx-headers) # It's important that the arch directory be included first so that its header files # which interpose on the default include dir be included instead of the default ones. target_include_directories(cxx-headers INTERFACE ${LIBCXX_GENERATED_INCLUDE_TARGET_DIR} ${LIBCXX_GENERATED_INCLUDE_DIR}) +# Make sure to map the generated include directory back to libc++'s actual source directory when generating +# debug information. Otherwise, the debug information will refer to generated headers which are created during +# the build and generally not persistent. +target_add_compile_flags_if_supported(cxx-headers INTERFACE "-fdebug-prefix-map=${LIBCXX_GENERATED_INCLUDE_DIR}=${LIBCXX_SOURCE_DIR}/include") + if (LIBCXX_INSTALL_HEADERS) foreach(file ${files}) get_filename_component(dir ${file} DIRECTORY) diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/copy.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/copy.h index ea98031df1..63877281bf 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/copy.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/copy.h @@ -182,7 +182,7 @@ struct __copy_impl { } }; - template ::value, int> = 0> + template , int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> operator()(_InIter __first, _InIter __last, _OutIter __result) const { std::__for_each_segment(__first, __last, _CopySegment<_InIter, _OutIter>(__result)); @@ -192,7 +192,7 @@ struct __copy_impl { template ::value && - !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, + !__is_segmented_iterator_v<_InIter> && __is_segmented_iterator_v<_OutIter>, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> operator()(_InIter __first, _InIter __last, _OutIter __result) const { diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/copy_backward.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/copy_backward.h index 9f890645a4..807c64b55a 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/copy_backward.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/copy_backward.h @@ -170,7 +170,7 @@ struct __copy_backward_impl { return std::make_pair(std::move(__original_last_iter), std::move(__result)); } - template ::value, int> = 0> + template , int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> operator()(_InIter __first, _InIter __last, _OutIter __result) const { using _Traits = __segmented_iterator_traits<_InIter>; @@ -200,7 +200,7 @@ struct __copy_backward_impl { template ::value && - !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, + !__is_segmented_iterator_v<_InIter> && __is_segmented_iterator_v<_OutIter>, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> operator()(_InIter __first, _InIter __last, _OutIter __result) const { 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 a7d9374b3a..8c8cb5820f 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/find.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/find.h @@ -149,7 +149,7 @@ struct __find_segment; template ::value, int> = 0> + __enable_if_t<__is_segmented_iterator_v<_SegmentedIterator>, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _SegmentedIterator __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); diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/for_each.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/for_each.h index b6c2c7c056..e31fcae83a 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/for_each.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/for_each.h @@ -12,41 +12,54 @@ #include <__algorithm/for_each_segment.h> #include <__config> +#include <__functional/identity.h> #include <__iterator/segmented_iterator.h> #include <__type_traits/enable_if.h> +#include <__type_traits/invoke.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 -template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __for_each(_InputIterator __first, _Sent __last, _Func& __f) { +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator +__for_each(_InputIterator __first, _Sent __last, _Func& __f, _Proj& __proj) { for (; __first != __last; ++__first) - __f(*__first); + std::__invoke(__f, std::__invoke(__proj, *__first)); + return __first; } #ifndef _LIBCPP_CXX03_LANG template ::value, int> = 0> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void -__for_each(_SegmentedIterator __first, _SegmentedIterator __last, _Function& __func) { + class _Func, + class _Proj, + __enable_if_t<__is_segmented_iterator_v<_SegmentedIterator>, int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _SegmentedIterator +__for_each(_SegmentedIterator __first, _SegmentedIterator __last, _Func& __func, _Proj& __proj) { using __local_iterator_t = typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator; std::__for_each_segment(__first, __last, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) { - std::__for_each(__lfirst, __llast, __func); + std::__for_each(__lfirst, __llast, __func, __proj); }); + return __last; } #endif // !_LIBCPP_CXX03_LANG -template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Function -for_each(_InputIterator __first, _InputIterator __last, _Function __f) { - std::__for_each(__first, __last, __f); +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Func +for_each(_InputIterator __first, _InputIterator __last, _Func __f) { + __identity __proj; + std::__for_each(__first, __last, __f, __proj); return __f; } _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_FOR_EACH_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/for_each_n.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/for_each_n.h index 29351ec39f..04650e15b6 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/for_each_n.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/for_each_n.h @@ -13,10 +13,12 @@ #include <__algorithm/for_each.h> #include <__algorithm/for_each_n_segment.h> #include <__config> +#include <__functional/identity.h> #include <__iterator/iterator_traits.h> #include <__iterator/segmented_iterator.h> #include <__type_traits/disjunction.h> #include <__type_traits/enable_if.h> +#include <__type_traits/invoke.h> #include <__type_traits/negation.h> #include <__utility/convert_to_integral.h> #include <__utility/move.h> @@ -33,16 +35,17 @@ _LIBCPP_BEGIN_NAMESPACE_STD template ::value && - _Or< _Not<__is_segmented_iterator<_InputIterator> >, - _Not<__has_random_access_local_iterator<_InputIterator> > >::value, + _Or >, + _Not<__has_random_access_local_iterator<_InputIterator> > >::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator -__for_each_n(_InputIterator __first, _Size __orig_n, _Func& __f) { +__for_each_n(_InputIterator __first, _Size __orig_n, _Func& __f, _Proj& __proj) { typedef decltype(std::__convert_to_integral(__orig_n)) _IntegralSize; _IntegralSize __n = __orig_n; while (__n > 0) { - __f(*__first); + std::__invoke(__f, std::__invoke(__proj, *__first)); ++__first; --__n; } @@ -52,39 +55,42 @@ __for_each_n(_InputIterator __first, _Size __orig_n, _Func& __f) { template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandIter -__for_each_n(_RandIter __first, _Size __orig_n, _Func& __f) { +__for_each_n(_RandIter __first, _Size __orig_n, _Func& __f, _Proj& __proj) { typename std::iterator_traits<_RandIter>::difference_type __n = __orig_n; auto __last = __first + __n; - std::__for_each(__first, __last, __f); - return std::move(__last); + std::__for_each(__first, __last, __f, __proj); + return __last; } #ifndef _LIBCPP_CXX03_LANG template ::value && - __is_segmented_iterator<_SegmentedIterator>::value && + __is_segmented_iterator_v<_SegmentedIterator> && __has_random_access_iterator_category< typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _SegmentedIterator -__for_each_n(_SegmentedIterator __first, _Size __orig_n, _Func& __f) { +__for_each_n(_SegmentedIterator __first, _Size __orig_n, _Func& __f, _Proj& __proj) { using __local_iterator_t = typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator; return std::__for_each_n_segment(__first, __orig_n, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) { - std::__for_each(__lfirst, __llast, __f); + std::__for_each(__lfirst, __llast, __f, __proj); }); } #endif // !_LIBCPP_CXX03_LANG #if _LIBCPP_STD_VER >= 17 -template +template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator -for_each_n(_InputIterator __first, _Size __orig_n, _Function __f) { - return std::__for_each_n(__first, __orig_n, __f); +for_each_n(_InputIterator __first, _Size __orig_n, _Func __f) { + __identity __proj; + return std::__for_each_n(__first, __orig_n, __f, __proj); } #endif // _LIBCPP_STD_VER >= 17 diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/for_each_n_segment.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/for_each_n_segment.h index 1b522fb373..a433df5d09 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/for_each_n_segment.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/for_each_n_segment.h @@ -27,7 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _SegmentedIterator __for_each_n_segment(_SegmentedIterator __first, _Size __orig_n, _Functor __func) { - static_assert(__is_segmented_iterator<_SegmentedIterator>::value && + static_assert(__is_segmented_iterator_v<_SegmentedIterator> && __has_random_access_iterator_category< typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator>::value, "__for_each_n_segment only works with segmented iterators with random-access local iterators"); diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/move.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/move.h index a3320e9f19..73b780d9b1 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/move.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/move.h @@ -65,7 +65,7 @@ struct __move_impl { } }; - template ::value, int> = 0> + template , int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> operator()(_InIter __first, _InIter __last, _OutIter __result) const { std::__for_each_segment(__first, __last, _MoveSegment<_InIter, _OutIter>(__result)); @@ -75,7 +75,7 @@ struct __move_impl { template ::value && - !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, + !__is_segmented_iterator_v<_InIter> && __is_segmented_iterator_v<_OutIter>, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> operator()(_InIter __first, _InIter __last, _OutIter __result) const { diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/move_backward.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/move_backward.h index 14482fee18..e3e61c7bc1 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/move_backward.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/move_backward.h @@ -51,7 +51,7 @@ struct __move_backward_impl { return std::make_pair(std::move(__original_last_iter), std::move(__result)); } - template ::value, int> = 0> + template , int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> operator()(_InIter __first, _InIter __last, _OutIter __result) const { using _Traits = __segmented_iterator_traits<_InIter>; @@ -81,7 +81,7 @@ struct __move_backward_impl { template ::value && - !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, + !__is_segmented_iterator_v<_InIter> && __is_segmented_iterator_v<_OutIter>, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> operator()(_InIter __first, _InIter __last, _OutIter __result) const { diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_for_each.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_for_each.h index de39bc5522..e9c84e8583 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_for_each.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_for_each.h @@ -9,10 +9,12 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_FOR_EACH_H #define _LIBCPP___ALGORITHM_RANGES_FOR_EACH_H +#include <__algorithm/for_each.h> +#include <__algorithm/for_each_n.h> #include <__algorithm/in_fun_result.h> +#include <__concepts/assignable.h> #include <__config> #include <__functional/identity.h> -#include <__functional/invoke.h> #include <__iterator/concepts.h> #include <__iterator/projected.h> #include <__ranges/access.h> @@ -41,9 +43,17 @@ private: template _LIBCPP_HIDE_FROM_ABI constexpr static for_each_result<_Iter, _Func> __for_each_impl(_Iter __first, _Sent __last, _Func& __func, _Proj& __proj) { - for (; __first != __last; ++__first) - std::invoke(__func, std::invoke(__proj, *__first)); - return {std::move(__first), std::move(__func)}; + // In the case where we have different iterator and sentinel types, the segmented iterator optimization + // in std::for_each will not kick in. Therefore, we prefer std::for_each_n in that case (whenever we can + // obtain the `n`). + if constexpr (!std::assignable_from<_Iter&, _Sent> && std::sized_sentinel_for<_Sent, _Iter>) { + auto __n = __last - __first; + auto __end = std::__for_each_n(std::move(__first), __n, __func, __proj); + return {std::move(__end), std::move(__func)}; + } else { + auto __end = std::__for_each(std::move(__first), std::move(__last), __func, __proj); + return {std::move(__end), std::move(__func)}; + } } public: diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_for_each_n.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_for_each_n.h index 603cb72323..3aab1b79c1 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_for_each_n.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_for_each_n.h @@ -9,10 +9,10 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_FOR_EACH_N_H #define _LIBCPP___ALGORITHM_RANGES_FOR_EACH_N_H +#include <__algorithm/for_each_n.h> #include <__algorithm/in_fun_result.h> #include <__config> #include <__functional/identity.h> -#include <__functional/invoke.h> #include <__iterator/concepts.h> #include <__iterator/incrementable_traits.h> #include <__iterator/iterator_traits.h> @@ -40,11 +40,8 @@ struct __for_each_n { template > _Func> _LIBCPP_HIDE_FROM_ABI constexpr for_each_n_result<_Iter, _Func> operator()(_Iter __first, iter_difference_t<_Iter> __count, _Func __func, _Proj __proj = {}) const { - while (__count-- > 0) { - std::invoke(__func, std::invoke(__proj, *__first)); - ++__first; - } - return {std::move(__first), std::move(__func)}; + auto __last = std::__for_each_n(std::move(__first), __count, __func, __proj); + return {std::move(__last), std::move(__func)}; } }; 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 47942a09e6..07fef20f61 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 @@ -26,9 +26,7 @@ _LIBCPP_PUSH_MACROS #include <__undef_macros> // TODO: Find out how altivec changes things and allow vectorizations there too. -// TODO: Simplify this condition once we stop building with AppleClang 15 in the CI. -#if _LIBCPP_STD_VER >= 14 && defined(_LIBCPP_COMPILER_CLANG_BASED) && !defined(__ALTIVEC__) && \ - !(defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER < 1600) +#if _LIBCPP_STD_VER >= 14 && defined(_LIBCPP_COMPILER_CLANG_BASED) && !defined(__ALTIVEC__) # define _LIBCPP_HAS_ALGORITHM_VECTOR_UTILS 1 #else # define _LIBCPP_HAS_ALGORITHM_VECTOR_UTILS 0 diff --git a/naiveproxy/src/third_party/libc++/src/include/__assert b/naiveproxy/src/third_party/libc++/src/include/__assert index 90eaa60235..a9451daf47 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__assert +++ b/naiveproxy/src/third_party/libc++/src/include/__assert @@ -20,8 +20,8 @@ #define _LIBCPP_ASSERT(expression, message) \ (__builtin_expect(static_cast(expression), 1) \ ? (void)0 \ - : _LIBCPP_ASSERTION_HANDLER(__FILE__ ":" _LIBCPP_TOSTRING(__LINE__) ": assertion " _LIBCPP_TOSTRING( \ - expression) " failed: " message "\n")) + : _LIBCPP_ASSERTION_HANDLER(__FILE__ ":" _LIBCPP_TOSTRING( \ + __LINE__) ": libc++ Hardening assertion " _LIBCPP_TOSTRING(expression) " failed: " message "\n")) // WARNING: __builtin_assume can currently inhibit optimizations. Only add assumptions with a clear // optimization intent. See https://discourse.llvm.org/t/llvm-assume-blocks-optimization/71609 for a 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 cfd792dc2e..99881a8538 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 @@ -11,8 +11,8 @@ #include <__assert> #include <__bit/countl.h> -#include <__concepts/arithmetic.h> #include <__config> +#include <__type_traits/integer_traits.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -41,7 +41,7 @@ template # if _LIBCPP_STD_VER >= 20 -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[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 6bcbc53fb4..799a064130 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 @@ -10,8 +10,8 @@ #define _LIBCPP___BIT_BIT_FLOOR_H #include <__bit/bit_log2.h> -#include <__concepts/arithmetic.h> #include <__config> +#include <__type_traits/integer_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[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_log2.h b/naiveproxy/src/third_party/libc++/src/include/__bit/bit_log2.h index b22e1ce1f8..8077cd91d6 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__bit/bit_log2.h +++ b/naiveproxy/src/third_party/libc++/src/include/__bit/bit_log2.h @@ -11,7 +11,7 @@ #include <__bit/countl.h> #include <__config> -#include <__type_traits/is_unsigned_integer.h> +#include <__type_traits/integer_traits.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __bit_log2(_Tp __t) _NOEXCEPT { - static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__bit_log2 requires an unsigned integer type"); + static_assert(__is_unsigned_integer_v<_Tp>, "__bit_log2 requires an unsigned integer type"); return numeric_limits<_Tp>::digits - 1 - std::__countl_zero(__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 853e481776..75050acabb 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 @@ -10,8 +10,8 @@ #define _LIBCPP___BIT_BIT_WIDTH_H #include <__bit/bit_log2.h> -#include <__concepts/arithmetic.h> #include <__config> +#include <__type_traits/integer_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[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/countl.h b/naiveproxy/src/third_party/libc++/src/include/__bit/countl.h index 9499bf9b45..0759140208 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__bit/countl.h +++ b/naiveproxy/src/third_party/libc++/src/include/__bit/countl.h @@ -9,9 +9,8 @@ #ifndef _LIBCPP___BIT_COUNTL_H #define _LIBCPP___BIT_COUNTL_H -#include <__concepts/arithmetic.h> #include <__config> -#include <__type_traits/is_unsigned_integer.h> +#include <__type_traits/integer_traits.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -25,18 +24,18 @@ _LIBCPP_BEGIN_NAMESPACE_STD template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int __countl_zero(_Tp __t) _NOEXCEPT { - static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__countl_zero requires an unsigned integer type"); + static_assert(__is_unsigned_integer_v<_Tp>, "__countl_zero requires an unsigned integer type"); return __builtin_clzg(__t, numeric_limits<_Tp>::digits); } #if _LIBCPP_STD_VER >= 20 -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countl_zero(_Tp __t) noexcept { return std::__countl_zero(__t); } -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[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 7b311b8385..f6c98695d3 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__bit/countr.h +++ b/naiveproxy/src/third_party/libc++/src/include/__bit/countr.h @@ -9,9 +9,8 @@ #ifndef _LIBCPP___BIT_COUNTR_H #define _LIBCPP___BIT_COUNTR_H -#include <__concepts/arithmetic.h> #include <__config> -#include <__type_traits/is_unsigned.h> +#include <__type_traits/integer_traits.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -25,18 +24,18 @@ _LIBCPP_BEGIN_NAMESPACE_STD template [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __countr_zero(_Tp __t) _NOEXCEPT { - static_assert(is_unsigned<_Tp>::value, "__countr_zero only works with unsigned types"); + static_assert(__is_unsigned_integer_v<_Tp>, "__countr_zero only works with unsigned types"); return __builtin_ctzg(__t, numeric_limits<_Tp>::digits); } #if _LIBCPP_STD_VER >= 20 -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { return std::__countr_zero(__t); } -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[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 52f5853a1b..b43e69323e 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 @@ -9,8 +9,8 @@ #ifndef _LIBCPP___BIT_HAS_SINGLE_BIT_H #define _LIBCPP___BIT_HAS_SINGLE_BIT_H -#include <__concepts/arithmetic.h> #include <__config> +#include <__type_traits/integer_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -23,7 +23,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[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 9ae572d466..8d9ba09938 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__bit/popcount.h +++ b/naiveproxy/src/third_party/libc++/src/include/__bit/popcount.h @@ -9,9 +9,8 @@ #ifndef _LIBCPP___BIT_POPCOUNT_H #define _LIBCPP___BIT_POPCOUNT_H -#include <__concepts/arithmetic.h> #include <__config> -#include <__type_traits/is_unsigned.h> +#include <__type_traits/integer_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -24,13 +23,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD template [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __popcount(_Tp __t) _NOEXCEPT { - static_assert(is_unsigned<_Tp>::value, "__popcount only works with unsigned types"); + static_assert(__is_unsigned_integer_v<_Tp>, "__popcount only works with unsigned types"); return __builtin_popcountg(__t); } #if _LIBCPP_STD_VER >= 20 -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int popcount(_Tp __t) noexcept { return std::__popcount(__t); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__bit/rotate.h b/naiveproxy/src/third_party/libc++/src/include/__bit/rotate.h index d79d98de29..c6f34bdaf6 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__bit/rotate.h +++ b/naiveproxy/src/third_party/libc++/src/include/__bit/rotate.h @@ -9,9 +9,8 @@ #ifndef _LIBCPP___BIT_ROTATE_H #define _LIBCPP___BIT_ROTATE_H -#include <__concepts/arithmetic.h> #include <__config> -#include <__type_traits/is_unsigned_integer.h> +#include <__type_traits/integer_traits.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -25,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // the rotr function becomes the ROR instruction. template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __rotl(_Tp __x, int __s) _NOEXCEPT { - static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__rotl requires an unsigned integer type"); + static_assert(__is_unsigned_integer_v<_Tp>, "__rotl requires an unsigned integer type"); const int __n = numeric_limits<_Tp>::digits; int __r = __s % __n; @@ -40,7 +39,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __rotl(_Tp __x, int __s) template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __rotr(_Tp __x, int __s) _NOEXCEPT { - static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__rotr requires an unsigned integer type"); + static_assert(__is_unsigned_integer_v<_Tp>, "__rotr requires an unsigned integer type"); const int __n = numeric_limits<_Tp>::digits; int __r = __s % __n; @@ -55,12 +54,12 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __rotr(_Tp __x, int __s) #if _LIBCPP_STD_VER >= 20 -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp rotl(_Tp __t, int __cnt) noexcept { return std::__rotl(__t, __cnt); } -template <__libcpp_unsigned_integer _Tp> +template <__unsigned_integer _Tp> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp rotr(_Tp __t, int __cnt) noexcept { return std::__rotr(__t, __cnt); } 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 86b606d278..49758397f6 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__chrono/formatter.h +++ b/naiveproxy/src/third_party/libc++/src/include/__chrono/formatter.h @@ -50,12 +50,14 @@ # include <__format/formatter.h> # include <__format/parser_std_format_spec.h> # include <__format/write_escaped.h> +# include <__iterator/istreambuf_iterator.h> +# include <__iterator/ostreambuf_iterator.h> +# include <__locale_dir/time.h> # include <__memory/addressof.h> # include <__type_traits/is_specialization.h> # include # include # include -# include # include # include 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 6b866b882f..fc4408d23d 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 @@ -58,6 +58,19 @@ public: // arithmetic +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI constexpr time_point& operator++() { + ++__d_; + return *this; + } + _LIBCPP_HIDE_FROM_ABI constexpr time_point operator++(int) { return time_point{__d_++}; } + _LIBCPP_HIDE_FROM_ABI constexpr time_point& operator--() { + --__d_; + return *this; + } + _LIBCPP_HIDE_FROM_ABI constexpr time_point operator--(int) { return time_point{__d_--}; } +#endif // _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 time_point& operator+=(const duration& __d) { __d_ += __d; return *this; diff --git a/naiveproxy/src/third_party/libc++/src/include/__concepts/arithmetic.h b/naiveproxy/src/third_party/libc++/src/include/__concepts/arithmetic.h index 0c44f11780..64c0200783 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__concepts/arithmetic.h +++ b/naiveproxy/src/third_party/libc++/src/include/__concepts/arithmetic.h @@ -13,8 +13,6 @@ #include <__type_traits/is_floating_point.h> #include <__type_traits/is_integral.h> #include <__type_traits/is_signed.h> -#include <__type_traits/is_signed_integer.h> -#include <__type_traits/is_unsigned_integer.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -38,17 +36,6 @@ concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>; template concept floating_point = is_floating_point_v<_Tp>; -// Concept helpers for the internal type traits for the fundamental types. - -template -concept __libcpp_unsigned_integer = __libcpp_is_unsigned_integer<_Tp>::value; - -template -concept __libcpp_signed_integer = __libcpp_is_signed_integer<_Tp>::value; - -template -concept __libcpp_integer = __libcpp_unsigned_integer<_Tp> || __libcpp_signed_integer<_Tp>; - #endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/naiveproxy/src/third_party/libc++/src/include/__concepts/common_with.h b/naiveproxy/src/third_party/libc++/src/include/__concepts/common_with.h index 85abb05efb..09082b2295 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__concepts/common_with.h +++ b/naiveproxy/src/third_party/libc++/src/include/__concepts/common_with.h @@ -12,7 +12,7 @@ #include <__concepts/common_reference_with.h> #include <__concepts/same_as.h> #include <__config> -#include <__type_traits/add_lvalue_reference.h> +#include <__type_traits/add_reference.h> #include <__type_traits/common_reference.h> #include <__type_traits/common_type.h> #include <__utility/declval.h> diff --git a/naiveproxy/src/third_party/libc++/src/include/__config b/naiveproxy/src/third_party/libc++/src/include/__config index 110450f6e9..77a71b6cf1 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__config +++ b/naiveproxy/src/third_party/libc++/src/include/__config @@ -28,7 +28,7 @@ // _LIBCPP_VERSION represents the version of libc++, which matches the version of LLVM. // Given a LLVM release LLVM XX.YY.ZZ (e.g. LLVM 17.0.1 == 17.00.01), _LIBCPP_VERSION is // defined to XXYYZZ. -# define _LIBCPP_VERSION 210000 +# define _LIBCPP_VERSION 220000 # define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y # define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y) @@ -38,11 +38,47 @@ # define _LIBCPP_FREESTANDING # endif +// NOLINTNEXTLINE(libcpp-cpp-version-check) +# if __cplusplus < 201103L +# define _LIBCPP_CXX03_LANG +# endif + +# if __has_feature(experimental_library) +# ifndef _LIBCPP_ENABLE_EXPERIMENTAL +# define _LIBCPP_ENABLE_EXPERIMENTAL +# endif +# endif + +// Incomplete features get their own specific disabling flags. This makes it +// easier to grep for target specific flags once the feature is complete. +# if defined(_LIBCPP_ENABLE_EXPERIMENTAL) || defined(_LIBCPP_BUILDING_LIBRARY) +# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 1 +# else +# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 0 +# endif + +# define _LIBCPP_HAS_EXPERIMENTAL_PSTL _LIBCPP_HAS_EXPERIMENTAL_LIBRARY +# define _LIBCPP_HAS_EXPERIMENTAL_TZDB _LIBCPP_HAS_EXPERIMENTAL_LIBRARY +# define _LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM _LIBCPP_HAS_EXPERIMENTAL_LIBRARY +# define _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC _LIBCPP_HAS_EXPERIMENTAL_LIBRARY + // HARDENING { -// TODO: Remove in LLVM 21. We're making this an error to catch folks who might not have migrated. -# ifdef _LIBCPP_ENABLE_ASSERTIONS -# error "_LIBCPP_ENABLE_ASSERTIONS has been removed, please use _LIBCPP_HARDENING_MODE instead" +// TODO(LLVM 23): Remove this. We're making these an error to catch folks who might not have migrated. +// Since hardening went through several changes (many of which impacted user-facing macros), +// we're keeping these checks around for a bit longer than usual. Failure to properly configure +// hardening results in checks being dropped silently, which is a pretty big deal. +# if defined(_LIBCPP_ENABLE_ASSERTIONS) +# error "_LIBCPP_ENABLE_ASSERTIONS has been removed, please use _LIBCPP_HARDENING_MODE= instead (see docs)" +# endif +# if defined(_LIBCPP_ENABLE_HARDENED_MODE) +# error "_LIBCPP_ENABLE_HARDENED_MODE has been removed, please use _LIBCPP_HARDENING_MODE= instead (see docs)" +# endif +# if defined(_LIBCPP_ENABLE_SAFE_MODE) +# error "_LIBCPP_ENABLE_SAFE_MODE has been removed, please use _LIBCPP_HARDENING_MODE= instead (see docs)" +# endif +# if defined(_LIBCPP_ENABLE_DEBUG_MODE) +# error "_LIBCPP_ENABLE_DEBUG_MODE has been removed, please use _LIBCPP_HARDENING_MODE= instead (see docs)" # endif // The library provides the macro `_LIBCPP_HARDENING_MODE` which can be set to one of the following values: @@ -147,16 +183,53 @@ _LIBCPP_HARDENING_MODE_EXTENSIVE, \ _LIBCPP_HARDENING_MODE_DEBUG # endif +// Hardening assertion semantics generally mirror the evaluation semantics of C++26 Contracts: +// - `ignore` evaluates the assertion but doesn't do anything if it fails (note that it differs from the Contracts +// `ignore` semantic which wouldn't evaluate the assertion at all); +// - `observe` logs an error (indicating, if possible, that the error is fatal) and continues execution; +// - `quick-enforce` terminates the program as fast as possible (via trapping); +// - `enforce` logs an error and then terminates the program. +// +// Notes: +// - Continuing execution after a hardening check fails results in undefined behavior; the `observe` semantic is meant +// to make adopting hardening easier but should not be used outside of this scenario; +// - C++26 wording for Library Hardening precludes a conforming Hardened implementation from using the Contracts +// `ignore` semantic when evaluating hardened preconditions in the Library. Libc++ allows using this semantic for +// hardened preconditions, however, be aware that using `ignore` does not produce a conforming "Hardened" +// implementation, unlike the other semantics above. +// clang-format off +# define _LIBCPP_ASSERTION_SEMANTIC_IGNORE (1 << 1) +# define _LIBCPP_ASSERTION_SEMANTIC_OBSERVE (1 << 2) +# define _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE (1 << 3) +# define _LIBCPP_ASSERTION_SEMANTIC_ENFORCE (1 << 4) +// clang-format on + +// Allow users to define an arbitrary assertion semantic; otherwise, use the default mapping from modes to semantics. +// The default is for production-capable modes to use `quick-enforce` (i.e., trap) and for the `debug` mode to use +// `enforce` (i.e., log and abort). +# ifndef _LIBCPP_ASSERTION_SEMANTIC + +# if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG +# define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_ENFORCE +# else +# define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE +# endif + +# else +# if !_LIBCPP_HAS_EXPERIMENTAL_LIBRARY +# error "Assertion semantics are an experimental feature." +# endif +# if defined(_LIBCPP_CXX03_LANG) +# error "Assertion semantics are not available in the C++03 mode." +# endif + +# endif // _LIBCPP_ASSERTION_SEMANTIC + // } HARDENING # define _LIBCPP_TOSTRING2(x) #x # define _LIBCPP_TOSTRING(x) _LIBCPP_TOSTRING2(x) -// NOLINTNEXTLINE(libcpp-cpp-version-check) -# if __cplusplus < 201103L -# define _LIBCPP_CXX03_LANG -# endif - # ifndef __has_constexpr_builtin # define __has_constexpr_builtin(x) 0 # endif @@ -190,24 +263,6 @@ _LIBCPP_HARDENING_MODE_DEBUG # define _LIBCPP_ABI_VCRUNTIME # endif -# if __has_feature(experimental_library) -# ifndef _LIBCPP_ENABLE_EXPERIMENTAL -# define _LIBCPP_ENABLE_EXPERIMENTAL -# endif -# endif - -// Incomplete features get their own specific disabling flags. This makes it -// easier to grep for target specific flags once the feature is complete. -# if defined(_LIBCPP_ENABLE_EXPERIMENTAL) || defined(_LIBCPP_BUILDING_LIBRARY) -# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 1 -# else -# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 0 -# endif - -# define _LIBCPP_HAS_EXPERIMENTAL_PSTL _LIBCPP_HAS_EXPERIMENTAL_LIBRARY -# define _LIBCPP_HAS_EXPERIMENTAL_TZDB _LIBCPP_HAS_EXPERIMENTAL_LIBRARY -# define _LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM _LIBCPP_HAS_EXPERIMENTAL_LIBRARY - # if defined(__MVS__) # include // for __NATIVE_ASCII_F # endif @@ -265,13 +320,6 @@ _LIBCPP_HARDENING_MODE_DEBUG // When this option is used, the token passed to `std::random_device`'s // constructor *must* be "/dev/urandom" -- anything else is an error. // -// _LIBCPP_USING_NACL_RANDOM -// NaCl's sandbox (which PNaCl also runs in) doesn't allow filesystem access, -// including accesses to the special files under `/dev`. This implementation -// uses the NaCL syscall `nacl_secure_random_init()` to get entropy. -// When this option is used, the token passed to `std::random_device`'s -// constructor *must* be "/dev/urandom" -- anything else is an error. -// // _LIBCPP_USING_WIN32_RANDOM // Use rand_s(), for use on Windows. // When this option is used, the token passed to `std::random_device`'s @@ -283,8 +331,6 @@ _LIBCPP_HARDENING_MODE_DEBUG # define _LIBCPP_USING_GETENTROPY # elif defined(__Fuchsia__) # define _LIBCPP_USING_FUCHSIA_CPRNG -# elif defined(__native_client__) -# define _LIBCPP_USING_NACL_RANDOM # elif defined(_LIBCPP_WIN32API) # define _LIBCPP_USING_WIN32_RANDOM # else @@ -319,37 +365,12 @@ typedef __char32_t char32_t; # define _LIBCPP_PREFERRED_ALIGNOF(_Tp) __alignof(_Tp) -// Objective-C++ features (opt-in) -# if __has_feature(objc_arc) -# define _LIBCPP_HAS_OBJC_ARC 1 -# else -# define _LIBCPP_HAS_OBJC_ARC 0 -# endif - -# if __has_feature(objc_arc_weak) -# define _LIBCPP_HAS_OBJC_ARC_WEAK 1 -# else -# define _LIBCPP_HAS_OBJC_ARC_WEAK 0 -# endif - -# if __has_extension(blocks) -# define _LIBCPP_HAS_EXTENSION_BLOCKS 1 -# else -# define _LIBCPP_HAS_EXTENSION_BLOCKS 0 -# endif - -# if _LIBCPP_HAS_EXTENSION_BLOCKS && defined(__APPLE__) +# if __has_extension(blocks) && defined(__APPLE__) # define _LIBCPP_HAS_BLOCKS_RUNTIME 1 # else # define _LIBCPP_HAS_BLOCKS_RUNTIME 0 # endif -# if __has_feature(address_sanitizer) -# define _LIBCPP_HAS_ASAN 1 -# else -# define _LIBCPP_HAS_ASAN 0 -# endif - # define _LIBCPP_ALWAYS_INLINE __attribute__((__always_inline__)) # if defined(_LIBCPP_OBJECT_FORMAT_COFF) @@ -441,6 +462,12 @@ typedef __char32_t char32_t; # define _LIBCPP_GCC_DIAGNOSTIC_IGNORED(str) # endif +// Macros to enter and leave a state where deprecation warnings are suppressed. +# define _LIBCPP_SUPPRESS_DEPRECATED_PUSH \ + _LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wdeprecated") \ + _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wdeprecated-declarations") +# define _LIBCPP_SUPPRESS_DEPRECATED_POP _LIBCPP_DIAGNOSTIC_POP + # if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_FAST # define _LIBCPP_HARDENING_SIG f # elif _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_EXTENSIVE @@ -530,13 +557,6 @@ typedef __char32_t char32_t; # define _LIBCPP_HIDE_FROM_ABI_AFTER_V1 _LIBCPP_HIDE_FROM_ABI # 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 - // Clang modules take a significant compile time hit when pushing and popping diagnostics. // Since all the headers are marked as system headers unless _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER is defined, we can // simply disable this pushing and popping when _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER isn't defined. @@ -547,7 +567,7 @@ typedef __char32_t char32_t; _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++14-extensions") \ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++17-extensions") \ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++20-extensions") \ - _LIBCPP_CLANG_DIAGNOSTIC_IGNORED_CXX23_EXTENSION \ + _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++23-extensions") \ _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++14-extensions") \ _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++17-extensions") \ _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++20-extensions") \ @@ -671,10 +691,6 @@ typedef __char32_t char32_t; # define _LIBCPP_HAS_C11_ALIGNED_ALLOC 1 # endif -# if defined(__APPLE__) || defined(__FreeBSD__) -# define _LIBCPP_HAS_DEFAULTRUNELOCALE -# endif - # if defined(__APPLE__) || defined(__FreeBSD__) # define _LIBCPP_WCTYPE_IS_MASK # endif @@ -749,17 +765,6 @@ typedef __char32_t char32_t; # define _LIBCPP_DEPRECATED_WITH_CHAR8_T # endif -// Macros to enter and leave a state where deprecation warnings are suppressed. -# if defined(_LIBCPP_COMPILER_CLANG_BASED) || defined(_LIBCPP_COMPILER_GCC) -# define _LIBCPP_SUPPRESS_DEPRECATED_PUSH \ - _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wdeprecated\"") \ - _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") -# define _LIBCPP_SUPPRESS_DEPRECATED_POP _Pragma("GCC diagnostic pop") -# else -# define _LIBCPP_SUPPRESS_DEPRECATED_PUSH -# define _LIBCPP_SUPPRESS_DEPRECATED_POP -# endif - # if _LIBCPP_STD_VER <= 11 # define _LIBCPP_EXPLICIT_SINCE_CXX14 # else @@ -935,23 +940,6 @@ typedef __char32_t char32_t; # define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS # endif -// Work around the attribute handling in clang. When both __declspec and -// __attribute__ are present, the processing goes awry preventing the definition -// of the types. In MinGW mode, __declspec evaluates to __attribute__, and thus -// combining the two does work. -# if defined(_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS) && defined(__clang__) && \ - __has_attribute(acquire_capability) && !defined(_MSC_VER) -# define _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS 1 -# else -# define _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS 0 -# endif - -# if _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS -# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x)) -# else -# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) -# endif - # if _LIBCPP_STD_VER >= 20 # define _LIBCPP_CONSTINIT constinit # elif __has_attribute(__require_constant_initialization__) @@ -1148,6 +1136,20 @@ typedef __char32_t char32_t; # define _LIBCPP_DIAGNOSE_WARNING(...) # endif +# if __has_attribute(__diagnose_if__) && !defined(_LIBCPP_APPLE_CLANG_VER) && \ + (!defined(_LIBCPP_CLANG_VER) || _LIBCPP_CLANG_VER >= 2001) +# define _LIBCPP_DIAGNOSE_IF(...) __attribute__((__diagnose_if__(__VA_ARGS__))) +# else +# define _LIBCPP_DIAGNOSE_IF(...) +# endif + +# define _LIBCPP_DIAGNOSE_NULLPTR_IF(condition, condition_description) \ + _LIBCPP_DIAGNOSE_IF( \ + condition, \ + "null passed to callee that requires a non-null argument" condition_description, \ + "warning", \ + "nonnull") + # if __has_cpp_attribute(_Clang::__lifetimebound__) # define _LIBCPP_LIFETIMEBOUND [[_Clang::__lifetimebound__]] # else @@ -1179,6 +1181,60 @@ typedef __char32_t char32_t; # define _LIBCPP_PREFERRED_NAME(x) # endif +# if __has_cpp_attribute(_Clang::__scoped_lockable__) +# define _LIBCPP_SCOPED_LOCKABLE [[_Clang::__scoped_lockable__]] +# else +# define _LIBCPP_SCOPED_LOCKABLE +# endif + +# if __has_cpp_attribute(_Clang::__capability__) +# define _LIBCPP_CAPABILITY(...) [[_Clang::__capability__(__VA_ARGS__)]] +# else +# define _LIBCPP_CAPABILITY(...) +# endif + +# if __has_attribute(__acquire_capability__) +# define _LIBCPP_ACQUIRE_CAPABILITY(...) __attribute__((__acquire_capability__(__VA_ARGS__))) +# else +# define _LIBCPP_ACQUIRE_CAPABILITY(...) +# endif + +# if __has_cpp_attribute(_Clang::__try_acquire_capability__) +# define _LIBCPP_TRY_ACQUIRE_CAPABILITY(...) [[_Clang::__try_acquire_capability__(__VA_ARGS__)]] +# else +# define _LIBCPP_TRY_ACQUIRE_CAPABILITY(...) +# endif + +# if __has_cpp_attribute(_Clang::__acquire_shared_capability__) +# define _LIBCPP_ACQUIRE_SHARED_CAPABILITY [[_Clang::__acquire_shared_capability__]] +# else +# define _LIBCPP_ACQUIRE_SHARED_CAPABILITY +# endif + +# if __has_cpp_attribute(_Clang::__try_acquire_shared_capability__) +# define _LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(...) [[_Clang::__try_acquire_shared_capability__(__VA_ARGS__)]] +# else +# define _LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(...) +# endif + +# if __has_cpp_attribute(_Clang::__release_capability__) +# define _LIBCPP_RELEASE_CAPABILITY [[_Clang::__release_capability__]] +# else +# define _LIBCPP_RELEASE_CAPABILITY +# endif + +# if __has_cpp_attribute(_Clang::__release_shared_capability__) +# define _LIBCPP_RELEASE_SHARED_CAPABILITY [[_Clang::__release_shared_capability__]] +# else +# define _LIBCPP_RELEASE_SHARED_CAPABILITY +# endif + +# if __has_attribute(__requires_capability__) +# define _LIBCPP_REQUIRES_CAPABILITY(...) __attribute__((__requires_capability__(__VA_ARGS__))) +# else +# define _LIBCPP_REQUIRES_CAPABILITY(...) +# endif + # if defined(_LIBCPP_ABI_MICROSOFT) && __has_declspec_attribute(empty_bases) # define _LIBCPP_DECLSPEC_EMPTY_BASES __declspec(empty_bases) # else 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 fc01aaf2d8..b68c0c8258 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__config_site.in +++ b/naiveproxy/src/third_party/libc++/src/include/__config_site.in @@ -30,7 +30,6 @@ #cmakedefine01 _LIBCPP_HAS_LOCALIZATION #cmakedefine01 _LIBCPP_HAS_UNICODE #cmakedefine01 _LIBCPP_HAS_WIDE_CHARACTERS -#cmakedefine _LIBCPP_HAS_NO_STD_MODULES #cmakedefine01 _LIBCPP_HAS_TIME_ZONE_DATABASE #cmakedefine01 _LIBCPP_INSTRUMENTED_WITH_ASAN diff --git a/naiveproxy/src/third_party/libc++/src/include/__configuration/abi.h b/naiveproxy/src/third_party/libc++/src/include/__configuration/abi.h index cc4b930b3c..a75cd0a675 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__configuration/abi.h +++ b/naiveproxy/src/third_party/libc++/src/include/__configuration/abi.h @@ -38,84 +38,47 @@ #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 -// 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 +// TODO: Move the description of the remaining ABI flags to ABIGuarantees.rst or remove them. + +// 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 // 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. + +// In LLVM 20, we've changed to take these ABI breaks unconditionally. These flags only exist in case someone is running +// into the static_asserts we added to catch the ABI break and don't care that it is one. +// TODO(LLVM 22): Remove these flags +# define _LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB +# define _LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB +# define _LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB +# define _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB + +// These flags are documented in ABIGuarantees.rst +# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT +# define _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON +# define _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON # 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_ENABLE_SHARED_PTR_TRIVIAL_ABI +# define _LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI +# define _LIBCPP_ABI_FIX_CITYHASH_IMPLEMENTATION +# define _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE +# define _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE +# define _LIBCPP_ABI_IOS_ALLOW_ARBITRARY_FILL_VALUE +# define _LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING +# define _LIBCPP_ABI_NO_FILESYSTEM_INLINE_NAMESPACE +# define _LIBCPP_ABI_NO_ITERATOR_BASES +# define _LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT +# define _LIBCPP_ABI_OPTIMIZED_FUNCTION +# define _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO +# define _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION # 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 -// std::basic_ios uses WEOF to indicate that the fill value is -// uninitialized. However, on platforms where the size of char_type is -// equal to or greater than the size of int_type and char_type is unsigned, -// std::char_traits::eq_int_type() cannot distinguish between WEOF -// and WCHAR_MAX. This ABI setting determines whether we should instead track whether the fill -// value has been initialized using a separate boolean, which changes the ABI. -# define _LIBCPP_ABI_IOS_ALLOW_ARBITRARY_FILL_VALUE -// Historically, libc++ used a type called `__compressed_pair` to reduce storage needs in cases of empty types (e.g. an -// empty allocator in std::vector). We switched to using `[[no_unique_address]]`. However, for ABI compatibility reasons -// we had to add artificial padding in a few places. -// -// This setting disables the addition of such artificial padding, leading to a more optimal -// representation for several types. -# define _LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING +# define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION + #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 @@ -145,35 +108,6 @@ // 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 - -// Changes the iterator type of `basic_string` to a bounded iterator that keeps track of whether it's within the bounds -// of the original container and asserts it on every dereference and when performing iterator arithmetics. -// -// ABI impact: changes the iterator type of `basic_string` and its specializations, such as `string` and `wstring`. -// #define _LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING - -// Changes the iterator type of `vector` to a bounded iterator that keeps track of whether it's within the bounds of the -// original container and asserts it on every dereference and when performing iterator arithmetics. Note: this doesn't -// yet affect `vector`. -// -// ABI impact: changes the iterator type of `vector` (except `vector`). -// #define _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR - -// Changes the iterator type of `array` to a bounded iterator that keeps track of whether it's within the bounds of the -// container and asserts it on every dereference and when performing iterator arithmetic. -// -// ABI impact: changes the iterator type of `array`, its size and its layout. -// #define _LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY - // [[msvc::no_unique_address]] seems to mostly affect empty classes, so the padding scheme for Itanium doesn't work. #if defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING) # define _LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING diff --git a/naiveproxy/src/third_party/libc++/src/include/__configuration/compiler.h b/naiveproxy/src/third_party/libc++/src/include/__configuration/compiler.h index 4b6c6cad35..11c07ed0dc 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__configuration/compiler.h +++ b/naiveproxy/src/third_party/libc++/src/include/__configuration/compiler.h @@ -37,7 +37,7 @@ # warning "Libc++ only supports Clang 19 and later" # endif # elif defined(_LIBCPP_APPLE_CLANG_VER) -# if _LIBCPP_APPLE_CLANG_VER < 1500 +# if _LIBCPP_APPLE_CLANG_VER < 1600 # warning "Libc++ only supports AppleClang 15 and later" # endif # elif defined(_LIBCPP_GCC_VER) diff --git a/naiveproxy/src/third_party/libc++/src/include/__coroutine/coroutine_handle.h b/naiveproxy/src/third_party/libc++/src/include/__coroutine/coroutine_handle.h index 88848544cf..b7add25851 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__coroutine/coroutine_handle.h +++ b/naiveproxy/src/third_party/libc++/src/include/__coroutine/coroutine_handle.h @@ -172,6 +172,6 @@ struct hash> { _LIBCPP_END_NAMESPACE_STD -#endif // __LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___COROUTINE_COROUTINE_HANDLE_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__coroutine/coroutine_traits.h b/naiveproxy/src/third_party/libc++/src/include/__coroutine/coroutine_traits.h index 78f05341f7..60f7ca2311 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__coroutine/coroutine_traits.h +++ b/naiveproxy/src/third_party/libc++/src/include/__coroutine/coroutine_traits.h @@ -43,6 +43,6 @@ struct coroutine_traits : public __coroutine_traits_sfinae<_Ret> {}; _LIBCPP_END_NAMESPACE_STD -#endif // __LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___COROUTINE_COROUTINE_TRAITS_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__coroutine/noop_coroutine_handle.h b/naiveproxy/src/third_party/libc++/src/include/__coroutine/noop_coroutine_handle.h index c95d85d548..2b2838b6bf 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__coroutine/noop_coroutine_handle.h +++ b/naiveproxy/src/third_party/libc++/src/include/__coroutine/noop_coroutine_handle.h @@ -94,6 +94,6 @@ inline _LIBCPP_HIDE_FROM_ABI noop_coroutine_handle noop_coroutine() noexcept { r _LIBCPP_END_NAMESPACE_STD -#endif // __LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___COROUTINE_NOOP_COROUTINE_HANDLE_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__coroutine/trivial_awaitables.h b/naiveproxy/src/third_party/libc++/src/include/__coroutine/trivial_awaitables.h index b604bd3c2d..7cb7f4dfeb 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__coroutine/trivial_awaitables.h +++ b/naiveproxy/src/third_party/libc++/src/include/__coroutine/trivial_awaitables.h @@ -35,6 +35,6 @@ struct suspend_always { _LIBCPP_END_NAMESPACE_STD -#endif // __LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 #endif // __LIBCPP___COROUTINE_TRIVIAL_AWAITABLES_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__cxx03/__config b/naiveproxy/src/third_party/libc++/src/include/__cxx03/__config index ef47327d96..9b88a49505 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__cxx03/__config +++ b/naiveproxy/src/third_party/libc++/src/include/__cxx03/__config @@ -152,6 +152,10 @@ _LIBCPP_HARDENING_MODE_EXTENSIVE, \ _LIBCPP_HARDENING_MODE_DEBUG # endif +# ifdef _LIBCPP_ASSERTION_SEMANTIC +# error "Assertion semantics are not available in the C++03 mode." +# endif + // } HARDENING # define _LIBCPP_TOSTRING2(x) #x diff --git a/naiveproxy/src/third_party/libc++/src/include/__cxx03/__math/logarithms.h b/naiveproxy/src/third_party/libc++/src/include/__cxx03/__math/logarithms.h index 2547350143..9b9e59a5a7 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__cxx03/__math/logarithms.h +++ b/naiveproxy/src/third_party/libc++/src/include/__cxx03/__math/logarithms.h @@ -58,7 +58,7 @@ inline _LIBCPP_HIDE_FROM_ABI double log10(_A1 __x) _NOEXCEPT { inline _LIBCPP_HIDE_FROM_ABI int ilogb(float __x) _NOEXCEPT { return __builtin_ilogbf(__x); } template -_LIBCPP_HIDE_FROM_ABI double ilogb(double __x) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI int ilogb(double __x) _NOEXCEPT { return __builtin_ilogb(__x); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__cxx03/__thread/support/windows.h b/naiveproxy/src/third_party/libc++/src/include/__cxx03/__thread/support/windows.h index 45252a57ef..f9facbeefe 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__cxx03/__thread/support/windows.h +++ b/naiveproxy/src/third_party/libc++/src/include/__cxx03/__thread/support/windows.h @@ -28,12 +28,10 @@ using __libcpp_timespec_t = ::timespec; typedef void* __libcpp_mutex_t; #define _LIBCPP_MUTEX_INITIALIZER 0 -#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__) -typedef void* __libcpp_recursive_mutex_t[6]; -#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__) +#if defined(_WIN64) typedef void* __libcpp_recursive_mutex_t[5]; #else -# error Unsupported architecture +typedef void* __libcpp_recursive_mutex_t[6]; #endif _LIBCPP_EXPORTED_FROM_ABI int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t* __m); diff --git a/naiveproxy/src/third_party/libc++/src/include/__cxx03/__verbose_trap b/naiveproxy/src/third_party/libc++/src/include/__cxx03/__verbose_trap new file mode 100644 index 0000000000..755124b97a --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__cxx03/__verbose_trap @@ -0,0 +1,36 @@ +// -*- 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___CXX03___VERBOSE_TRAP +#define _LIBCPP___CXX03___VERBOSE_TRAP + +#include <__cxx03/__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if __has_builtin(__builtin_verbose_trap) +// AppleClang shipped a slightly different version of __builtin_verbose_trap from the upstream +// version before upstream Clang actually got the builtin. +// TODO: Remove once AppleClang supports the two-arguments version of the builtin. +# if defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER < 1700 +# define _LIBCPP_VERBOSE_TRAP(message) __builtin_verbose_trap(message) +# else +# define _LIBCPP_VERBOSE_TRAP(message) __builtin_verbose_trap("libc++", message) +# endif +#else +# define _LIBCPP_VERBOSE_TRAP(message) ((void)message, __builtin_trap()) +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CXX03___VERBOSE_TRAP 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 index 73d192711e..058feab026 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__debug_utils/sanitizers.h +++ b/naiveproxy/src/third_party/libc++/src/include/__debug_utils/sanitizers.h @@ -17,7 +17,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_HAS_ASAN +#if __has_feature(address_sanitizer) extern "C" { _LIBCPP_EXPORTED_FROM_ABI void @@ -28,12 +28,12 @@ _LIBCPP_EXPORTED_FROM_ABI int __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, const void*, const void*); } -#endif // _LIBCPP_HAS_ASAN +#endif // __has_feature(address_sanitizer) _LIBCPP_BEGIN_NAMESPACE_STD // ASan choices -#if _LIBCPP_HAS_ASAN +#if __has_feature(address_sanitizer) # define _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS 1 #endif @@ -57,7 +57,7 @@ _LIBCPP_HIDE_FROM_ABI void __annotate_double_ended_contiguous_container( const void* __last_old_contained, const void* __first_new_contained, const void* __last_new_contained) { -#if !_LIBCPP_HAS_ASAN +#if !__has_feature(address_sanitizer) (void)__first_storage; (void)__last_storage; (void)__first_old_contained; @@ -86,7 +86,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __annotate_contiguous_c const void* __last_storage, const void* __old_last_contained, const void* __new_last_contained) { -#if !_LIBCPP_HAS_ASAN +#if !__has_feature(address_sanitizer) (void)__first_storage; (void)__last_storage; (void)__old_last_contained; 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 b1fe9a1299..796fa924be 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 @@ -15,6 +15,7 @@ #include <__memory/addressof.h> #include <__memory/construct_at.h> #include <__type_traits/decay.h> +#include <__type_traits/is_pointer.h> #include #include @@ -62,7 +63,7 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { static exception_ptr __from_native_exception_pointer(void*) _NOEXCEPT; template - friend _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep) _NOEXCEPT; + friend _LIBCPP_HIDE_FROM_ABI exception_ptr __make_exception_ptr_explicit(_Ep&) _NOEXCEPT; public: // exception_ptr is basically a COW string so it is trivially relocatable. @@ -91,25 +92,21 @@ public: friend _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr); }; -template -_LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { # if _LIBCPP_HAS_EXCEPTIONS -# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201103L +# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION +template +_LIBCPP_HIDE_FROM_ABI exception_ptr __make_exception_ptr_explicit(_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* { + auto __cleanup = [](void* __p) -> void* { + std::__destroy_at(static_cast<_Ep2*>(__p)); + return __p; + }; # else - (void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast(&typeid(_Ep)), [](void* __p) { + auto __cleanup = [](void* __p) { std::__destroy_at(static_cast<_Ep2*>(__p)); }; # endif - std::__destroy_at(static_cast<_Ep2*>(__p)); -# ifdef __wasm__ - return __p; -# endif - }); + (void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast(&typeid(_Ep)), __cleanup); try { ::new (__ex) _Ep2(__e); @@ -118,19 +115,48 @@ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { __cxxabiv1::__cxa_free_exception(__ex); return current_exception(); } -# else +} +# endif + +template +_LIBCPP_HIDE_FROM_ABI exception_ptr __make_exception_ptr_via_throw(_Ep& __e) _NOEXCEPT { try { throw __e; } catch (...) { return current_exception(); } -# endif -# else - ((void)__e); - std::abort(); -# endif } +template +_LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { + // Objective-C exceptions are thrown via pointer. When throwing an Objective-C exception, + // Clang generates a call to `objc_exception_throw` instead of the usual `__cxa_throw`. + // That function creates an exception with a special Objective-C typeinfo instead of + // the usual C++ typeinfo, since that is needed to implement the behavior documented + // at [1]). + // + // Because of this special behavior, we can't create an exception via `__cxa_init_primary_exception` + // for Objective-C exceptions, otherwise we'd bypass `objc_exception_throw`. See https://llvm.org/PR135089. + // + // [1]: + // https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Exceptions/Articles/Exceptions64Bit.html + if _LIBCPP_CONSTEXPR (is_pointer<_Ep>::value) { + return std::__make_exception_ptr_via_throw(__e); + } + +# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && !defined(_LIBCPP_CXX03_LANG) + return std::__make_exception_ptr_explicit(__e); +# else + return std::__make_exception_ptr_via_throw(__e); +# endif +} +# else // !_LIBCPP_HAS_EXCEPTIONS +template +_LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep) _NOEXCEPT { + std::abort(); +} +# endif // _LIBCPP_HAS_EXCEPTIONS + #else // _LIBCPP_ABI_MICROSOFT class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { 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 a2c28bfd79..381e5678a5 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__filesystem/path.h +++ b/naiveproxy/src/third_party/libc++/src/include/__filesystem/path.h @@ -29,7 +29,6 @@ #if _LIBCPP_HAS_LOCALIZATION # include // for quoted -# include #endif #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 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 e13980298d..a701425e42 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__filesystem/u8path.h +++ b/naiveproxy/src/third_party/libc++/src/include/__filesystem/u8path.h @@ -13,14 +13,9 @@ #include <__algorithm/unwrap_iter.h> #include <__config> #include <__filesystem/path.h> +#include <__locale> #include -// Only required on Windows for __widen_from_utf8, and included conservatively -// because it requires support for localization. -#if defined(_LIBCPP_WIN32API) -# include -#endif - #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif diff --git a/naiveproxy/src/third_party/libc++/src/include/__flat_map/flat_map.h b/naiveproxy/src/third_party/libc++/src/include/__flat_map/flat_map.h index 8f01882934..bf193f6d3c 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__flat_map/flat_map.h +++ b/naiveproxy/src/third_party/libc++/src/include/__flat_map/flat_map.h @@ -114,11 +114,12 @@ public: class value_compare { private: _LIBCPP_NO_UNIQUE_ADDRESS key_compare __comp_; - _LIBCPP_HIDE_FROM_ABI value_compare(key_compare __c) : __comp_(__c) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 value_compare(key_compare __c) : __comp_(__c) {} friend flat_map; public: - _LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator()(const_reference __x, const_reference __y) const { return __comp_(__x.first, __y.first); } }; @@ -137,14 +138,14 @@ private: public: // [flat.map.cons], construct/copy/destroy - _LIBCPP_HIDE_FROM_ABI flat_map() noexcept( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map() noexcept( is_nothrow_default_constructible_v<_KeyContainer> && is_nothrow_default_constructible_v<_MappedContainer> && is_nothrow_default_constructible_v<_Compare>) : __containers_(), __compare_() {} _LIBCPP_HIDE_FROM_ABI flat_map(const flat_map&) = default; - _LIBCPP_HIDE_FROM_ABI flat_map(flat_map&& __other) noexcept( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(flat_map&& __other) noexcept( is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_MappedContainer> && is_nothrow_move_constructible_v<_Compare>) # if _LIBCPP_HAS_EXCEPTIONS @@ -165,7 +166,7 @@ public: template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_map(const flat_map& __other, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(const flat_map& __other, const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_tag{}, __alloc, __other.__containers_.keys, @@ -174,7 +175,7 @@ public: template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_map(flat_map&& __other, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(flat_map&& __other, const _Allocator& __alloc) # if _LIBCPP_HAS_EXCEPTIONS try # endif // _LIBCPP_HAS_EXCEPTIONS @@ -191,7 +192,7 @@ public: # endif // _LIBCPP_HAS_EXCEPTIONS } - _LIBCPP_HIDE_FROM_ABI flat_map( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map( key_container_type __key_cont, mapped_container_type __mapped_cont, const key_compare& __comp = key_compare()) : __containers_{.keys = std::move(__key_cont), .values = std::move(__mapped_cont)}, __compare_(__comp) { _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(), @@ -201,7 +202,7 @@ public: template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(const key_container_type& __key_cont, const mapped_container_type& __mapped_cont, const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont) { _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(), @@ -211,7 +212,7 @@ public: template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(const key_container_type& __key_cont, const mapped_container_type& __mapped_cont, const key_compare& __comp, @@ -222,7 +223,7 @@ public: __sort_and_unique(); } - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(sorted_unique_t, key_container_type __key_cont, mapped_container_type __mapped_cont, @@ -236,7 +237,7 @@ public: template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(sorted_unique_t, const key_container_type& __key_cont, const mapped_container_type& __mapped_cont, @@ -250,12 +251,12 @@ public: template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI - flat_map(sorted_unique_t, - const key_container_type& __key_cont, - const mapped_container_type& __mapped_cont, - const key_compare& __comp, - const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map( + sorted_unique_t, + const key_container_type& __key_cont, + const mapped_container_type& __mapped_cont, + const key_compare& __comp, + const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont, __comp) { _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(), "flat_map keys and mapped containers have different size"); @@ -263,21 +264,22 @@ public: __is_sorted_and_unique(__containers_.keys), "Either the key container is not sorted or it contains duplicates"); } - _LIBCPP_HIDE_FROM_ABI explicit flat_map(const key_compare& __comp) : __containers_(), __compare_(__comp) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit flat_map(const key_compare& __comp) + : __containers_(), __compare_(__comp) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_map(const key_compare& __comp, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(const key_compare& __comp, const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI explicit flat_map(const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit flat_map(const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc) {} template requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(_InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare()) : __containers_(), __compare_(__comp) { insert(__first, __last); @@ -285,7 +287,7 @@ public: template requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>) - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(_InputIterator __first, _InputIterator __last, const key_compare& __comp, const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) { insert(__first, __last); @@ -293,99 +295,105 @@ public: template requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>) - _LIBCPP_HIDE_FROM_ABI flat_map(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_map(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc) { insert(__first, __last); } template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI flat_map(from_range_t __fr, _Range&& __rg) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(from_range_t __fr, _Range&& __rg) : flat_map(__fr, std::forward<_Range>(__rg), key_compare()) {} template <_ContainerCompatibleRange _Range, class _Allocator> requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_map(from_range_t, _Range&& __rg, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(from_range_t, _Range&& __rg, const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc) { insert_range(std::forward<_Range>(__rg)); } template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI flat_map(from_range_t, _Range&& __rg, const key_compare& __comp) : flat_map(__comp) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(from_range_t, _Range&& __rg, const key_compare& __comp) + : flat_map(__comp) { insert_range(std::forward<_Range>(__rg)); } template <_ContainerCompatibleRange _Range, class _Allocator> requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_map(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_map(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) { insert_range(std::forward<_Range>(__rg)); } template requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(sorted_unique_t, _InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare()) : __containers_(), __compare_(__comp) { insert(sorted_unique, __first, __last); } template requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>) - _LIBCPP_HIDE_FROM_ABI - flat_map(sorted_unique_t, - _InputIterator __first, - _InputIterator __last, - const key_compare& __comp, - const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map( + sorted_unique_t, + _InputIterator __first, + _InputIterator __last, + const key_compare& __comp, + const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) { insert(sorted_unique, __first, __last); } template requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>) - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(sorted_unique_t, _InputIterator __first, _InputIterator __last, const _Allocator& __alloc) : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc) { insert(sorted_unique, __first, __last); } - _LIBCPP_HIDE_FROM_ABI flat_map(initializer_list __il, const key_compare& __comp = key_compare()) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_map(initializer_list __il, const key_compare& __comp = key_compare()) : flat_map(__il.begin(), __il.end(), __comp) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(initializer_list __il, const key_compare& __comp, const _Allocator& __alloc) : flat_map(__il.begin(), __il.end(), __comp, __alloc) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_map(initializer_list __il, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_map(initializer_list __il, const _Allocator& __alloc) : flat_map(__il.begin(), __il.end(), __alloc) {} - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(sorted_unique_t, initializer_list __il, const key_compare& __comp = key_compare()) : flat_map(sorted_unique, __il.begin(), __il.end(), __comp) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map(sorted_unique_t, initializer_list __il, const key_compare& __comp, const _Allocator& __alloc) : flat_map(sorted_unique, __il.begin(), __il.end(), __comp, __alloc) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_map(sorted_unique_t, initializer_list __il, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_map(sorted_unique_t, initializer_list __il, const _Allocator& __alloc) : flat_map(sorted_unique, __il.begin(), __il.end(), __alloc) {} - _LIBCPP_HIDE_FROM_ABI flat_map& operator=(initializer_list __il) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map& operator=(initializer_list __il) { clear(); insert(__il); return *this; } - _LIBCPP_HIDE_FROM_ABI flat_map& operator=(const flat_map&) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map& operator=(const flat_map&) = default; - _LIBCPP_HIDE_FROM_ABI flat_map& operator=(flat_map&& __other) noexcept( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map& operator=(flat_map&& __other) noexcept( is_nothrow_move_assignable_v<_KeyContainer> && is_nothrow_move_assignable_v<_MappedContainer> && is_nothrow_move_assignable_v<_Compare>) { // No matter what happens, we always want to clear the other container before returning @@ -402,49 +410,65 @@ public: } // iterators - _LIBCPP_HIDE_FROM_ABI iterator begin() noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator begin() noexcept { return iterator(__containers_.keys.begin(), __containers_.values.begin()); } - _LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator begin() const noexcept { return const_iterator(__containers_.keys.begin(), __containers_.values.begin()); } - _LIBCPP_HIDE_FROM_ABI iterator end() noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator end() noexcept { return iterator(__containers_.keys.end(), __containers_.values.end()); } - _LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator end() const noexcept { return const_iterator(__containers_.keys.end(), __containers_.values.end()); } - _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI reverse_iterator rend() noexcept { return reverse_iterator(begin()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rbegin() noexcept { + return reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rbegin() const noexcept { + return const_reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rend() noexcept { + return reverse_iterator(begin()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rend() const noexcept { + return const_reverse_iterator(begin()); + } - _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return begin(); } - _LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return end(); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cbegin() const noexcept { return begin(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cend() const noexcept { return end(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crbegin() const noexcept { + return const_reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crend() const noexcept { + return const_reverse_iterator(begin()); + } // [flat.map.capacity], capacity - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __containers_.keys.empty(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool empty() const noexcept { + return __containers_.keys.empty(); + } - _LIBCPP_HIDE_FROM_ABI size_type size() const noexcept { return __containers_.keys.size(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type size() const noexcept { + return __containers_.keys.size(); + } - _LIBCPP_HIDE_FROM_ABI size_type max_size() const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type max_size() const noexcept { return std::min(__containers_.keys.max_size(), __containers_.values.max_size()); } // [flat.map.access], element access - _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](const key_type& __x) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 mapped_type& operator[](const key_type& __x) requires is_constructible_v { return try_emplace(__x).first->second; } - _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](key_type&& __x) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 mapped_type& operator[](key_type&& __x) requires is_constructible_v { return try_emplace(std::move(__x)).first->second; @@ -453,11 +477,11 @@ public: template requires(__is_compare_transparent && is_constructible_v && is_constructible_v && !is_convertible_v<_Kp &&, const_iterator> && !is_convertible_v<_Kp &&, iterator>) - _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](_Kp&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 mapped_type& operator[](_Kp&& __x) { return try_emplace(std::forward<_Kp>(__x)).first->second; } - _LIBCPP_HIDE_FROM_ABI mapped_type& at(const key_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 mapped_type& at(const key_type& __x) { auto __it = find(__x); if (__it == end()) { std::__throw_out_of_range("flat_map::at(const key_type&): Key does not exist"); @@ -465,7 +489,7 @@ public: return __it->second; } - _LIBCPP_HIDE_FROM_ABI const mapped_type& at(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const mapped_type& at(const key_type& __x) const { auto __it = find(__x); if (__it == end()) { std::__throw_out_of_range("flat_map::at(const key_type&) const: Key does not exist"); @@ -475,7 +499,7 @@ public: template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI mapped_type& at(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 mapped_type& at(const _Kp& __x) { auto __it = find(__x); if (__it == end()) { std::__throw_out_of_range("flat_map::at(const K&): Key does not exist"); @@ -485,7 +509,7 @@ public: template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI const mapped_type& at(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const mapped_type& at(const _Kp& __x) const { auto __it = find(__x); if (__it == end()) { std::__throw_out_of_range("flat_map::at(const K&) const: Key does not exist"); @@ -496,45 +520,49 @@ public: // [flat.map.modifiers], modifiers template requires is_constructible_v, _Args...> - _LIBCPP_HIDE_FROM_ABI pair emplace(_Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair emplace(_Args&&... __args) { std::pair __pair(std::forward<_Args>(__args)...); return __try_emplace(std::move(__pair.first), std::move(__pair.second)); } template requires is_constructible_v, _Args...> - _LIBCPP_HIDE_FROM_ABI iterator emplace_hint(const_iterator __hint, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator emplace_hint(const_iterator __hint, _Args&&... __args) { std::pair __pair(std::forward<_Args>(__args)...); return __try_emplace_hint(__hint, std::move(__pair.first), std::move(__pair.second)).first; } - _LIBCPP_HIDE_FROM_ABI pair insert(const value_type& __x) { return emplace(__x); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair insert(const value_type& __x) { + return emplace(__x); + } - _LIBCPP_HIDE_FROM_ABI pair insert(value_type&& __x) { return emplace(std::move(__x)); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair insert(value_type&& __x) { + return emplace(std::move(__x)); + } - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, const value_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, const value_type& __x) { return emplace_hint(__hint, __x); } - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, value_type&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, value_type&& __x) { return emplace_hint(__hint, std::move(__x)); } template requires is_constructible_v, _PairLike> - _LIBCPP_HIDE_FROM_ABI pair insert(_PairLike&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair insert(_PairLike&& __x) { return emplace(std::forward<_PairLike>(__x)); } template requires is_constructible_v, _PairLike> - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, _PairLike&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, _PairLike&& __x) { return emplace_hint(__hint, std::forward<_PairLike>(__x)); } template requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(_InputIterator __first, _InputIterator __last) { if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) { __reserve(__last - __first); } @@ -543,7 +571,8 @@ public: template requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI void insert(sorted_unique_t, _InputIterator __first, _InputIterator __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + insert(sorted_unique_t, _InputIterator __first, _InputIterator __last) { if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) { __reserve(__last - __first); } @@ -552,7 +581,7 @@ public: } template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert_range(_Range&& __range) { if constexpr (ranges::sized_range<_Range>) { __reserve(ranges::size(__range)); } @@ -560,19 +589,22 @@ public: __append_sort_merge_unique(ranges::begin(__range), ranges::end(__range)); } - _LIBCPP_HIDE_FROM_ABI void insert(initializer_list __il) { insert(__il.begin(), __il.end()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(initializer_list __il) { + insert(__il.begin(), __il.end()); + } - _LIBCPP_HIDE_FROM_ABI void insert(sorted_unique_t, initializer_list __il) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(sorted_unique_t, initializer_list __il) { insert(sorted_unique, __il.begin(), __il.end()); } - _LIBCPP_HIDE_FROM_ABI containers extract() && { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 containers extract() && { auto __guard = std::__make_scope_guard([&]() noexcept { clear() /* noexcept */; }); auto __ret = std::move(__containers_); return __ret; } - _LIBCPP_HIDE_FROM_ABI void replace(key_container_type&& __key_cont, mapped_container_type&& __mapped_cont) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + replace(key_container_type&& __key_cont, mapped_container_type&& __mapped_cont) { _LIBCPP_ASSERT_VALID_INPUT_RANGE( __key_cont.size() == __mapped_cont.size(), "flat_map keys and mapped containers have different size"); @@ -586,13 +618,15 @@ public: template requires is_constructible_v - _LIBCPP_HIDE_FROM_ABI pair try_emplace(const key_type& __key, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + try_emplace(const key_type& __key, _Args&&... __args) { return __try_emplace(__key, std::forward<_Args>(__args)...); } template requires is_constructible_v - _LIBCPP_HIDE_FROM_ABI pair try_emplace(key_type&& __key, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + try_emplace(key_type&& __key, _Args&&... __args) { return __try_emplace(std::move(__key), std::forward<_Args>(__args)...); } @@ -600,75 +634,84 @@ public: requires(__is_compare_transparent && is_constructible_v && is_constructible_v && !is_convertible_v<_Kp &&, const_iterator> && !is_convertible_v<_Kp &&, iterator>) - _LIBCPP_HIDE_FROM_ABI pair try_emplace(_Kp&& __key, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair try_emplace(_Kp&& __key, _Args&&... __args) { return __try_emplace(std::forward<_Kp>(__key), std::forward<_Args>(__args)...); } template requires is_constructible_v - _LIBCPP_HIDE_FROM_ABI iterator try_emplace(const_iterator __hint, const key_type& __key, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + try_emplace(const_iterator __hint, const key_type& __key, _Args&&... __args) { return __try_emplace_hint(__hint, __key, std::forward<_Args>(__args)...).first; } template requires is_constructible_v - _LIBCPP_HIDE_FROM_ABI iterator try_emplace(const_iterator __hint, key_type&& __key, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + try_emplace(const_iterator __hint, key_type&& __key, _Args&&... __args) { return __try_emplace_hint(__hint, std::move(__key), std::forward<_Args>(__args)...).first; } template requires __is_compare_transparent && is_constructible_v && is_constructible_v - _LIBCPP_HIDE_FROM_ABI iterator try_emplace(const_iterator __hint, _Kp&& __key, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + try_emplace(const_iterator __hint, _Kp&& __key, _Args&&... __args) { return __try_emplace_hint(__hint, std::forward<_Kp>(__key), std::forward<_Args>(__args)...).first; } template requires is_assignable_v && is_constructible_v - _LIBCPP_HIDE_FROM_ABI pair insert_or_assign(const key_type& __key, _Mapped&& __obj) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + insert_or_assign(const key_type& __key, _Mapped&& __obj) { return __insert_or_assign(__key, std::forward<_Mapped>(__obj)); } template requires is_assignable_v && is_constructible_v - _LIBCPP_HIDE_FROM_ABI pair insert_or_assign(key_type&& __key, _Mapped&& __obj) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + insert_or_assign(key_type&& __key, _Mapped&& __obj) { return __insert_or_assign(std::move(__key), std::forward<_Mapped>(__obj)); } template requires __is_compare_transparent && is_constructible_v && is_assignable_v && is_constructible_v - _LIBCPP_HIDE_FROM_ABI pair insert_or_assign(_Kp&& __key, _Mapped&& __obj) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + insert_or_assign(_Kp&& __key, _Mapped&& __obj) { return __insert_or_assign(std::forward<_Kp>(__key), std::forward<_Mapped>(__obj)); } template requires is_assignable_v && is_constructible_v - _LIBCPP_HIDE_FROM_ABI iterator insert_or_assign(const_iterator __hint, const key_type& __key, _Mapped&& __obj) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + insert_or_assign(const_iterator __hint, const key_type& __key, _Mapped&& __obj) { return __insert_or_assign(__hint, __key, std::forward<_Mapped>(__obj)); } template requires is_assignable_v && is_constructible_v - _LIBCPP_HIDE_FROM_ABI iterator insert_or_assign(const_iterator __hint, key_type&& __key, _Mapped&& __obj) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + insert_or_assign(const_iterator __hint, key_type&& __key, _Mapped&& __obj) { return __insert_or_assign(__hint, std::move(__key), std::forward<_Mapped>(__obj)); } template requires __is_compare_transparent && is_constructible_v && is_assignable_v && is_constructible_v - _LIBCPP_HIDE_FROM_ABI iterator insert_or_assign(const_iterator __hint, _Kp&& __key, _Mapped&& __obj) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + insert_or_assign(const_iterator __hint, _Kp&& __key, _Mapped&& __obj) { return __insert_or_assign(__hint, std::forward<_Kp>(__key), std::forward<_Mapped>(__obj)); } - _LIBCPP_HIDE_FROM_ABI iterator erase(iterator __position) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(iterator __position) { return __erase(__position.__key_iter_, __position.__mapped_iter_); } - _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __position) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(const_iterator __position) { return __erase(__position.__key_iter_, __position.__mapped_iter_); } - _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(const key_type& __x) { auto __iter = find(__x); if (__iter != end()) { erase(__iter); @@ -680,14 +723,14 @@ public: template requires(__is_compare_transparent && !is_convertible_v<_Kp &&, iterator> && !is_convertible_v<_Kp &&, const_iterator>) - _LIBCPP_HIDE_FROM_ABI size_type erase(_Kp&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(_Kp&& __x) { auto [__first, __last] = equal_range(__x); auto __res = __last - __first; erase(__first, __last); return __res; } - _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(const_iterator __first, const_iterator __last) { auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); auto __key_it = __containers_.keys.erase(__first.__key_iter_, __last.__key_iter_); auto __mapped_it = __containers_.values.erase(__first.__mapped_iter_, __last.__mapped_iter_); @@ -695,7 +738,7 @@ public: return iterator(std::move(__key_it), std::move(__mapped_it)); } - _LIBCPP_HIDE_FROM_ABI void swap(flat_map& __y) noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(flat_map& __y) noexcept { // warning: The spec has unconditional noexcept, which means that // if any of the following functions throw an exception, // std::terminate will be called. @@ -705,133 +748,156 @@ public: ranges::swap(__containers_.values, __y.__containers_.values); } - _LIBCPP_HIDE_FROM_ABI void clear() noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void clear() noexcept { __containers_.keys.clear(); __containers_.values.clear(); } // observers - _LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __compare_; } - _LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return value_compare(__compare_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 key_compare key_comp() const { return __compare_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 value_compare value_comp() const { + return value_compare(__compare_); + } - _LIBCPP_HIDE_FROM_ABI const key_container_type& keys() const noexcept { return __containers_.keys; } - _LIBCPP_HIDE_FROM_ABI const mapped_container_type& values() const noexcept { return __containers_.values; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const key_container_type& keys() const noexcept { + return __containers_.keys; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const mapped_container_type& values() const noexcept { + return __containers_.values; + } // map operations - _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __x) { return __find_impl(*this, __x); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const key_type& __x) { + return __find_impl(*this, __x); + } - _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __x) const { return __find_impl(*this, __x); } - - template - requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI iterator find(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const key_type& __x) const { return __find_impl(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI const_iterator find(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const _Kp& __x) { return __find_impl(*this, __x); } - _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __x) const { return contains(__x) ? 1 : 0; } - template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI size_type count(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const _Kp& __x) const { + return __find_impl(*this, __x); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const key_type& __x) const { return contains(__x) ? 1 : 0; } - _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __x) const { return find(__x) != end(); } - template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI bool contains(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const _Kp& __x) const { + return contains(__x) ? 1 : 0; + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const key_type& __x) const { return find(__x) != end(); } - _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __x) { return __lower_bound(*this, __x); } + template + requires __is_compare_transparent + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const _Kp& __x) const { + return find(__x) != end(); + } - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const key_type& __x) { + return __lower_bound(*this, __x); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const key_type& __x) const { return __lower_bound(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const _Kp& __x) { return __lower_bound(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const _Kp& __x) const { return __lower_bound(*this, __x); } - _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __x) { return __upper_bound(*this, __x); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const key_type& __x) { + return __upper_bound(*this, __x); + } - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const key_type& __x) const { return __upper_bound(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const _Kp& __x) { return __upper_bound(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const _Kp& __x) const { return __upper_bound(*this, __x); } - _LIBCPP_HIDE_FROM_ABI pair equal_range(const key_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair equal_range(const key_type& __x) { return __equal_range_impl(*this, __x); } - _LIBCPP_HIDE_FROM_ABI pair equal_range(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + equal_range(const key_type& __x) const { return __equal_range_impl(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI pair equal_range(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair equal_range(const _Kp& __x) { return __equal_range_impl(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI pair equal_range(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + equal_range(const _Kp& __x) const { return __equal_range_impl(*this, __x); } - friend _LIBCPP_HIDE_FROM_ABI bool operator==(const flat_map& __x, const flat_map& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator==(const flat_map& __x, const flat_map& __y) { return ranges::equal(__x, __y); } - friend _LIBCPP_HIDE_FROM_ABI auto operator<=>(const flat_map& __x, const flat_map& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 auto + operator<=>(const flat_map& __x, const flat_map& __y) { return std::lexicographical_compare_three_way( __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way); } - friend _LIBCPP_HIDE_FROM_ABI void swap(flat_map& __x, flat_map& __y) noexcept { __x.swap(__y); } + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(flat_map& __x, flat_map& __y) noexcept { + __x.swap(__y); + } private: struct __ctor_uses_allocator_tag { - explicit _LIBCPP_HIDE_FROM_ABI __ctor_uses_allocator_tag() = default; + explicit _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __ctor_uses_allocator_tag() = default; }; struct __ctor_uses_allocator_empty_tag { - explicit _LIBCPP_HIDE_FROM_ABI __ctor_uses_allocator_empty_tag() = default; + explicit _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __ctor_uses_allocator_empty_tag() = default; }; template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI - flat_map(__ctor_uses_allocator_tag, - const _Allocator& __alloc, - _KeyCont&& __key_cont, - _MappedCont&& __mapped_cont, - _CompArg&&... __comp) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_map( + __ctor_uses_allocator_tag, + const _Allocator& __alloc, + _KeyCont&& __key_cont, + _MappedCont&& __mapped_cont, + _CompArg&&... __comp) : __containers_{.keys = std::make_obj_using_allocator( __alloc, std::forward<_KeyCont>(__key_cont)), .values = std::make_obj_using_allocator( @@ -840,12 +906,13 @@ private: template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_map(__ctor_uses_allocator_empty_tag, const _Allocator& __alloc, _CompArg&&... __comp) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_map(__ctor_uses_allocator_empty_tag, const _Allocator& __alloc, _CompArg&&... __comp) : __containers_{.keys = std::make_obj_using_allocator(__alloc), .values = std::make_obj_using_allocator(__alloc)}, __compare_(std::forward<_CompArg>(__comp)...) {} - _LIBCPP_HIDE_FROM_ABI bool __is_sorted_and_unique(auto&& __key_container) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __is_sorted_and_unique(auto&& __key_container) const { auto __greater_or_equal_to = [this](const auto& __x, const auto& __y) { return !__compare_(__x, __y); }; return ranges::adjacent_find(__key_container, __greater_or_equal_to) == ranges::end(__key_container); } @@ -853,7 +920,7 @@ private: // This function is only used in constructors. So there is not exception handling in this function. // If the function exits via an exception, there will be no flat_map object constructed, thus, there // is no invariant state to preserve - _LIBCPP_HIDE_FROM_ABI void __sort_and_unique() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __sort_and_unique() { auto __zv = ranges::views::zip(__containers_.keys, __containers_.values); ranges::sort(__zv, __compare_, [](const auto& __p) -> decltype(auto) { return std::get<0>(__p); }); auto __dup_start = ranges::unique(__zv, __key_equiv(__compare_)).begin(); @@ -863,14 +930,16 @@ private: } template - _LIBCPP_HIDE_FROM_ABI static auto __corresponding_mapped_it(_Self&& __self, _KeyIter&& __key_iter) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto + __corresponding_mapped_it(_Self&& __self, _KeyIter&& __key_iter) { return __self.__containers_.values.begin() + static_cast>( ranges::distance(__self.__containers_.keys.begin(), __key_iter)); } template - _LIBCPP_HIDE_FROM_ABI void __append_sort_merge_unique(_InputIterator __first, _Sentinel __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + __append_sort_merge_unique(_InputIterator __first, _Sentinel __last) { auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); size_t __num_of_appended = __flat_map_utils::__append(*this, std::move(__first), std::move(__last)); if (__num_of_appended != 0) { @@ -898,7 +967,7 @@ private: } template - _LIBCPP_HIDE_FROM_ABI static auto __find_impl(_Self&& __self, const _Kp& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto __find_impl(_Self&& __self, const _Kp& __key) { auto __it = __self.lower_bound(__key); auto __last = __self.end(); if (__it == __last || __self.__compare_(__key, __it->first)) { @@ -908,7 +977,7 @@ private: } template - _LIBCPP_HIDE_FROM_ABI static auto __key_equal_range(_Self&& __self, const _Kp& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto __key_equal_range(_Self&& __self, const _Kp& __key) { auto __it = std::lower_bound(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __key, __self.__compare_); auto __last = __self.__containers_.keys.end(); @@ -919,7 +988,7 @@ private: } template - _LIBCPP_HIDE_FROM_ABI static auto __equal_range_impl(_Self&& __self, const _Kp& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto __equal_range_impl(_Self&& __self, const _Kp& __key) { auto [__key_first, __key_last] = __key_equal_range(__self, __key); using __iterator_type = ranges::iterator_t; return std::make_pair(__iterator_type(__key_first, __corresponding_mapped_it(__self, __key_first)), @@ -927,7 +996,7 @@ private: } template - _LIBCPP_HIDE_FROM_ABI static _Res __lower_bound(_Self&& __self, _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static _Res __lower_bound(_Self&& __self, _Kp& __x) { auto __key_iter = std::lower_bound(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __x, __self.__compare_); auto __mapped_iter = __corresponding_mapped_it(__self, __key_iter); @@ -935,7 +1004,7 @@ private: } template - _LIBCPP_HIDE_FROM_ABI static _Res __upper_bound(_Self&& __self, _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static _Res __upper_bound(_Self&& __self, _Kp& __x) { auto __key_iter = std::upper_bound(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __x, __self.__compare_); auto __mapped_iter = __corresponding_mapped_it(__self, __key_iter); @@ -943,7 +1012,8 @@ private: } template - _LIBCPP_HIDE_FROM_ABI pair __try_emplace(_KeyArg&& __key, _MArgs&&... __mapped_args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __try_emplace(_KeyArg&& __key, _MArgs&&... __mapped_args) { auto __key_it = std::lower_bound(__containers_.keys.begin(), __containers_.keys.end(), __key, __compare_); auto __mapped_it = __containers_.values.begin() + ranges::distance(__containers_.keys.begin(), __key_it); @@ -962,7 +1032,7 @@ private: } template - _LIBCPP_HIDE_FROM_ABI bool __is_hint_correct(const_iterator __hint, _Kp&& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __is_hint_correct(const_iterator __hint, _Kp&& __key) { if (__hint != cbegin() && !__compare_((__hint - 1)->first, __key)) { return false; } @@ -973,7 +1043,8 @@ private: } template - _LIBCPP_HIDE_FROM_ABI pair __try_emplace_hint(const_iterator __hint, _Kp&& __key, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __try_emplace_hint(const_iterator __hint, _Kp&& __key, _Args&&... __args) { if (__is_hint_correct(__hint, __key)) { if (__hint == cend() || __compare_(__key, __hint->first)) { return {__flat_map_utils::__emplace_exact_pos( @@ -994,7 +1065,8 @@ private: } template - _LIBCPP_HIDE_FROM_ABI pair __insert_or_assign(_Kp&& __key, _Mapped&& __mapped) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __insert_or_assign(_Kp&& __key, _Mapped&& __mapped) { auto __r = try_emplace(std::forward<_Kp>(__key), std::forward<_Mapped>(__mapped)); if (!__r.second) { __r.first->second = std::forward<_Mapped>(__mapped); @@ -1003,7 +1075,8 @@ private: } template - _LIBCPP_HIDE_FROM_ABI iterator __insert_or_assign(const_iterator __hint, _Kp&& __key, _Mapped&& __mapped) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + __insert_or_assign(const_iterator __hint, _Kp&& __key, _Mapped&& __mapped) { auto __r = __try_emplace_hint(__hint, std::forward<_Kp>(__key), std::forward<_Mapped>(__mapped)); if (!__r.second) { __r.first->second = std::forward<_Mapped>(__mapped); @@ -1011,7 +1084,7 @@ private: return __r.first; } - _LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __reserve(size_t __size) { if constexpr (__container_traits<_KeyContainer>::__reservable) { __containers_.keys.reserve(__size); } @@ -1022,7 +1095,8 @@ private: } template - _LIBCPP_HIDE_FROM_ABI iterator __erase(_KIter __key_iter_to_remove, _MIter __mapped_iter_to_remove) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + __erase(_KIter __key_iter_to_remove, _MIter __mapped_iter_to_remove) { auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); auto __key_iter = __containers_.keys.erase(__key_iter_to_remove); auto __mapped_iter = __containers_.values.erase(__mapped_iter_to_remove); @@ -1032,7 +1106,8 @@ private: template friend typename flat_map<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>::size_type - erase_if(flat_map<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>&, _Predicate); + _LIBCPP_CONSTEXPR_SINCE_CXX26 + erase_if(flat_map<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>&, _Predicate); friend __flat_map_utils; @@ -1040,8 +1115,9 @@ private: _LIBCPP_NO_UNIQUE_ADDRESS key_compare __compare_; struct __key_equiv { - _LIBCPP_HIDE_FROM_ABI __key_equiv(key_compare __c) : __comp_(__c) {} - _LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_equiv(key_compare __c) : __comp_(__c) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator()(const_reference __x, const_reference __y) const { return !__comp_(std::get<0>(__x), std::get<0>(__y)) && !__comp_(std::get<0>(__y), std::get<0>(__x)); } key_compare __comp_; @@ -1164,8 +1240,9 @@ struct uses_allocator && uses_allocator_v<_MappedContainer, _Allocator>> {}; template -_LIBCPP_HIDE_FROM_ABI typename flat_map<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>::size_type -erase_if(flat_map<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>& __flat_map, _Predicate __pred) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + typename flat_map<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>::size_type + erase_if(flat_map<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>& __flat_map, _Predicate __pred) { auto __zv = ranges::views::zip(__flat_map.__containers_.keys, __flat_map.__containers_.values); auto __first = __zv.begin(); auto __last = __zv.end(); diff --git a/naiveproxy/src/third_party/libc++/src/include/__flat_map/flat_multimap.h b/naiveproxy/src/third_party/libc++/src/include/__flat_map/flat_multimap.h index 0af6aac00c..260d93ed25 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__flat_map/flat_multimap.h +++ b/naiveproxy/src/third_party/libc++/src/include/__flat_map/flat_multimap.h @@ -114,11 +114,12 @@ public: class value_compare { private: _LIBCPP_NO_UNIQUE_ADDRESS key_compare __comp_; - _LIBCPP_HIDE_FROM_ABI value_compare(key_compare __c) : __comp_(__c) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 value_compare(key_compare __c) : __comp_(__c) {} friend flat_multimap; public: - _LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator()(const_reference __x, const_reference __y) const { return __comp_(__x.first, __y.first); } }; @@ -137,17 +138,17 @@ private: public: // [flat.map.cons], construct/copy/destroy - _LIBCPP_HIDE_FROM_ABI flat_multimap() noexcept( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap() noexcept( is_nothrow_default_constructible_v<_KeyContainer> && is_nothrow_default_constructible_v<_MappedContainer> && is_nothrow_default_constructible_v<_Compare>) : __containers_(), __compare_() {} - _LIBCPP_HIDE_FROM_ABI flat_multimap(const flat_multimap&) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap(const flat_multimap&) = default; // The copy/move constructors are not specified in the spec, which means they should be defaulted. // However, the move constructor can potentially leave a moved-from object in an inconsistent // state if an exception is thrown. - _LIBCPP_HIDE_FROM_ABI flat_multimap(flat_multimap&& __other) noexcept( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap(flat_multimap&& __other) noexcept( is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_MappedContainer> && is_nothrow_move_constructible_v<_Compare>) # if _LIBCPP_HAS_EXCEPTIONS @@ -168,7 +169,8 @@ public: template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_multimap(const flat_multimap& __other, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multimap(const flat_multimap& __other, const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __other.__containers_.keys, @@ -177,7 +179,7 @@ public: template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_multimap(flat_multimap&& __other, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap(flat_multimap&& __other, const _Allocator& __alloc) # if _LIBCPP_HAS_EXCEPTIONS try # endif // _LIBCPP_HAS_EXCEPTIONS @@ -194,7 +196,7 @@ public: # endif // _LIBCPP_HAS_EXCEPTIONS } - _LIBCPP_HIDE_FROM_ABI flat_multimap( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap( key_container_type __key_cont, mapped_container_type __mapped_cont, const key_compare& __comp = key_compare()) : __containers_{.keys = std::move(__key_cont), .values = std::move(__mapped_cont)}, __compare_(__comp) { _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(), @@ -204,7 +206,7 @@ public: template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_multimap( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap( const key_container_type& __key_cont, const mapped_container_type& __mapped_cont, const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont) { _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(), @@ -214,22 +216,22 @@ public: template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI - flat_multimap(const key_container_type& __key_cont, - const mapped_container_type& __mapped_cont, - const key_compare& __comp, - const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap( + const key_container_type& __key_cont, + const mapped_container_type& __mapped_cont, + const key_compare& __comp, + const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont, __comp) { _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(), "flat_multimap keys and mapped containers have different size"); __sort(); } - _LIBCPP_HIDE_FROM_ABI - flat_multimap(sorted_equivalent_t, - key_container_type __key_cont, - mapped_container_type __mapped_cont, - const key_compare& __comp = key_compare()) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap( + sorted_equivalent_t, + key_container_type __key_cont, + mapped_container_type __mapped_cont, + const key_compare& __comp = key_compare()) : __containers_{.keys = std::move(__key_cont), .values = std::move(__mapped_cont)}, __compare_(__comp) { _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(), "flat_multimap keys and mapped containers have different size"); @@ -238,11 +240,11 @@ public: template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI - flat_multimap(sorted_equivalent_t, - const key_container_type& __key_cont, - const mapped_container_type& __mapped_cont, - const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap( + sorted_equivalent_t, + const key_container_type& __key_cont, + const mapped_container_type& __mapped_cont, + const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont) { _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(), "flat_multimap keys and mapped containers have different size"); @@ -251,33 +253,35 @@ public: template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI - flat_multimap(sorted_equivalent_t, - const key_container_type& __key_cont, - const mapped_container_type& __mapped_cont, - const key_compare& __comp, - const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap( + sorted_equivalent_t, + const key_container_type& __key_cont, + const mapped_container_type& __mapped_cont, + const key_compare& __comp, + const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont, __comp) { _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(), "flat_multimap keys and mapped containers have different size"); _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__is_sorted(__containers_.keys), "Key container is not sorted"); } - _LIBCPP_HIDE_FROM_ABI explicit flat_multimap(const key_compare& __comp) : __containers_(), __compare_(__comp) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit flat_multimap(const key_compare& __comp) + : __containers_(), __compare_(__comp) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_multimap(const key_compare& __comp, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multimap(const key_compare& __comp, const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI explicit flat_multimap(const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit flat_multimap(const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc) {} template requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap(_InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare()) : __containers_(), __compare_(__comp) { insert(__first, __last); @@ -285,7 +289,7 @@ public: template requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>) - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap(_InputIterator __first, _InputIterator __last, const key_compare& __comp, const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) { insert(__first, __last); @@ -293,91 +297,99 @@ public: template requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>) - _LIBCPP_HIDE_FROM_ABI flat_multimap(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multimap(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc) { insert(__first, __last); } template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI flat_multimap(from_range_t __fr, _Range&& __rg) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap(from_range_t __fr, _Range&& __rg) : flat_multimap(__fr, std::forward<_Range>(__rg), key_compare()) {} template <_ContainerCompatibleRange _Range, class _Allocator> requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_multimap(from_range_t, _Range&& __rg, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multimap(from_range_t, _Range&& __rg, const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc) { insert_range(std::forward<_Range>(__rg)); } template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI flat_multimap(from_range_t, _Range&& __rg, const key_compare& __comp) : flat_multimap(__comp) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multimap(from_range_t, _Range&& __rg, const key_compare& __comp) + : flat_multimap(__comp) { insert_range(std::forward<_Range>(__rg)); } template <_ContainerCompatibleRange _Range, class _Allocator> requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_multimap(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multimap(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) { insert_range(std::forward<_Range>(__rg)); } template requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI flat_multimap( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap( sorted_equivalent_t, _InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare()) : __containers_(), __compare_(__comp) { insert(sorted_equivalent, __first, __last); } template requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>) - _LIBCPP_HIDE_FROM_ABI - flat_multimap(sorted_equivalent_t, - _InputIterator __first, - _InputIterator __last, - const key_compare& __comp, - const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap( + sorted_equivalent_t, + _InputIterator __first, + _InputIterator __last, + const key_compare& __comp, + const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) { insert(sorted_equivalent, __first, __last); } template requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>) - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap(sorted_equivalent_t, _InputIterator __first, _InputIterator __last, const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc) { insert(sorted_equivalent, __first, __last); } - _LIBCPP_HIDE_FROM_ABI flat_multimap(initializer_list __il, const key_compare& __comp = key_compare()) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multimap(initializer_list __il, const key_compare& __comp = key_compare()) : flat_multimap(__il.begin(), __il.end(), __comp) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap(initializer_list __il, const key_compare& __comp, const _Allocator& __alloc) : flat_multimap(__il.begin(), __il.end(), __comp, __alloc) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_multimap(initializer_list __il, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multimap(initializer_list __il, const _Allocator& __alloc) : flat_multimap(__il.begin(), __il.end(), __alloc) {} - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap(sorted_equivalent_t, initializer_list __il, const key_compare& __comp = key_compare()) : flat_multimap(sorted_equivalent, __il.begin(), __il.end(), __comp) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_multimap( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap( sorted_equivalent_t, initializer_list __il, const key_compare& __comp, const _Allocator& __alloc) : flat_multimap(sorted_equivalent, __il.begin(), __il.end(), __comp, __alloc) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_multimap(sorted_equivalent_t, initializer_list __il, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multimap(sorted_equivalent_t, initializer_list __il, const _Allocator& __alloc) : flat_multimap(sorted_equivalent, __il.begin(), __il.end(), __alloc) {} - _LIBCPP_HIDE_FROM_ABI flat_multimap& operator=(initializer_list __il) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap& operator=(initializer_list __il) { clear(); insert(__il); return *this; @@ -386,9 +398,9 @@ public: // copy/move assignment are not specified in the spec (defaulted) // but move assignment can potentially leave moved from object in an inconsistent // state if an exception is thrown - _LIBCPP_HIDE_FROM_ABI flat_multimap& operator=(const flat_multimap&) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap& operator=(const flat_multimap&) = default; - _LIBCPP_HIDE_FROM_ABI flat_multimap& operator=(flat_multimap&& __other) noexcept( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap& operator=(flat_multimap&& __other) noexcept( is_nothrow_move_assignable_v<_KeyContainer> && is_nothrow_move_assignable_v<_MappedContainer> && is_nothrow_move_assignable_v<_Compare>) { auto __clear_other_guard = std::__make_scope_guard([&]() noexcept { __other.clear() /* noexcept */; }); @@ -400,38 +412,54 @@ public: } // iterators - _LIBCPP_HIDE_FROM_ABI iterator begin() noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator begin() noexcept { return iterator(__containers_.keys.begin(), __containers_.values.begin()); } - _LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator begin() const noexcept { return const_iterator(__containers_.keys.begin(), __containers_.values.begin()); } - _LIBCPP_HIDE_FROM_ABI iterator end() noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator end() noexcept { return iterator(__containers_.keys.end(), __containers_.values.end()); } - _LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator end() const noexcept { return const_iterator(__containers_.keys.end(), __containers_.values.end()); } - _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI reverse_iterator rend() noexcept { return reverse_iterator(begin()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rbegin() noexcept { + return reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rbegin() const noexcept { + return const_reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rend() noexcept { + return reverse_iterator(begin()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rend() const noexcept { + return const_reverse_iterator(begin()); + } - _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return begin(); } - _LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return end(); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cbegin() const noexcept { return begin(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cend() const noexcept { return end(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crbegin() const noexcept { + return const_reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crend() const noexcept { + return const_reverse_iterator(begin()); + } // [flat.map.capacity], capacity - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __containers_.keys.empty(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool empty() const noexcept { + return __containers_.keys.empty(); + } - _LIBCPP_HIDE_FROM_ABI size_type size() const noexcept { return __containers_.keys.size(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type size() const noexcept { + return __containers_.keys.size(); + } - _LIBCPP_HIDE_FROM_ABI size_type max_size() const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type max_size() const noexcept { return std::min(__containers_.keys.max_size(), __containers_.values.max_size()); } @@ -439,7 +467,7 @@ public: template requires is_constructible_v, _Args...> && is_move_constructible_v && is_move_constructible_v - _LIBCPP_HIDE_FROM_ABI iterator emplace(_Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator emplace(_Args&&... __args) { std::pair __pair(std::forward<_Args>(__args)...); auto __key_it = std::upper_bound(__containers_.keys.begin(), __containers_.keys.end(), __pair.first, __compare_); auto __mapped_it = __corresponding_mapped_it(*this, __key_it); @@ -450,7 +478,7 @@ public: template requires is_constructible_v, _Args...> - _LIBCPP_HIDE_FROM_ABI iterator emplace_hint(const_iterator __hint, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator emplace_hint(const_iterator __hint, _Args&&... __args) { std::pair __pair(std::forward<_Args>(__args)...); auto __prev_larger = __hint != cbegin() && __compare_(__pair.first, (__hint - 1)->first); @@ -490,33 +518,35 @@ public: *this, __key_iter, __mapped_iter, std::move(__pair.first), std::move(__pair.second)); } - _LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __x) { return emplace(__x); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const value_type& __x) { return emplace(__x); } - _LIBCPP_HIDE_FROM_ABI iterator insert(value_type&& __x) { return emplace(std::move(__x)); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(value_type&& __x) { + return emplace(std::move(__x)); + } - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, const value_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, const value_type& __x) { return emplace_hint(__hint, __x); } - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, value_type&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, value_type&& __x) { return emplace_hint(__hint, std::move(__x)); } template requires is_constructible_v, _PairLike> - _LIBCPP_HIDE_FROM_ABI iterator insert(_PairLike&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(_PairLike&& __x) { return emplace(std::forward<_PairLike>(__x)); } template requires is_constructible_v, _PairLike> - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, _PairLike&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, _PairLike&& __x) { return emplace_hint(__hint, std::forward<_PairLike>(__x)); } template requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(_InputIterator __first, _InputIterator __last) { if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) { __reserve(__last - __first); } @@ -525,7 +555,8 @@ public: template requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI void insert(sorted_equivalent_t, _InputIterator __first, _InputIterator __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + insert(sorted_equivalent_t, _InputIterator __first, _InputIterator __last) { if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) { __reserve(__last - __first); } @@ -534,7 +565,7 @@ public: } template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert_range(_Range&& __range) { if constexpr (ranges::sized_range<_Range>) { __reserve(ranges::size(__range)); } @@ -542,19 +573,23 @@ public: __append_sort_merge(ranges::begin(__range), ranges::end(__range)); } - _LIBCPP_HIDE_FROM_ABI void insert(initializer_list __il) { insert(__il.begin(), __il.end()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(initializer_list __il) { + insert(__il.begin(), __il.end()); + } - _LIBCPP_HIDE_FROM_ABI void insert(sorted_equivalent_t, initializer_list __il) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + insert(sorted_equivalent_t, initializer_list __il) { insert(sorted_equivalent, __il.begin(), __il.end()); } - _LIBCPP_HIDE_FROM_ABI containers extract() && { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 containers extract() && { auto __guard = std::__make_scope_guard([&]() noexcept { clear() /* noexcept */; }); auto __ret = std::move(__containers_); return __ret; } - _LIBCPP_HIDE_FROM_ABI void replace(key_container_type&& __key_cont, mapped_container_type&& __mapped_cont) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + replace(key_container_type&& __key_cont, mapped_container_type&& __mapped_cont) { _LIBCPP_ASSERT_VALID_INPUT_RANGE( __key_cont.size() == __mapped_cont.size(), "flat_multimap keys and mapped containers have different size"); @@ -565,15 +600,15 @@ public: __guard.__complete(); } - _LIBCPP_HIDE_FROM_ABI iterator erase(iterator __position) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(iterator __position) { return __erase(__position.__key_iter_, __position.__mapped_iter_); } - _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __position) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(const_iterator __position) { return __erase(__position.__key_iter_, __position.__mapped_iter_); } - _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(const key_type& __x) { auto [__first, __last] = equal_range(__x); auto __res = __last - __first; erase(__first, __last); @@ -583,14 +618,14 @@ public: template requires(__is_compare_transparent && !is_convertible_v<_Kp &&, iterator> && !is_convertible_v<_Kp &&, const_iterator>) - _LIBCPP_HIDE_FROM_ABI size_type erase(_Kp&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(_Kp&& __x) { auto [__first, __last] = equal_range(__x); auto __res = __last - __first; erase(__first, __last); return __res; } - _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(const_iterator __first, const_iterator __last) { auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); auto __key_it = __containers_.keys.erase(__first.__key_iter_, __last.__key_iter_); auto __mapped_it = __containers_.values.erase(__first.__mapped_iter_, __last.__mapped_iter_); @@ -598,7 +633,7 @@ public: return iterator(std::move(__key_it), std::move(__mapped_it)); } - _LIBCPP_HIDE_FROM_ABI void swap(flat_multimap& __y) noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(flat_multimap& __y) noexcept { // warning: The spec has unconditional noexcept, which means that // if any of the following functions throw an exception, // std::terminate will be called @@ -607,137 +642,160 @@ public: ranges::swap(__containers_.values, __y.__containers_.values); } - _LIBCPP_HIDE_FROM_ABI void clear() noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void clear() noexcept { __containers_.keys.clear(); __containers_.values.clear(); } // observers - _LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __compare_; } - _LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return value_compare(__compare_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 key_compare key_comp() const { return __compare_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 value_compare value_comp() const { + return value_compare(__compare_); + } - _LIBCPP_HIDE_FROM_ABI const key_container_type& keys() const noexcept { return __containers_.keys; } - _LIBCPP_HIDE_FROM_ABI const mapped_container_type& values() const noexcept { return __containers_.values; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const key_container_type& keys() const noexcept { + return __containers_.keys; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const mapped_container_type& values() const noexcept { + return __containers_.values; + } // map operations - _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __x) { return __find_impl(*this, __x); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const key_type& __x) { + return __find_impl(*this, __x); + } - _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __x) const { return __find_impl(*this, __x); } - - template - requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI iterator find(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const key_type& __x) const { return __find_impl(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI const_iterator find(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const _Kp& __x) { return __find_impl(*this, __x); } - _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __x) const { + template + requires __is_compare_transparent + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const _Kp& __x) const { + return __find_impl(*this, __x); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const key_type& __x) const { auto [__first, __last] = equal_range(__x); return __last - __first; } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI size_type count(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const _Kp& __x) const { auto [__first, __last] = equal_range(__x); return __last - __first; } - _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __x) const { return find(__x) != end(); } - - template - requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI bool contains(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const key_type& __x) const { return find(__x) != end(); } - _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __x) { return __lower_bound(*this, __x); } + template + requires __is_compare_transparent + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const _Kp& __x) const { + return find(__x) != end(); + } - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const key_type& __x) { + return __lower_bound(*this, __x); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const key_type& __x) const { return __lower_bound(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const _Kp& __x) { return __lower_bound(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const _Kp& __x) const { return __lower_bound(*this, __x); } - _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __x) { return __upper_bound(*this, __x); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const key_type& __x) { + return __upper_bound(*this, __x); + } - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const key_type& __x) const { return __upper_bound(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const _Kp& __x) { return __upper_bound(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const _Kp& __x) const { return __upper_bound(*this, __x); } - _LIBCPP_HIDE_FROM_ABI pair equal_range(const key_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair equal_range(const key_type& __x) { return __equal_range_impl(*this, __x); } - _LIBCPP_HIDE_FROM_ABI pair equal_range(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + equal_range(const key_type& __x) const { return __equal_range_impl(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI pair equal_range(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair equal_range(const _Kp& __x) { return __equal_range_impl(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI pair equal_range(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + equal_range(const _Kp& __x) const { return __equal_range_impl(*this, __x); } - friend _LIBCPP_HIDE_FROM_ABI bool operator==(const flat_multimap& __x, const flat_multimap& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator==(const flat_multimap& __x, const flat_multimap& __y) { return ranges::equal(__x, __y); } - friend _LIBCPP_HIDE_FROM_ABI auto operator<=>(const flat_multimap& __x, const flat_multimap& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 auto + operator<=>(const flat_multimap& __x, const flat_multimap& __y) { return std::lexicographical_compare_three_way( __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way); } - friend _LIBCPP_HIDE_FROM_ABI void swap(flat_multimap& __x, flat_multimap& __y) noexcept { __x.swap(__y); } + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + swap(flat_multimap& __x, flat_multimap& __y) noexcept { + __x.swap(__y); + } private: struct __ctor_uses_allocator_tag { - explicit _LIBCPP_HIDE_FROM_ABI __ctor_uses_allocator_tag() = default; + explicit _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __ctor_uses_allocator_tag() = default; }; struct __ctor_uses_allocator_empty_tag { - explicit _LIBCPP_HIDE_FROM_ABI __ctor_uses_allocator_empty_tag() = default; + explicit _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __ctor_uses_allocator_empty_tag() = default; }; template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI - flat_multimap(__ctor_uses_allocator_tag, - const _Allocator& __alloc, - _KeyCont&& __key_cont, - _MappedCont&& __mapped_cont, - _CompArg&&... __comp) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap( + __ctor_uses_allocator_tag, + const _Allocator& __alloc, + _KeyCont&& __key_cont, + _MappedCont&& __mapped_cont, + _CompArg&&... __comp) : __containers_{.keys = std::make_obj_using_allocator( __alloc, std::forward<_KeyCont>(__key_cont)), .values = std::make_obj_using_allocator( @@ -746,29 +804,32 @@ private: template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_multimap(__ctor_uses_allocator_empty_tag, const _Allocator& __alloc, _CompArg&&... __comp) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multimap(__ctor_uses_allocator_empty_tag, const _Allocator& __alloc, _CompArg&&... __comp) : __containers_{.keys = std::make_obj_using_allocator(__alloc), .values = std::make_obj_using_allocator(__alloc)}, __compare_(std::forward<_CompArg>(__comp)...) {} - _LIBCPP_HIDE_FROM_ABI bool __is_sorted(auto&& __key_container) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __is_sorted(auto&& __key_container) const { return ranges::is_sorted(__key_container, __compare_); } - _LIBCPP_HIDE_FROM_ABI void __sort() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __sort() { auto __zv = ranges::views::zip(__containers_.keys, __containers_.values); ranges::sort(__zv, __compare_, [](const auto& __p) -> decltype(auto) { return std::get<0>(__p); }); } template - _LIBCPP_HIDE_FROM_ABI static auto __corresponding_mapped_it(_Self&& __self, _KeyIter&& __key_iter) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto + __corresponding_mapped_it(_Self&& __self, _KeyIter&& __key_iter) { return __self.__containers_.values.begin() + static_cast>( ranges::distance(__self.__containers_.keys.begin(), __key_iter)); } template - _LIBCPP_HIDE_FROM_ABI void __append_sort_merge(_InputIterator __first, _Sentinel __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + __append_sort_merge(_InputIterator __first, _Sentinel __last) { auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); size_t __num_appended = __flat_map_utils::__append(*this, std::move(__first), std::move(__last)); if (__num_appended != 0) { @@ -791,7 +852,7 @@ private: } template - _LIBCPP_HIDE_FROM_ABI static auto __find_impl(_Self&& __self, const _Kp& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto __find_impl(_Self&& __self, const _Kp& __key) { auto __it = __self.lower_bound(__key); auto __last = __self.end(); if (__it == __last || __self.__compare_(__key, __it->first)) { @@ -801,7 +862,7 @@ private: } template - _LIBCPP_HIDE_FROM_ABI static auto __equal_range_impl(_Self&& __self, const _Kp& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto __equal_range_impl(_Self&& __self, const _Kp& __key) { auto [__key_first, __key_last] = std::equal_range(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __key, __self.__compare_); @@ -811,7 +872,7 @@ private: } template - _LIBCPP_HIDE_FROM_ABI static _Res __lower_bound(_Self&& __self, _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static _Res __lower_bound(_Self&& __self, _Kp& __x) { auto __key_iter = std::lower_bound(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __x, __self.__compare_); auto __mapped_iter = __corresponding_mapped_it(__self, __key_iter); @@ -819,14 +880,14 @@ private: } template - _LIBCPP_HIDE_FROM_ABI static _Res __upper_bound(_Self&& __self, _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static _Res __upper_bound(_Self&& __self, _Kp& __x) { auto __key_iter = std::upper_bound(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __x, __self.__compare_); auto __mapped_iter = __corresponding_mapped_it(__self, __key_iter); return _Res(std::move(__key_iter), std::move(__mapped_iter)); } - _LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __reserve(size_t __size) { if constexpr (__container_traits<_KeyContainer>::__reservable) { __containers_.keys.reserve(__size); } @@ -837,7 +898,8 @@ private: } template - _LIBCPP_HIDE_FROM_ABI iterator __erase(_KIter __key_iter_to_remove, _MIter __mapped_iter_to_remove) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + __erase(_KIter __key_iter_to_remove, _MIter __mapped_iter_to_remove) { auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); auto __key_iter = __containers_.keys.erase(__key_iter_to_remove); auto __mapped_iter = __containers_.values.erase(__mapped_iter_to_remove); @@ -847,7 +909,8 @@ private: template friend typename flat_multimap<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>::size_type - erase_if(flat_multimap<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>&, _Predicate); + _LIBCPP_CONSTEXPR_SINCE_CXX26 + erase_if(flat_multimap<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>&, _Predicate); friend __flat_map_utils; @@ -855,8 +918,9 @@ private: _LIBCPP_NO_UNIQUE_ADDRESS key_compare __compare_; struct __key_equiv { - _LIBCPP_HIDE_FROM_ABI __key_equiv(key_compare __c) : __comp_(__c) {} - _LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_equiv(key_compare __c) : __comp_(__c) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator()(const_reference __x, const_reference __y) const { return !__comp_(std::get<0>(__x), std::get<0>(__y)) && !__comp_(std::get<0>(__y), std::get<0>(__x)); } key_compare __comp_; @@ -980,8 +1044,9 @@ struct uses_allocator && uses_allocator_v<_MappedContainer, _Allocator>> {}; template -_LIBCPP_HIDE_FROM_ABI typename flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>::size_type -erase_if(flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>& __flat_multimap, _Predicate __pred) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + typename flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>::size_type + erase_if(flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>& __flat_multimap, _Predicate __pred) { auto __zv = ranges::views::zip(__flat_multimap.__containers_.keys, __flat_multimap.__containers_.values); auto __first = __zv.begin(); auto __last = __zv.end(); diff --git a/naiveproxy/src/third_party/libc++/src/include/__flat_map/key_value_iterator.h b/naiveproxy/src/third_party/libc++/src/include/__flat_map/key_value_iterator.h index 3ebb653deb..d04a23d1f8 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__flat_map/key_value_iterator.h +++ b/naiveproxy/src/third_party/libc++/src/include/__flat_map/key_value_iterator.h @@ -13,9 +13,12 @@ #include <__compare/three_way_comparable.h> #include <__concepts/convertible_to.h> #include <__config> +#include <__cstddef/size_t.h> #include <__iterator/iterator_traits.h> +#include <__iterator/product_iterator.h> #include <__memory/addressof.h> #include <__type_traits/conditional.h> +#include <__utility/forward.h> #include <__utility/move.h> #include <__utility/pair.h> @@ -46,7 +49,7 @@ private: struct __arrow_proxy { __reference __ref_; - _LIBCPP_HIDE_FROM_ABI __reference* operator->() { return std::addressof(__ref_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __reference* operator->() { return std::addressof(__ref_); } }; __key_iterator __key_iter_; @@ -57,6 +60,8 @@ private: template friend struct __key_value_iterator; + friend struct __product_iterator_traits<__key_value_iterator>; + public: using iterator_concept = random_access_iterator_tag; // `__key_value_iterator` only satisfy "Cpp17InputIterator" named requirements, because @@ -69,104 +74,141 @@ public: _LIBCPP_HIDE_FROM_ABI __key_value_iterator() = default; - _LIBCPP_HIDE_FROM_ABI __key_value_iterator(__key_value_iterator<_Owner, _KeyContainer, _MappedContainer, !_Const> __i) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + __key_value_iterator(__key_value_iterator<_Owner, _KeyContainer, _MappedContainer, !_Const> __i) requires _Const && convertible_to && convertible_to : __key_iter_(std::move(__i.__key_iter_)), __mapped_iter_(std::move(__i.__mapped_iter_)) {} - _LIBCPP_HIDE_FROM_ABI __key_value_iterator(__key_iterator __key_iter, __mapped_iterator __mapped_iter) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + __key_value_iterator(__key_iterator __key_iter, __mapped_iterator __mapped_iter) : __key_iter_(std::move(__key_iter)), __mapped_iter_(std::move(__mapped_iter)) {} - _LIBCPP_HIDE_FROM_ABI __reference operator*() const { return __reference(*__key_iter_, *__mapped_iter_); } - _LIBCPP_HIDE_FROM_ABI __arrow_proxy operator->() const { return __arrow_proxy{**this}; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __reference operator*() const { + return __reference(*__key_iter_, *__mapped_iter_); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __arrow_proxy operator->() const { return __arrow_proxy{**this}; } - _LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator++() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator& operator++() { ++__key_iter_; ++__mapped_iter_; return *this; } - _LIBCPP_HIDE_FROM_ABI __key_value_iterator operator++(int) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator operator++(int) { __key_value_iterator __tmp(*this); ++*this; return __tmp; } - _LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator--() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator& operator--() { --__key_iter_; --__mapped_iter_; return *this; } - _LIBCPP_HIDE_FROM_ABI __key_value_iterator operator--(int) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator operator--(int) { __key_value_iterator __tmp(*this); --*this; return __tmp; } - _LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator+=(difference_type __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator& operator+=(difference_type __x) { __key_iter_ += __x; __mapped_iter_ += __x; return *this; } - _LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator-=(difference_type __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator& operator-=(difference_type __x) { __key_iter_ -= __x; __mapped_iter_ -= __x; return *this; } - _LIBCPP_HIDE_FROM_ABI __reference operator[](difference_type __n) const { return *(*this + __n); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __reference operator[](difference_type __n) const { + return *(*this + __n); + } - _LIBCPP_HIDE_FROM_ABI friend constexpr bool + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend bool operator==(const __key_value_iterator& __x, const __key_value_iterator& __y) { return __x.__key_iter_ == __y.__key_iter_; } - _LIBCPP_HIDE_FROM_ABI friend bool operator<(const __key_value_iterator& __x, const __key_value_iterator& __y) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend bool + operator<(const __key_value_iterator& __x, const __key_value_iterator& __y) { return __x.__key_iter_ < __y.__key_iter_; } - _LIBCPP_HIDE_FROM_ABI friend bool operator>(const __key_value_iterator& __x, const __key_value_iterator& __y) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend bool + operator>(const __key_value_iterator& __x, const __key_value_iterator& __y) { return __y < __x; } - _LIBCPP_HIDE_FROM_ABI friend bool operator<=(const __key_value_iterator& __x, const __key_value_iterator& __y) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend bool + operator<=(const __key_value_iterator& __x, const __key_value_iterator& __y) { return !(__y < __x); } - _LIBCPP_HIDE_FROM_ABI friend bool operator>=(const __key_value_iterator& __x, const __key_value_iterator& __y) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend bool + operator>=(const __key_value_iterator& __x, const __key_value_iterator& __y) { return !(__x < __y); } - _LIBCPP_HIDE_FROM_ABI friend auto operator<=>(const __key_value_iterator& __x, const __key_value_iterator& __y) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend auto + operator<=>(const __key_value_iterator& __x, const __key_value_iterator& __y) requires three_way_comparable<__key_iterator> { return __x.__key_iter_ <=> __y.__key_iter_; } - _LIBCPP_HIDE_FROM_ABI friend __key_value_iterator operator+(const __key_value_iterator& __i, difference_type __n) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend __key_value_iterator + operator+(const __key_value_iterator& __i, difference_type __n) { auto __tmp = __i; __tmp += __n; return __tmp; } - _LIBCPP_HIDE_FROM_ABI friend __key_value_iterator operator+(difference_type __n, const __key_value_iterator& __i) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend __key_value_iterator + operator+(difference_type __n, const __key_value_iterator& __i) { return __i + __n; } - _LIBCPP_HIDE_FROM_ABI friend __key_value_iterator operator-(const __key_value_iterator& __i, difference_type __n) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend __key_value_iterator + operator-(const __key_value_iterator& __i, difference_type __n) { auto __tmp = __i; __tmp -= __n; return __tmp; } - _LIBCPP_HIDE_FROM_ABI friend difference_type + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend difference_type operator-(const __key_value_iterator& __x, const __key_value_iterator& __y) { return difference_type(__x.__key_iter_ - __y.__key_iter_); } }; +template +struct __product_iterator_traits<__key_value_iterator<_Owner, _KeyContainer, _MappedContainer, _Const>> { + static constexpr size_t __size = 2; + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static decltype(auto) __get_iterator_element(_Iter&& __it) + requires(_Nth <= 1) + { + if constexpr (_Nth == 0) { + return std::forward<_Iter>(__it).__key_iter_; + } else { + return std::forward<_Iter>(__it).__mapped_iter_; + } + } + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto + __make_product_iterator(_KeyIter&& __key_iter, _MappedIter&& __mapped_iter) { + return __key_value_iterator<_Owner, _KeyContainer, _MappedContainer, _Const>( + std::forward<_KeyIter>(__key_iter), std::forward<_MappedIter>(__mapped_iter)); + } +}; + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_STD_VER >= 23 diff --git a/naiveproxy/src/third_party/libc++/src/include/__flat_map/utils.h b/naiveproxy/src/third_party/libc++/src/include/__flat_map/utils.h index acb7dca7ff..3a05c71566 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__flat_map/utils.h +++ b/naiveproxy/src/third_party/libc++/src/include/__flat_map/utils.h @@ -11,6 +11,7 @@ #define _LIBCPP___FLAT_MAP_UTILS_H #include <__config> +#include <__iterator/product_iterator.h> #include <__type_traits/container_traits.h> #include <__utility/exception_guard.h> #include <__utility/forward.h> @@ -35,7 +36,7 @@ struct __flat_map_utils { // roll back the changes it made to the map. If it cannot roll back the changes, it will // clear the map. template - _LIBCPP_HIDE_FROM_ABI static typename _Map::iterator __emplace_exact_pos( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static typename _Map::iterator __emplace_exact_pos( _Map& __map, _IterK&& __it_key, _IterM&& __it_mapped, _KeyArg&& __key, _MArgs&&... __mapped_args) { auto __on_key_failed = std::__make_exception_guard([&]() noexcept { using _KeyContainer = typename _Map::key_container_type; @@ -79,10 +80,8 @@ struct __flat_map_utils { return typename _Map::iterator(std::move(__key_it), std::move(__mapped_it)); } - // TODO: We could optimize this, see - // https://github.com/llvm/llvm-project/issues/108624 template - _LIBCPP_HIDE_FROM_ABI static typename _Map::size_type + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static typename _Map::size_type __append(_Map& __map, _InputIterator __first, _Sentinel __last) { typename _Map::size_type __num_appended = 0; for (; __first != __last; ++__first) { @@ -93,6 +92,25 @@ struct __flat_map_utils { } return __num_appended; } + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static typename _Map::size_type + __append(_Map& __map, _InputIterator __first, _InputIterator __last) + requires __is_product_iterator_of_size<_InputIterator, 2>::value + { + auto __s1 = __map.__containers_.keys.size(); + __map.__containers_.keys.insert( + __map.__containers_.keys.end(), + __product_iterator_traits<_InputIterator>::template __get_iterator_element<0>(__first), + __product_iterator_traits<_InputIterator>::template __get_iterator_element<0>(__last)); + + __map.__containers_.values.insert( + __map.__containers_.values.end(), + __product_iterator_traits<_InputIterator>::template __get_iterator_element<1>(__first), + __product_iterator_traits<_InputIterator>::template __get_iterator_element<1>(__last)); + + return __map.__containers_.keys.size() - __s1; + } }; _LIBCPP_END_NAMESPACE_STD diff --git a/naiveproxy/src/third_party/libc++/src/include/__flat_set/flat_set.h b/naiveproxy/src/third_party/libc++/src/include/__flat_set/flat_set.h index b8edd8eee0..95cb998459 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__flat_set/flat_set.h +++ b/naiveproxy/src/third_party/libc++/src/include/__flat_set/flat_set.h @@ -107,13 +107,13 @@ public: public: // [flat.set.cons], construct/copy/destroy - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set() noexcept(is_nothrow_default_constructible_v<_KeyContainer> && is_nothrow_default_constructible_v<_Compare>) : __keys_(), __compare_() {} - _LIBCPP_HIDE_FROM_ABI flat_set(const flat_set&) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(const flat_set&) = default; - _LIBCPP_HIDE_FROM_ABI flat_set(flat_set&& __other) noexcept( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(flat_set&& __other) noexcept( is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_Compare>) # if _LIBCPP_HAS_EXCEPTIONS try @@ -130,14 +130,17 @@ public: # endif // _LIBCPP_HAS_EXCEPTIONS } - _LIBCPP_HIDE_FROM_ABI explicit flat_set(const key_compare& __comp) : __keys_(), __compare_(__comp) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit flat_set(const key_compare& __comp) + : __keys_(), __compare_(__comp) {} - _LIBCPP_HIDE_FROM_ABI explicit flat_set(container_type __keys, const key_compare& __comp = key_compare()) + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit flat_set(container_type __keys, const key_compare& __comp = key_compare()) : __keys_(std::move(__keys)), __compare_(__comp) { __sort_and_unique(); } - _LIBCPP_HIDE_FROM_ABI flat_set(sorted_unique_t, container_type __keys, const key_compare& __comp = key_compare()) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(sorted_unique_t, container_type __keys, const key_compare& __comp = key_compare()) : __keys_(std::move(__keys)), __compare_(__comp) { _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT( __is_sorted_and_unique(__keys_), "Either the key container is not sorted or it contains duplicates"); @@ -145,7 +148,7 @@ public: template requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(_InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare()) : __keys_(), __compare_(__comp) { insert(__first, __last); @@ -153,7 +156,7 @@ public: template requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(sorted_unique_t, _InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare()) : __keys_(__first, __last), __compare_(__comp) { _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT( @@ -161,48 +164,52 @@ public: } template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI flat_set(from_range_t, _Range&& __rg) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(from_range_t, _Range&& __rg) : flat_set(from_range, std::forward<_Range>(__rg), key_compare()) {} template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI flat_set(from_range_t, _Range&& __rg, const key_compare& __comp) : flat_set(__comp) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(from_range_t, _Range&& __rg, const key_compare& __comp) + : flat_set(__comp) { insert_range(std::forward<_Range>(__rg)); } - _LIBCPP_HIDE_FROM_ABI flat_set(initializer_list __il, const key_compare& __comp = key_compare()) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(initializer_list __il, const key_compare& __comp = key_compare()) : flat_set(__il.begin(), __il.end(), __comp) {} - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(sorted_unique_t, initializer_list __il, const key_compare& __comp = key_compare()) : flat_set(sorted_unique, __il.begin(), __il.end(), __comp) {} template requires uses_allocator::value - _LIBCPP_HIDE_FROM_ABI explicit flat_set(const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit flat_set(const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator(__alloc)), __compare_() {} template requires uses_allocator::value - _LIBCPP_HIDE_FROM_ABI flat_set(const key_compare& __comp, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(const key_compare& __comp, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator(__alloc)), __compare_(__comp) {} template requires uses_allocator::value - _LIBCPP_HIDE_FROM_ABI flat_set(const container_type& __keys, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(const container_type& __keys, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator(__alloc, __keys)), __compare_() { __sort_and_unique(); } template requires uses_allocator::value - _LIBCPP_HIDE_FROM_ABI flat_set(const container_type& __keys, const key_compare& __comp, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(const container_type& __keys, const key_compare& __comp, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator(__alloc, __keys)), __compare_(__comp) { __sort_and_unique(); } template requires uses_allocator::value - _LIBCPP_HIDE_FROM_ABI flat_set(sorted_unique_t, const container_type& __keys, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(sorted_unique_t, const container_type& __keys, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator(__alloc, __keys)), __compare_() { _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT( __is_sorted_and_unique(__keys_), "Either the key container is not sorted or it contains duplicates"); @@ -210,7 +217,7 @@ public: template requires uses_allocator::value - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(sorted_unique_t, const container_type& __keys, const key_compare& __comp, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator(__alloc, __keys)), __compare_(__comp) { _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT( @@ -219,13 +226,13 @@ public: template requires uses_allocator::value - _LIBCPP_HIDE_FROM_ABI flat_set(const flat_set& __other, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(const flat_set& __other, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator(__alloc, __other.__keys_)), __compare_(__other.__compare_) {} template requires uses_allocator::value - _LIBCPP_HIDE_FROM_ABI flat_set(flat_set&& __other, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(flat_set&& __other, const _Allocator& __alloc) # if _LIBCPP_HAS_EXCEPTIONS try # endif // _LIBCPP_HAS_EXCEPTIONS @@ -241,14 +248,15 @@ public: template requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator::value) - _LIBCPP_HIDE_FROM_ABI flat_set(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator(__alloc)), __compare_() { insert(__first, __last); } template requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator::value) - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(_InputIterator __first, _InputIterator __last, const key_compare& __comp, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator(__alloc)), __compare_(__comp) { insert(__first, __last); @@ -256,7 +264,7 @@ public: template requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator::value) - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(sorted_unique_t, _InputIterator __first, _InputIterator __last, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator(__alloc, __first, __last)), __compare_() { _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT( @@ -265,12 +273,12 @@ public: template requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator::value) - _LIBCPP_HIDE_FROM_ABI - flat_set(sorted_unique_t, - _InputIterator __first, - _InputIterator __last, - const key_compare& __comp, - const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set( + sorted_unique_t, + _InputIterator __first, + _InputIterator __last, + const key_compare& __comp, + const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator(__alloc, __first, __last)), __compare_(__comp) { _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT( __is_sorted_and_unique(__keys_), "Either the key container is not sorted or it contains duplicates"); @@ -278,49 +286,52 @@ public: template <_ContainerCompatibleRange _Range, class _Allocator> requires uses_allocator::value - _LIBCPP_HIDE_FROM_ABI flat_set(from_range_t, _Range&& __rg, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(from_range_t, _Range&& __rg, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator(__alloc)), __compare_() { insert_range(std::forward<_Range>(__rg)); } template <_ContainerCompatibleRange _Range, class _Allocator> requires uses_allocator::value - _LIBCPP_HIDE_FROM_ABI flat_set(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator(__alloc)), __compare_(__comp) { insert_range(std::forward<_Range>(__rg)); } template requires uses_allocator::value - _LIBCPP_HIDE_FROM_ABI flat_set(initializer_list __il, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(initializer_list __il, const _Allocator& __alloc) : flat_set(__il.begin(), __il.end(), __alloc) {} template requires uses_allocator::value - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(initializer_list __il, const key_compare& __comp, const _Allocator& __alloc) : flat_set(__il.begin(), __il.end(), __comp, __alloc) {} template requires uses_allocator::value - _LIBCPP_HIDE_FROM_ABI flat_set(sorted_unique_t, initializer_list __il, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_set(sorted_unique_t, initializer_list __il, const _Allocator& __alloc) : flat_set(sorted_unique, __il.begin(), __il.end(), __alloc) {} template requires uses_allocator::value - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(sorted_unique_t, initializer_list __il, const key_compare& __comp, const _Allocator& __alloc) : flat_set(sorted_unique, __il.begin(), __il.end(), __comp, __alloc) {} - _LIBCPP_HIDE_FROM_ABI flat_set& operator=(initializer_list __il) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set& operator=(initializer_list __il) { clear(); insert(__il); return *this; } - _LIBCPP_HIDE_FROM_ABI flat_set& operator=(const flat_set&) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set& operator=(const flat_set&) = default; - _LIBCPP_HIDE_FROM_ABI flat_set& operator=(flat_set&& __other) noexcept( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set& operator=(flat_set&& __other) noexcept( is_nothrow_move_assignable_v<_KeyContainer> && is_nothrow_move_assignable_v<_Compare>) { // No matter what happens, we always want to clear the other container before returning // since we moved from it @@ -336,31 +347,53 @@ public: } // iterators - _LIBCPP_HIDE_FROM_ABI iterator begin() noexcept { return iterator(std::as_const(__keys_).begin()); } - _LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept { return const_iterator(__keys_.begin()); } - _LIBCPP_HIDE_FROM_ABI iterator end() noexcept { return iterator(std::as_const(__keys_).end()); } - _LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept { return const_iterator(__keys_.end()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator begin() noexcept { + return iterator(std::as_const(__keys_).begin()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator begin() const noexcept { + return const_iterator(__keys_.begin()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator end() noexcept { + return iterator(std::as_const(__keys_).end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator end() const noexcept { + return const_iterator(__keys_.end()); + } - _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI reverse_iterator rend() noexcept { return reverse_iterator(begin()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rbegin() noexcept { + return reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rbegin() const noexcept { + return const_reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rend() noexcept { + return reverse_iterator(begin()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rend() const noexcept { + return const_reverse_iterator(begin()); + } - _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return begin(); } - _LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return end(); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cbegin() const noexcept { return begin(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cend() const noexcept { return end(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crbegin() const noexcept { + return const_reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crend() const noexcept { + return const_reverse_iterator(begin()); + } // [flat.set.capacity], capacity - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __keys_.empty(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool empty() const noexcept { + return __keys_.empty(); + } - _LIBCPP_HIDE_FROM_ABI size_type size() const noexcept { return __keys_.size(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type size() const noexcept { return __keys_.size(); } - _LIBCPP_HIDE_FROM_ABI size_type max_size() const noexcept { return __keys_.max_size(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type max_size() const noexcept { return __keys_.max_size(); } // [flat.set.modifiers], modifiers template - _LIBCPP_HIDE_FROM_ABI pair emplace(_Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair emplace(_Args&&... __args) { if constexpr (sizeof...(__args) == 1 && (is_same_v, _Key> && ...)) { return __emplace(std::forward<_Args>(__args)...); } else { @@ -369,7 +402,7 @@ public: } template - _LIBCPP_HIDE_FROM_ABI iterator emplace_hint(const_iterator __hint, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator emplace_hint(const_iterator __hint, _Args&&... __args) { if constexpr (sizeof...(__args) == 1 && (is_same_v, _Key> && ...)) { return __emplace_hint(std::move(__hint), std::forward<_Args>(__args)...); } else { @@ -377,32 +410,36 @@ public: } } - _LIBCPP_HIDE_FROM_ABI pair insert(const value_type& __x) { return emplace(__x); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair insert(const value_type& __x) { + return emplace(__x); + } - _LIBCPP_HIDE_FROM_ABI pair insert(value_type&& __x) { return emplace(std::move(__x)); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair insert(value_type&& __x) { + return emplace(std::move(__x)); + } template requires(__is_transparent_v<_Compare> && is_constructible_v) - _LIBCPP_HIDE_FROM_ABI pair insert(_Kp&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair insert(_Kp&& __x) { return __emplace(std::forward<_Kp>(__x)); } - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, const value_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, const value_type& __x) { return emplace_hint(__hint, __x); } - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, value_type&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, value_type&& __x) { return emplace_hint(__hint, std::move(__x)); } template requires(__is_transparent_v<_Compare> && is_constructible_v) - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, _Kp&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, _Kp&& __x) { return __emplace_hint(__hint, std::forward<_Kp>(__x)); } template requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(_InputIterator __first, _InputIterator __last) { if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) { __reserve(__last - __first); } @@ -411,7 +448,8 @@ public: template requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI void insert(sorted_unique_t, _InputIterator __first, _InputIterator __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + insert(sorted_unique_t, _InputIterator __first, _InputIterator __last) { if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) { __reserve(__last - __first); } @@ -420,7 +458,7 @@ public: } template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert_range(_Range&& __range) { if constexpr (ranges::sized_range<_Range>) { __reserve(ranges::size(__range)); } @@ -428,19 +466,21 @@ public: __append_sort_merge_unique(std::forward<_Range>(__range)); } - _LIBCPP_HIDE_FROM_ABI void insert(initializer_list __il) { insert(__il.begin(), __il.end()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(initializer_list __il) { + insert(__il.begin(), __il.end()); + } - _LIBCPP_HIDE_FROM_ABI void insert(sorted_unique_t, initializer_list __il) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(sorted_unique_t, initializer_list __il) { insert(sorted_unique, __il.begin(), __il.end()); } - _LIBCPP_HIDE_FROM_ABI container_type extract() && { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 container_type extract() && { auto __guard = std::__make_scope_guard([&]() noexcept { clear() /* noexcept */; }); auto __ret = std::move(__keys_); return __ret; } - _LIBCPP_HIDE_FROM_ABI void replace(container_type&& __keys) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void replace(container_type&& __keys) { _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT( __is_sorted_and_unique(__keys), "Either the key container is not sorted or it contains duplicates"); auto __guard = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); @@ -448,7 +488,7 @@ public: __guard.__complete(); } - _LIBCPP_HIDE_FROM_ABI iterator erase(iterator __position) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(iterator __position) { auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); auto __key_iter = __keys_.erase(__position.__base()); __on_failure.__complete(); @@ -458,7 +498,7 @@ public: // The following overload is the same as the iterator overload // iterator erase(const_iterator __position); - _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(const key_type& __x) { auto __iter = find(__x); if (__iter != end()) { erase(__iter); @@ -470,21 +510,21 @@ public: template requires(__is_transparent_v<_Compare> && !is_convertible_v<_Kp &&, iterator> && !is_convertible_v<_Kp &&, const_iterator>) - _LIBCPP_HIDE_FROM_ABI size_type erase(_Kp&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(_Kp&& __x) { auto [__first, __last] = equal_range(__x); auto __res = __last - __first; erase(__first, __last); return __res; } - _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(const_iterator __first, const_iterator __last) { auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); auto __key_it = __keys_.erase(__first.__base(), __last.__base()); __on_failure.__complete(); return iterator(std::move(__key_it)); } - _LIBCPP_HIDE_FROM_ABI void swap(flat_set& __y) noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(flat_set& __y) noexcept { // warning: The spec has unconditional noexcept, which means that // if any of the following functions throw an exception, // std::terminate will be called. @@ -493,121 +533,134 @@ public: ranges::swap(__keys_, __y.__keys_); } - _LIBCPP_HIDE_FROM_ABI void clear() noexcept { __keys_.clear(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void clear() noexcept { __keys_.clear(); } // observers - _LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __compare_; } - _LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return __compare_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 key_compare key_comp() const { return __compare_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 value_compare value_comp() const { return __compare_; } // set operations - _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __x) { return __find_impl(*this, __x); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const key_type& __x) { + return __find_impl(*this, __x); + } - _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __x) const { return __find_impl(*this, __x); } - - template - requires __is_transparent_v<_Compare> - _LIBCPP_HIDE_FROM_ABI iterator find(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const key_type& __x) const { return __find_impl(*this, __x); } template requires __is_transparent_v<_Compare> - _LIBCPP_HIDE_FROM_ABI const_iterator find(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const _Kp& __x) { return __find_impl(*this, __x); } - _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __x) const { return contains(__x) ? 1 : 0; } - template requires __is_transparent_v<_Compare> - _LIBCPP_HIDE_FROM_ABI size_type count(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const _Kp& __x) const { + return __find_impl(*this, __x); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const key_type& __x) const { return contains(__x) ? 1 : 0; } - _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __x) const { return find(__x) != end(); } - template requires __is_transparent_v<_Compare> - _LIBCPP_HIDE_FROM_ABI bool contains(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const _Kp& __x) const { + return contains(__x) ? 1 : 0; + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const key_type& __x) const { return find(__x) != end(); } - _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __x) { + template + requires __is_transparent_v<_Compare> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const _Kp& __x) const { + return find(__x) != end(); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const key_type& __x) { const auto& __keys = __keys_; return iterator(std::lower_bound(__keys.begin(), __keys.end(), __x, __compare_)); } - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const key_type& __x) const { return const_iterator(std::lower_bound(__keys_.begin(), __keys_.end(), __x, __compare_)); } template requires __is_transparent_v<_Compare> - _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const _Kp& __x) { const auto& __keys = __keys_; return iterator(std::lower_bound(__keys.begin(), __keys.end(), __x, __compare_)); } template requires __is_transparent_v<_Compare> - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const _Kp& __x) const { return const_iterator(std::lower_bound(__keys_.begin(), __keys_.end(), __x, __compare_)); } - _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const key_type& __x) { const auto& __keys = __keys_; return iterator(std::upper_bound(__keys.begin(), __keys.end(), __x, __compare_)); } - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const key_type& __x) const { return const_iterator(std::upper_bound(__keys_.begin(), __keys_.end(), __x, __compare_)); } template requires __is_transparent_v<_Compare> - _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const _Kp& __x) { const auto& __keys = __keys_; return iterator(std::upper_bound(__keys.begin(), __keys.end(), __x, __compare_)); } template requires __is_transparent_v<_Compare> - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const _Kp& __x) const { return const_iterator(std::upper_bound(__keys_.begin(), __keys_.end(), __x, __compare_)); } - _LIBCPP_HIDE_FROM_ABI pair equal_range(const key_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair equal_range(const key_type& __x) { return __equal_range_impl(*this, __x); } - _LIBCPP_HIDE_FROM_ABI pair equal_range(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + equal_range(const key_type& __x) const { return __equal_range_impl(*this, __x); } template requires __is_transparent_v<_Compare> - _LIBCPP_HIDE_FROM_ABI pair equal_range(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair equal_range(const _Kp& __x) { return __equal_range_impl(*this, __x); } template requires __is_transparent_v<_Compare> - _LIBCPP_HIDE_FROM_ABI pair equal_range(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + equal_range(const _Kp& __x) const { return __equal_range_impl(*this, __x); } - friend _LIBCPP_HIDE_FROM_ABI bool operator==(const flat_set& __x, const flat_set& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator==(const flat_set& __x, const flat_set& __y) { return ranges::equal(__x, __y); } - friend _LIBCPP_HIDE_FROM_ABI auto operator<=>(const flat_set& __x, const flat_set& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 auto + operator<=>(const flat_set& __x, const flat_set& __y) { return std::lexicographical_compare_three_way( __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way); } - friend _LIBCPP_HIDE_FROM_ABI void swap(flat_set& __x, flat_set& __y) noexcept { __x.swap(__y); } + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(flat_set& __x, flat_set& __y) noexcept { + __x.swap(__y); + } private: - _LIBCPP_HIDE_FROM_ABI bool __is_sorted_and_unique(auto&& __key_container) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __is_sorted_and_unique(auto&& __key_container) const { auto __greater_or_equal_to = [this](const auto& __x, const auto& __y) { return !__compare_(__x, __y); }; return ranges::adjacent_find(__key_container, __greater_or_equal_to) == ranges::end(__key_container); } @@ -615,14 +668,14 @@ private: // This function is only used in constructors. So there is not exception handling in this function. // If the function exits via an exception, there will be no flat_set object constructed, thus, there // is no invariant state to preserve - _LIBCPP_HIDE_FROM_ABI void __sort_and_unique() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __sort_and_unique() { ranges::sort(__keys_, __compare_); auto __dup_start = ranges::unique(__keys_, __key_equiv(__compare_)).begin(); __keys_.erase(__dup_start, __keys_.end()); } template - _LIBCPP_HIDE_FROM_ABI void __append_sort_merge_unique(_Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __append_sort_merge_unique(_Args&&... __args) { auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); size_type __old_size = size(); __flat_set_utils::__append(*this, std::forward<_Args>(__args)...); @@ -642,7 +695,7 @@ private: } template - _LIBCPP_HIDE_FROM_ABI static auto __find_impl(_Self&& __self, const _Kp& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto __find_impl(_Self&& __self, const _Kp& __key) { auto __it = __self.lower_bound(__key); auto __last = __self.end(); if (__it == __last || __self.__compare_(__key, *__it)) { @@ -652,7 +705,7 @@ private: } template - _LIBCPP_HIDE_FROM_ABI static auto __equal_range_impl(_Self&& __self, const _Kp& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto __equal_range_impl(_Self&& __self, const _Kp& __key) { using __iter = _If>, const_iterator, iterator>; auto __it = std::lower_bound(__self.__keys_.begin(), __self.__keys_.end(), __key, __self.__compare_); auto __last = __self.__keys_.end(); @@ -663,7 +716,7 @@ private: } template - _LIBCPP_HIDE_FROM_ABI pair __emplace(_Kp&& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair __emplace(_Kp&& __key) { auto __it = lower_bound(__key); if (__it == end() || __compare_(__key, *__it)) { return pair(__flat_set_utils::__emplace_exact_pos(*this, __it, std::forward<_Kp>(__key)), true); @@ -673,7 +726,7 @@ private: } template - _LIBCPP_HIDE_FROM_ABI bool __is_hint_correct(const_iterator __hint, _Kp&& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __is_hint_correct(const_iterator __hint, _Kp&& __key) { if (__hint != cbegin() && !__compare_(*std::prev(__hint), __key)) { return false; } @@ -684,7 +737,7 @@ private: } template - _LIBCPP_HIDE_FROM_ABI iterator __emplace_hint(const_iterator __hint, _Kp&& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __emplace_hint(const_iterator __hint, _Kp&& __key) { if (__is_hint_correct(__hint, __key)) { if (__hint == cend() || __compare_(__key, *__hint)) { return __flat_set_utils::__emplace_exact_pos(*this, __hint, std::forward<_Kp>(__key)); @@ -697,22 +750,23 @@ private: } } - _LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __reserve(size_t __size) { if constexpr (__container_traits<_KeyContainer>::__reservable) { __keys_.reserve(__size); } } template - friend typename flat_set<_Key2, _Compare2, _KeyContainer2>::size_type + friend typename flat_set<_Key2, _Compare2, _KeyContainer2>::size_type _LIBCPP_CONSTEXPR_SINCE_CXX26 erase_if(flat_set<_Key2, _Compare2, _KeyContainer2>&, _Predicate); _KeyContainer __keys_; _LIBCPP_NO_UNIQUE_ADDRESS key_compare __compare_; struct __key_equiv { - _LIBCPP_HIDE_FROM_ABI __key_equiv(key_compare __c) : __comp_(__c) {} - _LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_equiv(key_compare __c) : __comp_(__c) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator()(const_reference __x, const_reference __y) const { return !__comp_(__x, __y) && !__comp_(__y, __x); } key_compare __comp_; @@ -799,7 +853,7 @@ struct uses_allocator, _Allocator> : bool_constant> {}; template -_LIBCPP_HIDE_FROM_ABI typename flat_set<_Key, _Compare, _KeyContainer>::size_type +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 typename flat_set<_Key, _Compare, _KeyContainer>::size_type erase_if(flat_set<_Key, _Compare, _KeyContainer>& __flat_set, _Predicate __pred) { auto __guard = std::__make_exception_guard([&] { __flat_set.clear(); }); auto __it = std::remove_if(__flat_set.__keys_.begin(), __flat_set.__keys_.end(), [&](const auto& __e) -> bool { diff --git a/naiveproxy/src/third_party/libc++/src/include/__flat_set/utils.h b/naiveproxy/src/third_party/libc++/src/include/__flat_set/utils.h index 542bfd886a..8a7f93a004 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__flat_set/utils.h +++ b/naiveproxy/src/third_party/libc++/src/include/__flat_set/utils.h @@ -38,7 +38,8 @@ struct __flat_set_utils { // When an exception is thrown during the emplacement, the function will clear the set if the container does not // have strong exception safety guarantee on emplacement. template - _LIBCPP_HIDE_FROM_ABI static auto __emplace_exact_pos(_Set& __set, _Iter&& __iter, _KeyArg&& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto + __emplace_exact_pos(_Set& __set, _Iter&& __iter, _KeyArg&& __key) { using _KeyContainer = typename decay_t<_Set>::container_type; auto __on_failure = std::__make_exception_guard([&]() noexcept { if constexpr (!__container_traits<_KeyContainer>::__emplacement_has_strong_exception_safety_guarantee) { @@ -51,12 +52,13 @@ struct __flat_set_utils { } template - _LIBCPP_HIDE_FROM_ABI static void __append(_Set& __set, _InputIterator __first, _InputIterator __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static void + __append(_Set& __set, _InputIterator __first, _InputIterator __last) { __set.__keys_.insert(__set.__keys_.end(), std::move(__first), std::move(__last)); } template - _LIBCPP_HIDE_FROM_ABI static void __append(_Set& __set, _Range&& __rng) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static void __append(_Set& __set, _Range&& __rng) { if constexpr (requires { __set.__keys_.insert_range(__set.__keys_.end(), std::forward<_Range>(__rng)); }) { // C++23 Sequence Container should have insert_range member function // Note that not all Sequence Containers provide append_range. diff --git a/naiveproxy/src/third_party/libc++/src/include/__format/concepts.h b/naiveproxy/src/third_party/libc++/src/include/__format/concepts.h index 28297c612d..5b603701c0 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__format/concepts.h +++ b/naiveproxy/src/third_party/libc++/src/include/__format/concepts.h @@ -15,12 +15,8 @@ #include <__config> #include <__format/format_parse_context.h> #include <__fwd/format.h> -#include <__fwd/tuple.h> -#include <__tuple/tuple_size.h> -#include <__type_traits/is_specialization.h> #include <__type_traits/remove_const.h> #include <__type_traits/remove_reference.h> -#include <__utility/pair.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -65,16 +61,6 @@ concept __formattable = # if _LIBCPP_STD_VER >= 23 template concept formattable = __formattable<_Tp, _CharT>; - -// [tuple.like] defines a tuple-like exposition only concept. This concept is -// not related to that. Therefore it uses a different name for the concept. -// -// TODO FMT Add a test to validate we fail when using that concept after P2165 -// has been implemented. -template -concept __fmt_pair_like = - __is_specialization_v<_Tp, pair> || (__is_specialization_v<_Tp, tuple> && tuple_size_v<_Tp> == 2); - # endif // _LIBCPP_STD_VER >= 23 #endif // _LIBCPP_STD_VER >= 20 diff --git a/naiveproxy/src/third_party/libc++/src/include/__format/fmt_pair_like.h b/naiveproxy/src/third_party/libc++/src/include/__format/fmt_pair_like.h new file mode 100644 index 0000000000..d2f2f54d5a --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__format/fmt_pair_like.h @@ -0,0 +1,42 @@ +// -*- 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___FORMAT_FMT_PAIR_LIKE_H +#define _LIBCPP___FORMAT_FMT_PAIR_LIKE_H + +#include <__config> +#include <__fwd/pair.h> +#include <__fwd/tuple.h> +#include <__tuple/tuple_size.h> +#include <__type_traits/is_specialization.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +// [tuple.like] defines a tuple-like exposition only concept. This concept is not related to that. Therefore it uses a +// different name for the concept. +// +// TODO FMT Add a test to validate we fail when using that concept after P2165 has been implemented. + +// [format.range.fmtkind]/2.2.1 and [tab:formatter.range.type]: +// "U is either a specialization of pair or a specialization of tuple such that tuple_size_v is 2." +template +concept __fmt_pair_like = + __is_specialization_v<_Tp, pair> || (__is_specialization_v<_Tp, tuple> && tuple_size_v<_Tp> == 2); + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FMT_PAIR_LIKE_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__format/format_arg_store.h b/naiveproxy/src/third_party/libc++/src/include/__format/format_arg_store.h index 87557aa4da..fbb4cad21b 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__format/format_arg_store.h +++ b/naiveproxy/src/third_party/libc++/src/include/__format/format_arg_store.h @@ -14,7 +14,6 @@ # pragma GCC system_header #endif -#include <__concepts/arithmetic.h> #include <__concepts/same_as.h> #include <__config> #include <__cstddef/size_t.h> @@ -22,6 +21,7 @@ #include <__format/format_arg.h> #include <__type_traits/conditional.h> #include <__type_traits/extent.h> +#include <__type_traits/integer_traits.h> #include <__type_traits/remove_const.h> #include #include @@ -65,7 +65,7 @@ consteval __arg_t __determine_arg_t() { # endif // Signed integers -template +template consteval __arg_t __determine_arg_t() { if constexpr (sizeof(_Tp) <= sizeof(int)) return __arg_t::__int; @@ -80,7 +80,7 @@ consteval __arg_t __determine_arg_t() { } // Unsigned integers -template +template consteval __arg_t __determine_arg_t() { if constexpr (sizeof(_Tp) <= sizeof(unsigned)) return __arg_t::__unsigned; diff --git a/naiveproxy/src/third_party/libc++/src/include/__format/range_default_formatter.h b/naiveproxy/src/third_party/libc++/src/include/__format/range_default_formatter.h index 7149debb2f..2d2190657b 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__format/range_default_formatter.h +++ b/naiveproxy/src/third_party/libc++/src/include/__format/range_default_formatter.h @@ -16,10 +16,11 @@ #include <__algorithm/ranges_copy.h> #include <__chrono/statically_widen.h> -#include <__concepts/same_as.h> #include <__config> #include <__format/concepts.h> +#include <__format/fmt_pair_like.h> #include <__format/formatter.h> +#include <__format/range_format.h> #include <__format/range_formatter.h> #include <__iterator/back_insert_iterator.h> #include <__ranges/concepts.h> @@ -42,51 +43,11 @@ concept __const_formattable_range = template using __fmt_maybe_const _LIBCPP_NODEBUG = conditional_t<__const_formattable_range<_Rp, _CharT>, const _Rp, _Rp>; -_LIBCPP_DIAGNOSTIC_PUSH -_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wshadow") -_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshadow") -// This shadows map, set, and string. -enum class range_format { disabled, map, set, sequence, string, debug_string }; -_LIBCPP_DIAGNOSTIC_POP - // There is no definition of this struct, it's purely intended to be used to // generate diagnostics. template struct __instantiated_the_primary_template_of_format_kind; -template -constexpr range_format format_kind = [] { - // [format.range.fmtkind]/1 - // A program that instantiates the primary template of format_kind is ill-formed. - static_assert(sizeof(_Rp) != sizeof(_Rp), "create a template specialization of format_kind for your type"); - return range_format::disabled; -}(); - -template - requires same_as<_Rp, remove_cvref_t<_Rp>> -inline constexpr range_format format_kind<_Rp> = [] { - // [format.range.fmtkind]/2 - - // 2.1 If same_as>, R> is true, - // Otherwise format_kind is range_format::disabled. - if constexpr (same_as>, _Rp>) - return range_format::disabled; - // 2.2 Otherwise, if the qualified-id R::key_type is valid and denotes a type: - else if constexpr (requires { typename _Rp::key_type; }) { - // 2.2.1 If the qualified-id R::mapped_type is valid and denotes a type ... - if constexpr (requires { typename _Rp::mapped_type; } && - // 2.2.1 ... If either U is a specialization of pair or U is a specialization - // of tuple and tuple_size_v == 2 - __fmt_pair_like>>) - return range_format::map; - else - // 2.2.2 Otherwise format_kind is range_format::set. - return range_format::set; - } else - // 2.3 Otherwise, format_kind is range_format::sequence. - return range_format::sequence; -}(); - template struct __range_default_formatter; diff --git a/naiveproxy/src/third_party/libc++/src/include/__format/range_format.h b/naiveproxy/src/third_party/libc++/src/include/__format/range_format.h new file mode 100644 index 0000000000..fe43923f9d --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__format/range_format.h @@ -0,0 +1,71 @@ +// -*- 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___FORMAT_RANGE_FORMAT_H +#define _LIBCPP___FORMAT_RANGE_FORMAT_H + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#include <__concepts/same_as.h> +#include <__config> +#include <__format/fmt_pair_like.h> +#include <__ranges/concepts.h> +#include <__type_traits/remove_cvref.h> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_DIAGNOSTIC_PUSH +_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wshadow") +_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshadow") +// This shadows map, set, and string. +enum class range_format { disabled, map, set, sequence, string, debug_string }; +_LIBCPP_DIAGNOSTIC_POP + +template +constexpr range_format format_kind = [] { + // [format.range.fmtkind]/1 + // A program that instantiates the primary template of format_kind is ill-formed. + static_assert(sizeof(_Rp) != sizeof(_Rp), "create a template specialization of format_kind for your type"); + return range_format::disabled; +}(); + +template + requires same_as<_Rp, remove_cvref_t<_Rp>> +inline constexpr range_format format_kind<_Rp> = [] { + // [format.range.fmtkind]/2 + + // 2.1 If same_as>, R> is true, + // Otherwise format_kind is range_format::disabled. + if constexpr (same_as>, _Rp>) + return range_format::disabled; + // 2.2 Otherwise, if the qualified-id R::key_type is valid and denotes a type: + else if constexpr (requires { typename _Rp::key_type; }) { + // 2.2.1 If the qualified-id R::mapped_type is valid and denotes a type ... + if constexpr (requires { typename _Rp::mapped_type; } && + // 2.2.1 ... If either U is a specialization of pair or U is a specialization + // of tuple and tuple_size_v == 2 + __fmt_pair_like>>) + return range_format::map; + else + // 2.2.2 Otherwise format_kind is range_format::set. + return range_format::set; + } else + // 2.3 Otherwise, format_kind is range_format::sequence. + return range_format::sequence; +}(); + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +#endif diff --git a/naiveproxy/src/third_party/libc++/src/include/__format/range_formatter.h b/naiveproxy/src/third_party/libc++/src/include/__format/range_formatter.h index 0d7fe9970c..06d2b4cb4b 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__format/range_formatter.h +++ b/naiveproxy/src/third_party/libc++/src/include/__format/range_formatter.h @@ -20,6 +20,7 @@ #include <__config> #include <__format/buffer.h> #include <__format/concepts.h> +#include <__format/fmt_pair_like.h> #include <__format/format_context.h> #include <__format/format_error.h> #include <__format/formatter.h> 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 596cce03cd..def9e4c4ec 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__functional/bind.h +++ b/naiveproxy/src/third_party/libc++/src/include/__functional/bind.h @@ -83,15 +83,14 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& __mu(reference_w template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __invoke_result_t<_Ti&, _Uj...> -__mu_expand(_Ti& __ti, tuple<_Uj...>& __uj, __tuple_indices<_Indx...>) { +__mu_expand(_Ti& __ti, tuple<_Uj...>& __uj, __index_sequence<_Indx...>) { return __ti(std::forward<_Uj>(std::get<_Indx>(__uj))...); } template ::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __invoke_result_t<_Ti&, _Uj...> __mu(_Ti& __ti, tuple<_Uj...>& __uj) { - typedef typename __make_tuple_indices::type __indices; - return std::__mu_expand(__ti, __uj, __indices()); + return std::__mu_expand(__ti, __uj, __make_index_sequence()); } template @@ -191,7 +190,7 @@ struct __bind_return<_Fp, const tuple<_BoundArgs...>, _TupleUj, true> { template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __bind_return<_Fp, _BoundArgs, _Args>::type -__apply_functor(_Fp& __f, _BoundArgs& __bound_args, __tuple_indices<_Indx...>, _Args&& __args) { +__apply_functor(_Fp& __f, _BoundArgs& __bound_args, __index_sequence<_Indx...>, _Args&& __args) { return std::__invoke(__f, std::__mu(std::get<_Indx>(__bound_args), __args)...); } @@ -205,8 +204,6 @@ private: _Fd __f_; _Td __bound_args_; - typedef typename __make_tuple_indices::type __indices; - public: template < class _Gp, @@ -219,14 +216,22 @@ public: template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type operator()(_Args&&... __args) { - return std::__apply_functor(__f_, __bound_args_, __indices(), tuple<_Args&&...>(std::forward<_Args>(__args)...)); + return std::__apply_functor( + __f_, + __bound_args_, + __make_index_sequence(), + tuple<_Args&&...>(std::forward<_Args>(__args)...)); } template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __bind_return >::type operator()(_Args&&... __args) const { - return std::__apply_functor(__f_, __bound_args_, __indices(), tuple<_Args&&...>(std::forward<_Args>(__args)...)); + return std::__apply_functor( + __f_, + __bound_args_, + __make_index_sequence(), + tuple<_Args&&...>(std::forward<_Args>(__args)...)); } }; diff --git a/naiveproxy/src/third_party/libc++/src/include/__functional/boyer_moore_searcher.h b/naiveproxy/src/third_party/libc++/src/include/__functional/boyer_moore_searcher.h index 7889232f4b..6c51c32d2f 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__functional/boyer_moore_searcher.h +++ b/naiveproxy/src/third_party/libc++/src/include/__functional/boyer_moore_searcher.h @@ -17,12 +17,10 @@ #include <__config> #include <__functional/hash.h> #include <__functional/operations.h> -#include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__memory/shared_ptr.h> #include <__type_traits/make_unsigned.h> #include <__utility/pair.h> -#include <__vector/vector.h> #include #include #include @@ -125,8 +123,8 @@ public: template _LIBCPP_HIDE_FROM_ABI pair<_RandomAccessIterator2, _RandomAccessIterator2> operator()(_RandomAccessIterator2 __first, _RandomAccessIterator2 __last) const { - static_assert(__is_same_uncvref::value_type, - typename iterator_traits<_RandomAccessIterator2>::value_type>::value, + static_assert(is_same_v<__remove_cvref_t::value_type>, + __remove_cvref_t::value_type>>, "Corpus and Pattern iterators must point to the same type"); if (__first == __last) return std::make_pair(__last, __last); @@ -196,7 +194,7 @@ private: if (__count == 0) return; - vector __scratch(__count); + auto __scratch = std::make_unique(__count); __compute_bm_prefix(__first, __last, __pred, __scratch); for (size_t __i = 0; __i <= __count; ++__i) @@ -256,8 +254,8 @@ public: template _LIBCPP_HIDE_FROM_ABI pair<_RandomAccessIterator2, _RandomAccessIterator2> operator()(_RandomAccessIterator2 __first, _RandomAccessIterator2 __last) const { - static_assert(__is_same_uncvref::value_type, - typename std::iterator_traits<_RandomAccessIterator2>::value_type>::value, + static_assert(is_same_v<__remove_cvref_t::value_type>, + __remove_cvref_t::value_type>>, "Corpus and Pattern iterators must point to the same type"); if (__first == __last) return std::make_pair(__last, __last); 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 e33c5ab9b8..dc112ebfd0 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__functional/function.h +++ b/naiveproxy/src/third_party/libc++/src/include/__functional/function.h @@ -17,13 +17,7 @@ #include <__functional/binary_function.h> #include <__functional/invoke.h> #include <__functional/unary_function.h> -#include <__iterator/iterator_traits.h> #include <__memory/addressof.h> -#include <__memory/allocator.h> -#include <__memory/allocator_destructor.h> -#include <__memory/allocator_traits.h> -#include <__memory/compressed_pair.h> -#include <__memory/unique_ptr.h> #include <__type_traits/aligned_storage.h> #include <__type_traits/decay.h> #include <__type_traits/is_core_convertible.h> @@ -34,9 +28,7 @@ #include <__type_traits/strip_signature.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <__utility/piecewise_construct.h> #include <__utility/swap.h> -#include <__verbose_abort> #include #include @@ -122,7 +114,7 @@ _LIBCPP_HIDE_FROM_ABI bool __not_null(function<_Fp> const& __f) { return !!__f; } -# if _LIBCPP_HAS_EXTENSION_BLOCKS +# if __has_extension(blocks) template _LIBCPP_HIDE_FROM_ABI bool __not_null(_Rp (^__p)(_Args...)) { return __p; @@ -133,104 +125,6 @@ _LIBCPP_HIDE_FROM_ABI bool __not_null(_Rp (^__p)(_Args...)) { namespace __function { -// __alloc_func holds a functor and an allocator. - -template -class __alloc_func; -template -class __default_alloc_func; - -template -class __alloc_func<_Fp, _Ap, _Rp(_ArgTypes...)> { - _LIBCPP_COMPRESSED_PAIR(_Fp, __func_, _Ap, __alloc_); - -public: - using _Target _LIBCPP_NODEBUG = _Fp; - using _Alloc _LIBCPP_NODEBUG = _Ap; - - _LIBCPP_HIDE_FROM_ABI const _Target& __target() const { return __func_; } - - // WIN32 APIs may define __allocator, so use __get_allocator instead. - _LIBCPP_HIDE_FROM_ABI const _Alloc& __get_allocator() const { return __alloc_; } - - _LIBCPP_HIDE_FROM_ABI explicit __alloc_func(_Target&& __f) : __func_(std::move(__f)), __alloc_() {} - - _LIBCPP_HIDE_FROM_ABI explicit __alloc_func(const _Target& __f, const _Alloc& __a) : __func_(__f), __alloc_(__a) {} - - _LIBCPP_HIDE_FROM_ABI explicit __alloc_func(const _Target& __f, _Alloc&& __a) - : __func_(__f), __alloc_(std::move(__a)) {} - - _LIBCPP_HIDE_FROM_ABI explicit __alloc_func(_Target&& __f, _Alloc&& __a) - : __func_(std::move(__f)), __alloc_(std::move(__a)) {} - - _LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes&&... __arg) { - return std::__invoke_r<_Rp>(__func_, std::forward<_ArgTypes>(__arg)...); - } - - _LIBCPP_HIDE_FROM_ABI __alloc_func* __clone() const { - typedef allocator_traits<_Alloc> __alloc_traits; - typedef __rebind_alloc<__alloc_traits, __alloc_func> _AA; - _AA __a(__alloc_); - typedef __allocator_destructor<_AA> _Dp; - unique_ptr<__alloc_func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); - ::new ((void*)__hold.get()) __alloc_func(__func_, _Alloc(__a)); - return __hold.release(); - } - - _LIBCPP_HIDE_FROM_ABI void destroy() _NOEXCEPT { - __func_.~_Fp(); - __alloc_.~_Alloc(); - } - - _LIBCPP_HIDE_FROM_ABI static void __destroy_and_delete(__alloc_func* __f) { - typedef allocator_traits<_Alloc> __alloc_traits; - typedef __rebind_alloc<__alloc_traits, __alloc_func> _FunAlloc; - _FunAlloc __a(__f->__get_allocator()); - __f->destroy(); - __a.deallocate(__f, 1); - } -}; - -template -struct __deallocating_deleter { - _LIBCPP_HIDE_FROM_ABI void operator()(void* __p) const { - std::__libcpp_deallocate<_Tp>(static_cast<_Tp*>(__p), __element_count(1)); - } -}; - -template -class __default_alloc_func<_Fp, _Rp(_ArgTypes...)> { - _Fp __f_; - -public: - using _Target _LIBCPP_NODEBUG = _Fp; - - _LIBCPP_HIDE_FROM_ABI const _Target& __target() const { return __f_; } - - _LIBCPP_HIDE_FROM_ABI explicit __default_alloc_func(_Target&& __f) : __f_(std::move(__f)) {} - - _LIBCPP_HIDE_FROM_ABI explicit __default_alloc_func(const _Target& __f) : __f_(__f) {} - - _LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes&&... __arg) { - return std::__invoke_r<_Rp>(__f_, std::forward<_ArgTypes>(__arg)...); - } - - _LIBCPP_HIDE_FROM_ABI __default_alloc_func* __clone() const { - using _Self = __default_alloc_func; - unique_ptr<_Self, __deallocating_deleter<_Self>> __hold(std::__libcpp_allocate<_Self>(__element_count(1))); - _Self* __res = ::new ((void*)__hold.get()) _Self(__f_); - (void)__hold.release(); - return __res; - } - - _LIBCPP_HIDE_FROM_ABI void destroy() _NOEXCEPT { __f_.~_Target(); } - - _LIBCPP_HIDE_FROM_ABI static void __destroy_and_delete(__default_alloc_func* __f) { - __f->destroy(); - std::__libcpp_deallocate<__default_alloc_func>(__f, __element_count(1)); - } -}; - // __base provides an abstract interface for copyable functors. template @@ -257,84 +151,38 @@ public: // __func implements __base for a given functor type. -template +template class __func; -template -class __func<_Fp, _Alloc, _Rp(_ArgTypes...)> : public __base<_Rp(_ArgTypes...)> { - __alloc_func<_Fp, _Alloc, _Rp(_ArgTypes...)> __f_; +template +class __func<_Fp, _Rp(_ArgTypes...)> : public __base<_Rp(_ArgTypes...)> { + _Fp __func_; public: - _LIBCPP_HIDE_FROM_ABI explicit __func(_Fp&& __f) : __f_(std::move(__f)) {} + _LIBCPP_HIDE_FROM_ABI explicit __func(_Fp&& __f) : __func_(std::move(__f)) {} + _LIBCPP_HIDE_FROM_ABI explicit __func(const _Fp& __f) : __func_(__f) {} - _LIBCPP_HIDE_FROM_ABI explicit __func(const _Fp& __f, const _Alloc& __a) : __f_(__f, __a) {} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL __base<_Rp(_ArgTypes...)>* __clone() const override { return new __func(__func_); } - _LIBCPP_HIDE_FROM_ABI explicit __func(const _Fp& __f, _Alloc&& __a) : __f_(__f, std::move(__a)) {} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __clone(__base<_Rp(_ArgTypes...)>* __p) const override { + ::new ((void*)__p) __func(__func_); + } - _LIBCPP_HIDE_FROM_ABI explicit __func(_Fp&& __f, _Alloc&& __a) : __f_(std::move(__f), std::move(__a)) {} - - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual __base<_Rp(_ArgTypes...)>* __clone() const; - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __clone(__base<_Rp(_ArgTypes...)>*) const; - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy() _NOEXCEPT; - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy_deallocate() _NOEXCEPT; - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual _Rp operator()(_ArgTypes&&... __arg); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void destroy() _NOEXCEPT override { __func_.~_Fp(); } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void destroy_deallocate() _NOEXCEPT override { delete this; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL _Rp operator()(_ArgTypes&&... __arg) override { + return std::__invoke_r<_Rp>(__func_, std::forward<_ArgTypes>(__arg)...); + } # if _LIBCPP_HAS_RTTI - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual const void* target(const type_info&) const _NOEXCEPT; - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual const std::type_info& target_type() const _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const void* target(const type_info& __ti) const _NOEXCEPT override { + if (__ti == typeid(_Fp)) + return std::addressof(__func_); + return nullptr; + } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const std::type_info& target_type() const _NOEXCEPT override { return typeid(_Fp); } # endif // _LIBCPP_HAS_RTTI }; -template -__base<_Rp(_ArgTypes...)>* __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__clone() const { - typedef allocator_traits<_Alloc> __alloc_traits; - typedef __rebind_alloc<__alloc_traits, __func> _Ap; - _Ap __a(__f_.__get_allocator()); - typedef __allocator_destructor<_Ap> _Dp; - unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); - ::new ((void*)__hold.get()) __func(__f_.__target(), _Alloc(__a)); - return __hold.release(); -} - -template -void __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__clone(__base<_Rp(_ArgTypes...)>* __p) const { - ::new ((void*)__p) __func(__f_.__target(), __f_.__get_allocator()); -} - -template -void __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy() _NOEXCEPT { - __f_.destroy(); -} - -template -void __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy_deallocate() _NOEXCEPT { - typedef allocator_traits<_Alloc> __alloc_traits; - typedef __rebind_alloc<__alloc_traits, __func> _Ap; - _Ap __a(__f_.__get_allocator()); - __f_.destroy(); - __a.deallocate(this, 1); -} - -template -_Rp __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::operator()(_ArgTypes&&... __arg) { - return __f_(std::forward<_ArgTypes>(__arg)...); -} - -# if _LIBCPP_HAS_RTTI - -template -const void* __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target(const type_info& __ti) const _NOEXCEPT { - if (__ti == typeid(_Fp)) - return std::addressof(__f_.__target()); - return nullptr; -} - -template -const std::type_info& __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target_type() const _NOEXCEPT { - return typeid(_Fp); -} - -# endif // _LIBCPP_HAS_RTTI - // __value_func creates a value-type from a __func. template @@ -354,29 +202,19 @@ class __value_func<_Rp(_ArgTypes...)> { public: _LIBCPP_HIDE_FROM_ABI __value_func() _NOEXCEPT : __f_(nullptr) {} - template - _LIBCPP_HIDE_FROM_ABI __value_func(_Fp&& __f, const _Alloc& __a) : __f_(nullptr) { - typedef allocator_traits<_Alloc> __alloc_traits; - typedef __function::__func<_Fp, _Alloc, _Rp(_ArgTypes...)> _Fun; - typedef __rebind_alloc<__alloc_traits, _Fun> _FunAlloc; + template , __value_func>::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI explicit __value_func(_Fp&& __f) : __f_(nullptr) { + typedef __function::__func<_Fp, _Rp(_ArgTypes...)> _Fun; if (__function::__not_null(__f)) { - _FunAlloc __af(__a); - if (sizeof(_Fun) <= sizeof(__buf_) && is_nothrow_copy_constructible<_Fp>::value && - is_nothrow_copy_constructible<_FunAlloc>::value) { - __f_ = ::new ((void*)&__buf_) _Fun(std::move(__f), _Alloc(__af)); + if (sizeof(_Fun) <= sizeof(__buf_) && is_nothrow_copy_constructible<_Fp>::value) { + __f_ = ::new (std::addressof(__buf_)) _Fun(std::move(__f)); } else { - typedef __allocator_destructor<_FunAlloc> _Dp; - unique_ptr<__func, _Dp> __hold(__af.allocate(1), _Dp(__af, 1)); - ::new ((void*)__hold.get()) _Fun(std::move(__f), _Alloc(__a)); - __f_ = __hold.release(); + __f_ = new _Fun(std::move(__f)); } } } - template , __value_func>::value, int> = 0> - _LIBCPP_HIDE_FROM_ABI explicit __value_func(_Fp&& __f) : __value_func(std::forward<_Fp>(__f), allocator<_Fp>()) {} - _LIBCPP_HIDE_FROM_ABI __value_func(const __value_func& __f) { if (__f.__f_ == nullptr) __f_ = nullptr; @@ -539,12 +377,12 @@ private: template _LIBCPP_HIDE_FROM_ABI static void* __large_clone(const void* __s) { const _Fun* __f = static_cast(__s); - return __f->__clone(); + return new _Fun(*__f); } template _LIBCPP_HIDE_FROM_ABI static void __large_destroy(void* __s) { - _Fun::__destroy_and_delete(static_cast<_Fun*>(__s)); + delete static_cast<_Fun*>(__s); } template @@ -554,7 +392,7 @@ private: std::addressof(__large_destroy<_Fun>), false, # if _LIBCPP_HAS_RTTI - &typeid(typename _Fun::_Target) + &typeid(_Fun) # else nullptr # endif @@ -569,7 +407,7 @@ private: nullptr, false, # if _LIBCPP_HAS_RTTI - &typeid(typename _Fun::_Target) + &typeid(_Fun) # else nullptr # endif @@ -583,42 +421,7 @@ private: template using __fast_forward _LIBCPP_NODEBUG = __conditional_t::value, _Tp, _Tp&&>; -// __policy_invoker calls an instance of __alloc_func held in __policy_storage. - -template -struct __policy_invoker; - -template -struct __policy_invoker<_Rp(_ArgTypes...)> { - typedef _Rp (*__Call)(const __policy_storage*, __fast_forward<_ArgTypes>...); - - __Call __call_; - - // Creates an invoker that throws bad_function_call. - _LIBCPP_HIDE_FROM_ABI __policy_invoker() : __call_(&__call_empty) {} - - // Creates an invoker that calls the given instance of __func. - template - _LIBCPP_HIDE_FROM_ABI static __policy_invoker __create() { - return __policy_invoker(std::addressof(__call_impl<_Fun>)); - } - -private: - _LIBCPP_HIDE_FROM_ABI explicit __policy_invoker(__Call __c) : __call_(__c) {} - - _LIBCPP_HIDE_FROM_ABI static _Rp __call_empty(const __policy_storage*, __fast_forward<_ArgTypes>...) { - std::__throw_bad_function_call(); - } - - template - _LIBCPP_HIDE_FROM_ABI static _Rp __call_impl(const __policy_storage* __buf, __fast_forward<_ArgTypes>... __args) { - _Fun* __f = reinterpret_cast<_Fun*>(__use_small_storage<_Fun>::value ? &__buf->__small : __buf->__large); - return (*__f)(std::forward<_ArgTypes>(__args)...); - } -}; - -// __policy_func uses a __policy and __policy_invoker to create a type-erased, -// copyable functor. +// __policy_func uses a __policy to create a type-erased, copyable functor. template class __policy_func; @@ -628,69 +431,52 @@ class __policy_func<_Rp(_ArgTypes...)> { // Inline storage for small objects. __policy_storage __buf_; - // Calls the value stored in __buf_. This could technically be part of - // policy, but storing it here eliminates a level of indirection inside - // operator(). - typedef __function::__policy_invoker<_Rp(_ArgTypes...)> __invoker; - __invoker __invoker_; + using _ErasedFunc _LIBCPP_NODEBUG = _Rp(const __policy_storage*, __fast_forward<_ArgTypes>...); + + _ErasedFunc* __func_; // The policy that describes how to move / copy / destroy __buf_. Never // null, even if the function is empty. const __policy* __policy_; -public: - _LIBCPP_HIDE_FROM_ABI __policy_func() : __policy_(__policy::__create_empty()) {} - - template - _LIBCPP_HIDE_FROM_ABI __policy_func(_Fp&& __f, const _Alloc& __a) : __policy_(__policy::__create_empty()) { - typedef __alloc_func<_Fp, _Alloc, _Rp(_ArgTypes...)> _Fun; - typedef allocator_traits<_Alloc> __alloc_traits; - typedef __rebind_alloc<__alloc_traits, _Fun> _FunAlloc; - - if (__function::__not_null(__f)) { - __invoker_ = __invoker::template __create<_Fun>(); - __policy_ = __policy::__create<_Fun>(); - - _FunAlloc __af(__a); - if (__use_small_storage<_Fun>()) { - ::new ((void*)&__buf_.__small) _Fun(std::move(__f), _Alloc(__af)); - } else { - typedef __allocator_destructor<_FunAlloc> _Dp; - unique_ptr<_Fun, _Dp> __hold(__af.allocate(1), _Dp(__af, 1)); - ::new ((void*)__hold.get()) _Fun(std::move(__f), _Alloc(__af)); - __buf_.__large = __hold.release(); - } - } + _LIBCPP_HIDE_FROM_ABI static _Rp __empty_func(const __policy_storage*, __fast_forward<_ArgTypes>...) { + std::__throw_bad_function_call(); } + template + _LIBCPP_HIDE_FROM_ABI static _Rp __call_func(const __policy_storage* __buf, __fast_forward<_ArgTypes>... __args) { + _Fun* __func = reinterpret_cast<_Fun*>(__use_small_storage<_Fun>::value ? &__buf->__small : __buf->__large); + + return std::__invoke_r<_Rp>(*__func, std::forward<_ArgTypes>(__args)...); + } + +public: + _LIBCPP_HIDE_FROM_ABI __policy_func() : __func_(__empty_func), __policy_(__policy::__create_empty()) {} + template , __policy_func>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI explicit __policy_func(_Fp&& __f) : __policy_(__policy::__create_empty()) { - typedef __default_alloc_func<_Fp, _Rp(_ArgTypes...)> _Fun; - if (__function::__not_null(__f)) { - __invoker_ = __invoker::template __create<_Fun>(); - __policy_ = __policy::__create<_Fun>(); - if (__use_small_storage<_Fun>()) { - ::new ((void*)&__buf_.__small) _Fun(std::move(__f)); + __func_ = __call_func<_Fp>; + __policy_ = __policy::__create<_Fp>(); + if (__use_small_storage<_Fp>()) { + ::new ((void*)&__buf_.__small) _Fp(std::move(__f)); } else { - unique_ptr<_Fun, __deallocating_deleter<_Fun>> __hold(std::__libcpp_allocate<_Fun>(__element_count(1))); - __buf_.__large = ::new ((void*)__hold.get()) _Fun(std::move(__f)); - (void)__hold.release(); + __buf_.__large = ::new _Fp(std::move(__f)); } } } _LIBCPP_HIDE_FROM_ABI __policy_func(const __policy_func& __f) - : __buf_(__f.__buf_), __invoker_(__f.__invoker_), __policy_(__f.__policy_) { + : __buf_(__f.__buf_), __func_(__f.__func_), __policy_(__f.__policy_) { if (__policy_->__clone) __buf_.__large = __policy_->__clone(__f.__buf_.__large); } _LIBCPP_HIDE_FROM_ABI __policy_func(__policy_func&& __f) - : __buf_(__f.__buf_), __invoker_(__f.__invoker_), __policy_(__f.__policy_) { + : __buf_(__f.__buf_), __func_(__f.__func_), __policy_(__f.__policy_) { if (__policy_->__destroy) { - __f.__policy_ = __policy::__create_empty(); - __f.__invoker_ = __invoker(); + __f.__policy_ = __policy::__create_empty(); + __f.__func_ = {}; } } @@ -700,30 +486,30 @@ public: } _LIBCPP_HIDE_FROM_ABI __policy_func& operator=(__policy_func&& __f) { - *this = nullptr; - __buf_ = __f.__buf_; - __invoker_ = __f.__invoker_; - __policy_ = __f.__policy_; - __f.__policy_ = __policy::__create_empty(); - __f.__invoker_ = __invoker(); + *this = nullptr; + __buf_ = __f.__buf_; + __func_ = __f.__func_; + __policy_ = __f.__policy_; + __f.__policy_ = __policy::__create_empty(); + __f.__func_ = {}; return *this; } _LIBCPP_HIDE_FROM_ABI __policy_func& operator=(nullptr_t) { const __policy* __p = __policy_; __policy_ = __policy::__create_empty(); - __invoker_ = __invoker(); + __func_ = {}; if (__p->__destroy) __p->__destroy(__buf_.__large); return *this; } _LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes&&... __args) const { - return __invoker_.__call_(std::addressof(__buf_), std::forward<_ArgTypes>(__args)...); + return __func_(std::addressof(__buf_), std::forward<_ArgTypes>(__args)...); } _LIBCPP_HIDE_FROM_ABI void swap(__policy_func& __f) { - std::swap(__invoker_, __f.__invoker_); + std::swap(__func_, __f.__func_); std::swap(__policy_, __f.__policy_); std::swap(__buf_, __f.__buf_); } @@ -750,14 +536,14 @@ public: extern "C" void* _Block_copy(const void*); extern "C" void _Block_release(const void*); -template -class __func<_Rp1 (^)(_ArgTypes1...), _Alloc, _Rp(_ArgTypes...)> : public __base<_Rp(_ArgTypes...)> { +template +class __func<_Rp1 (^)(_ArgTypes1...), _Rp(_ArgTypes...)> : public __base<_Rp(_ArgTypes...)> { typedef _Rp1 (^__block_type)(_ArgTypes1...); __block_type __f_; public: _LIBCPP_HIDE_FROM_ABI explicit __func(__block_type const& __f) -# if _LIBCPP_HAS_OBJC_ARC +# if __has_feature(objc_arc) : __f_(__f) # else : __f_(reinterpret_cast<__block_type>(__f ? _Block_copy(__f) : nullptr)) @@ -767,15 +553,6 @@ public: // [TODO] add && to save on a retain - _LIBCPP_HIDE_FROM_ABI explicit __func(__block_type __f, const _Alloc& /* unused */) -# if _LIBCPP_HAS_OBJC_ARC - : __f_(__f) -# else - : __f_(reinterpret_cast<__block_type>(__f ? _Block_copy(__f) : nullptr)) -# endif - { - } - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual __base<_Rp(_ArgTypes...)>* __clone() const { _LIBCPP_ASSERT_INTERNAL( false, @@ -790,7 +567,7 @@ public: } _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy() _NOEXCEPT { -# if !_LIBCPP_HAS_OBJC_ARC +# if !__has_feature(objc_arc) if (__f_) _Block_release(__f_); # endif @@ -822,7 +599,7 @@ public: # endif // _LIBCPP_HAS_RTTI }; -# endif // _LIBCPP_HAS_EXTENSION_BLOCKS +# endif // _LIBCPP_HAS_BLOCKS_RUNTIME } // namespace __function @@ -954,7 +731,7 @@ function<_Rp(_ArgTypes...)>::function(_Fp __f) : __f_(std::move(__f)) {} # if _LIBCPP_STD_VER <= 14 template template -function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc& __a, _Fp __f) : __f_(std::move(__f), __a) {} +function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc&, _Fp __f) : __f_(std::move(__f)) {} # endif template diff --git a/naiveproxy/src/third_party/libc++/src/include/__functional/hash.h b/naiveproxy/src/third_party/libc++/src/include/__functional/hash.h index f9f7d2c767..489a6f00b8 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__functional/hash.h +++ b/naiveproxy/src/third_party/libc++/src/include/__functional/hash.h @@ -19,6 +19,8 @@ #include <__type_traits/invoke.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_enum.h> +#include <__type_traits/is_floating_point.h> +#include <__type_traits/is_integral.h> #include <__type_traits/underlying_type.h> #include <__utility/pair.h> #include <__utility/swap.h> @@ -345,122 +347,43 @@ struct hash<_Tp*> : public __unary_function<_Tp*, size_t> { } }; -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(bool __v) const _NOEXCEPT { return static_cast(__v); } +template +struct __hash_impl { + __hash_impl() = delete; + __hash_impl(__hash_impl const&) = delete; + __hash_impl& operator=(__hash_impl const&) = delete; }; -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(char __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(signed char __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned char __v) const _NOEXCEPT { return static_cast(__v); } -}; - -#if _LIBCPP_HAS_CHAR8_T -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(char8_t __v) const _NOEXCEPT { return static_cast(__v); } -}; -#endif // _LIBCPP_HAS_CHAR8_T - -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(char16_t __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(char32_t __v) const _NOEXCEPT { return static_cast(__v); } -}; - -#if _LIBCPP_HAS_WIDE_CHARACTERS -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(wchar_t __v) const _NOEXCEPT { return static_cast(__v); } -}; -#endif // _LIBCPP_HAS_WIDE_CHARACTERS - -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(short __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned short __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(int __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned int __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(long __v) const _NOEXCEPT { return static_cast(__v); } -}; - -template <> -struct hash : public __unary_function { - _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned long __v) const _NOEXCEPT { - static_assert(sizeof(size_t) >= sizeof(unsigned long), - "This would be a terrible hash function on a platform where size_t is smaller than unsigned long"); - return static_cast(__v); +template +struct __hash_impl<_Tp, __enable_if_t::value> > : __unary_function<_Tp, size_t> { + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { + using type = __underlying_type_t<_Tp>; + return hash()(static_cast(__v)); } }; -template <> -struct hash : public __scalar_hash {}; +template +struct __hash_impl<_Tp, __enable_if_t::value && (sizeof(_Tp) <= sizeof(size_t))> > + : __unary_function<_Tp, size_t> { + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { return static_cast(__v); } +}; -template <> -struct hash : public __scalar_hash {}; +template +struct __hash_impl<_Tp, __enable_if_t::value && (sizeof(_Tp) > sizeof(size_t))> > + : __scalar_hash<_Tp> {}; -#if _LIBCPP_HAS_INT128 - -template <> -struct hash<__int128_t> : public __scalar_hash<__int128_t> {}; - -template <> -struct hash<__uint128_t> : public __scalar_hash<__uint128_t> {}; - -#endif - -template <> -struct hash : public __scalar_hash { - _LIBCPP_HIDE_FROM_ABI size_t operator()(float __v) const _NOEXCEPT { +template +struct __hash_impl<_Tp, __enable_if_t::value> > : __scalar_hash<_Tp> { + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { // -0.0 and 0.0 should return same hash if (__v == 0.0f) return 0; - return __scalar_hash::operator()(__v); + return __scalar_hash<_Tp>::operator()(__v); } }; template <> -struct hash : public __scalar_hash { - _LIBCPP_HIDE_FROM_ABI size_t operator()(double __v) const _NOEXCEPT { - // -0.0 and 0.0 should return same hash - if (__v == 0.0) - return 0; - return __scalar_hash::operator()(__v); - } -}; - -template <> -struct hash : public __scalar_hash { +struct __hash_impl : __scalar_hash { _LIBCPP_HIDE_FROM_ABI size_t operator()(long double __v) const _NOEXCEPT { // -0.0 and 0.0 should return same hash if (__v == 0.0L) @@ -501,22 +424,8 @@ struct hash : public __scalar_hash { } }; -template ::value> -struct __enum_hash : public __unary_function<_Tp, size_t> { - _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { - using type = __underlying_type_t<_Tp>; - return hash()(static_cast(__v)); - } -}; template -struct __enum_hash<_Tp, false> { - __enum_hash() = delete; - __enum_hash(__enum_hash const&) = delete; - __enum_hash& operator=(__enum_hash const&) = delete; -}; - -template -struct hash : public __enum_hash<_Tp> {}; +struct hash : public __hash_impl<_Tp> {}; #if _LIBCPP_STD_VER >= 17 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 b409ad7511..148703b21d 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 @@ -11,14 +11,18 @@ #define _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H #include <__compare/synth_three_way.h> -#include <__concepts/boolean_testable.h> +#include <__concepts/convertible_to.h> #include <__config> #include <__functional/weak_result_type.h> #include <__memory/addressof.h> +#include <__type_traits/common_reference.h> #include <__type_traits/desugars_to.h> #include <__type_traits/enable_if.h> #include <__type_traits/invoke.h> #include <__type_traits/is_const.h> +#include <__type_traits/is_core_convertible.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_specialization.h> #include <__type_traits/remove_cvref.h> #include <__type_traits/void_t.h> #include <__utility/declval.h> @@ -45,7 +49,7 @@ private: public: template ()))>, - __enable_if_t::value, int> = 0> + __enable_if_t, reference_wrapper>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper(_Up&& __u) _NOEXCEPT_(noexcept(__fun(std::declval<_Up>()))) { type& __f = static_cast<_Up&&>(__u); @@ -75,7 +79,7 @@ public: _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(reference_wrapper __x, reference_wrapper __y) requires requires { - { __x.get() == __y.get() } -> __boolean_testable; + { __x.get() == __y.get() } -> __core_convertible_to; } { return __x.get() == __y.get(); @@ -83,7 +87,7 @@ public: _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(reference_wrapper __x, const _Tp& __y) requires requires { - { __x.get() == __y } -> __boolean_testable; + { __x.get() == __y } -> __core_convertible_to; } { return __x.get() == __y; @@ -91,7 +95,7 @@ public: _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; + { __x.get() == __y.get() } -> __core_convertible_to; } { return __x.get() == __y.get(); @@ -155,6 +159,32 @@ template inline const bool __desugars_to_v<_CanonicalTag, reference_wrapper<_Operation>, _Args...> = __desugars_to_v<_CanonicalTag, _Operation, _Args...>; +#if _LIBCPP_STD_VER >= 20 + +template +inline constexpr bool __is_ref_wrapper = __is_specialization_v<_Tp, reference_wrapper>; + +template +concept __ref_wrap_common_reference_exists_with = __is_ref_wrapper<_Rp> && requires { + typename common_reference_t; +} && convertible_to<_RpQual, common_reference_t>; + +template class _RpQual, template class _TpQual> + requires(__ref_wrap_common_reference_exists_with<_Rp, _Tp, _RpQual<_Rp>, _TpQual<_Tp>> && + !__ref_wrap_common_reference_exists_with<_Tp, _Rp, _TpQual<_Tp>, _RpQual<_Rp>>) +struct basic_common_reference<_Rp, _Tp, _RpQual, _TpQual> { + using type _LIBCPP_NODEBUG = common_reference_t>; +}; + +template class _TpQual, template class _RpQual> + requires(__ref_wrap_common_reference_exists_with<_Rp, _Tp, _RpQual<_Rp>, _TpQual<_Tp>> && + !__ref_wrap_common_reference_exists_with<_Tp, _Rp, _TpQual<_Tp>, _RpQual<_Rp>>) +struct basic_common_reference<_Tp, _Rp, _TpQual, _RpQual> { + using type _LIBCPP_NODEBUG = common_reference_t>; +}; + +#endif // _LIBCPP_STD_VER >= 20 + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__hash_table b/naiveproxy/src/third_party/libc++/src/include/__hash_table index aefa8e19c1..dacc152030 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__hash_table +++ b/naiveproxy/src/third_party/libc++/src/include/__hash_table @@ -29,6 +29,7 @@ #include <__memory/unique_ptr.h> #include <__new/launder.h> #include <__type_traits/can_extract_key.h> +#include <__type_traits/copy_cvref.h> #include <__type_traits/enable_if.h> #include <__type_traits/invoke.h> #include <__type_traits/is_const.h> @@ -108,9 +109,35 @@ struct __hash_node_base { _LIBCPP_HIDE_FROM_ABI explicit __hash_node_base(__next_pointer __next) _NOEXCEPT : __next_(__next) {} }; +template +struct __get_hash_node_value_type { + using type _LIBCPP_NODEBUG = _Tp; +}; + +template +struct __get_hash_node_value_type<__hash_value_type<_Key, _Tp> > { + using type _LIBCPP_NODEBUG = pair; +}; + +template +using __get_hash_node_value_type_t _LIBCPP_NODEBUG = typename __get_hash_node_value_type<_Tp>::type; + +template +struct __get_hash_node_key_type { + using type _LIBCPP_NODEBUG = _Tp; +}; + +template +struct __get_hash_node_key_type<__hash_value_type<_Key, _Tp> > { + using type _LIBCPP_NODEBUG = _Key; +}; + +template +using __get_hash_node_key_type_t _LIBCPP_NODEBUG = typename __get_hash_node_key_type<_Tp>::type; + template struct __hash_node : public __hash_node_base< __rebind_pointer_t<_VoidPtr, __hash_node<_Tp, _VoidPtr> > > { - typedef _Tp __node_value_type; + using __node_value_type _LIBCPP_NODEBUG = __get_hash_node_value_type_t<_Tp>; using _Base _LIBCPP_NODEBUG = __hash_node_base<__rebind_pointer_t<_VoidPtr, __hash_node<_Tp, _VoidPtr> > >; using __next_pointer _LIBCPP_NODEBUG = typename _Base::__next_pointer; @@ -122,18 +149,20 @@ struct __hash_node : public __hash_node_base< __rebind_pointer_t<_VoidPtr, __has private: union { - _Tp __value_; + __node_value_type __value_; }; public: - _LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return __value_; } + _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return __value_; } #else private: - _ALIGNAS_TYPE(_Tp) char __buffer_[sizeof(_Tp)]; + _ALIGNAS_TYPE(__node_value_type) char __buffer_[sizeof(__node_value_type)]; public: - _LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return *std::__launder(reinterpret_cast<_Tp*>(&__buffer_)); } + _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { + return *std::__launder(reinterpret_cast<__node_value_type*>(&__buffer_)); + } #endif _LIBCPP_HIDE_FROM_ABI explicit __hash_node(__next_pointer __next, size_t __hash) : _Base(__next), __hash_(__hash) {} @@ -166,69 +195,11 @@ class __hash_map_iterator; template class __hash_map_const_iterator; -template -struct __hash_key_value_types { - static_assert(!is_reference<_Tp>::value && !is_const<_Tp>::value, ""); - typedef _Tp key_type; - typedef _Tp __node_value_type; - typedef _Tp __container_value_type; - static const bool __is_map = false; - - _LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(_Tp const& __v) { return __v; } - _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(__node_value_type const& __v) { return __v; } - _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) { return std::addressof(__n); } - _LIBCPP_HIDE_FROM_ABI static __container_value_type&& __move(__node_value_type& __v) { return std::move(__v); } -}; - -template -struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > { - typedef _Key key_type; - typedef _Tp mapped_type; - typedef __hash_value_type<_Key, _Tp> __node_value_type; - typedef pair __container_value_type; - typedef __container_value_type __map_value_type; - static const bool __is_map = true; - - _LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(__container_value_type const& __v) { return __v.first; } - - template ::value, int> = 0> - _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(_Up& __t) { - return __t.__get_value(); - } - - template ::value, int> = 0> - _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(_Up& __t) { - return __t; - } - - _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) { - return std::addressof(__n.__get_value()); - } - _LIBCPP_HIDE_FROM_ABI static pair __move(__node_value_type& __v) { return __v.__move(); } -}; - -template , bool = _KVTypes::__is_map> -struct __hash_map_pointer_types {}; - -template -struct __hash_map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> { - typedef typename _KVTypes::__map_value_type _Mv; - typedef __rebind_pointer_t<_AllocPtr, _Mv> __map_value_type_pointer; - typedef __rebind_pointer_t<_AllocPtr, const _Mv> __const_map_value_type_pointer; -}; - template ::element_type> struct __hash_node_types; template -struct __hash_node_types<_NodePtr, __hash_node<_Tp, _VoidPtr> > - : public __hash_key_value_types<_Tp>, - __hash_map_pointer_types<_Tp, _VoidPtr> - -{ - typedef __hash_key_value_types<_Tp> __base; - -public: +struct __hash_node_types<_NodePtr, __hash_node<_Tp, _VoidPtr> > { typedef ptrdiff_t difference_type; typedef size_t size_type; @@ -242,7 +213,7 @@ public: typedef typename __node_base_type::__next_pointer __next_pointer; - typedef _Tp __node_value_type; + using __node_value_type _LIBCPP_NODEBUG = __get_hash_node_value_type_t<_Tp>; typedef __rebind_pointer_t<_VoidPtr, __node_value_type> __node_value_type_pointer; typedef __rebind_pointer_t<_VoidPtr, const __node_value_type> __const_node_value_type_pointer; @@ -601,8 +572,6 @@ public: typedef typename __alloc_traits::pointer pointer; private: - typedef __hash_node_types _NodeTypes; - allocator_type& __na_; public: @@ -617,7 +586,7 @@ public: _LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT { if (__value_constructed) { - __alloc_traits::destroy(__na_, _NodeTypes::__get_ptr(__p->__get_value())); + __alloc_traits::destroy(__na_, std::addressof(__p->__get_value())); std::__destroy_at(std::addressof(*__p)); } if (__p) @@ -667,19 +636,19 @@ int __diagnose_unordered_container_requirements(void*); template class __hash_table { public: - typedef _Tp value_type; + using value_type = __get_hash_node_value_type_t<_Tp>; + using key_type = __get_hash_node_key_type_t<_Tp>; + typedef _Hash hasher; typedef _Equal key_equal; typedef _Alloc allocator_type; private: typedef allocator_traits __alloc_traits; - typedef typename __make_hash_node_types::type _NodeTypes; + typedef typename __make_hash_node_types<_Tp, typename __alloc_traits::void_pointer>::type _NodeTypes; public: typedef typename _NodeTypes::__node_value_type __node_value_type; - typedef typename _NodeTypes::__container_value_type __container_value_type; - typedef typename _NodeTypes::key_type key_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename __alloc_traits::pointer pointer; @@ -808,7 +777,7 @@ public: template ::value, int> = 0> + __enable_if_t<__can_extract_map_key<_First, key_type, value_type>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI pair __emplace_unique(_First&& __f, _Second&& __s) { return __emplace_unique_key_args(__f, std::forward<_First>(__f), std::forward<_Second>(__s)); } @@ -836,27 +805,32 @@ public: template _LIBCPP_HIDE_FROM_ABI iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args); - _LIBCPP_HIDE_FROM_ABI pair __insert_unique(__container_value_type&& __x) { - return __emplace_unique_key_args(_NodeTypes::__get_key(__x), std::move(__x)); + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI void __insert_unique_from_orphaned_node(value_type&& __value) { + __node_holder __h = __construct_node(const_cast(__value.first), std::move(__value.second)); + __node_insert_unique(__h.get()); + __h.release(); } - template ::value, int> = 0> - _LIBCPP_HIDE_FROM_ABI pair __insert_unique(_Pp&& __x) { - return __emplace_unique(std::forward<_Pp>(__x)); + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI void __insert_unique_from_orphaned_node(value_type&& __value) { + __node_holder __h = __construct_node(std::move(__value)); + __node_insert_unique(__h.get()); + __h.release(); } - template - _LIBCPP_HIDE_FROM_ABI iterator __insert_multi(_Pp&& __x) { - return __emplace_multi(std::forward<_Pp>(__x)); + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI void __insert_multi_from_orphaned_node(value_type&& __value) { + __node_holder __h = __construct_node(const_cast(__value.first), std::move(__value.second)); + __node_insert_multi(__h.get()); + __h.release(); } - template - _LIBCPP_HIDE_FROM_ABI iterator __insert_multi(const_iterator __p, _Pp&& __x) { - return __emplace_hint_multi(__p, std::forward<_Pp>(__x)); - } - - _LIBCPP_HIDE_FROM_ABI pair __insert_unique(const __container_value_type& __x) { - return __emplace_unique_key_args(_NodeTypes::__get_key(__x), __x); + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI void __insert_multi_from_orphaned_node(value_type&& __value) { + __node_holder __h = __construct_node(std::move(__value)); + __node_insert_multi(__h.get()); + __h.release(); } #if _LIBCPP_STD_VER >= 17 @@ -1020,6 +994,19 @@ private: _LIBCPP_HIDE_FROM_ABI void __deallocate_node(__next_pointer __np) _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI __next_pointer __detach() _NOEXCEPT; + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI void __assign_value(__get_hash_node_value_type_t<_Tp>& __lhs, _From&& __rhs) { + // This is technically UB, since the object was constructed as `const`. + // Clang doesn't optimize on this currently though. + const_cast(__lhs.first) = const_cast<__copy_cvref_t<_From, key_type>&&>(__rhs.first); + __lhs.second = std::forward<_From>(__rhs).second; + } + + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI void __assign_value(_Tp& __lhs, _From&& __rhs) { + __lhs = std::forward<_From>(__rhs); + } + template friend class unordered_map; template @@ -1161,7 +1148,7 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate_node(__next_pointer while (__np != nullptr) { __next_pointer __next = __np->__next_; __node_pointer __real_np = __np->__upcast(); - __node_traits::destroy(__na, _NodeTypes::__get_ptr(__real_np->__get_value())); + __node_traits::destroy(__na, std::addressof(__real_np->__get_value())); std::__destroy_at(std::addressof(*__real_np)); __node_traits::deallocate(__na, __real_np, 1); __np = __next; @@ -1216,8 +1203,8 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(__hash_table& __u, #endif // _LIBCPP_HAS_EXCEPTIONS const_iterator __i = __u.begin(); while (__cache != nullptr && __u.size() != 0) { - __cache->__upcast()->__get_value() = std::move(__u.remove(__i++)->__get_value()); - __next_pointer __next = __cache->__next_; + __assign_value(__cache->__upcast()->__get_value(), std::move(__u.remove(__i++)->__get_value())); + __next_pointer __next = __cache->__next_; __node_insert_multi(__cache->__upcast()); __cache = __next; } @@ -1230,11 +1217,8 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(__hash_table& __u, __deallocate_node(__cache); } const_iterator __i = __u.begin(); - while (__u.size() != 0) { - __node_holder __h = __construct_node(_NodeTypes::__move(__u.remove(__i++)->__get_value())); - __node_insert_multi(__h.get()); - __h.release(); - } + while (__u.size() != 0) + __insert_multi_from_orphaned_node(std::move(__u.remove(__i++)->__get_value())); } } @@ -1253,8 +1237,8 @@ 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, - "__assign_unique may only be called with the containers value type"); + static_assert( + is_same<_ItValueType, value_type>::value, "__assign_unique may only be called with the containers value type"); if (bucket_count() != 0) { __next_pointer __cache = __detach(); @@ -1262,8 +1246,8 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __ try { #endif // _LIBCPP_HAS_EXCEPTIONS for (; __cache != nullptr && __first != __last; ++__first) { - __cache->__upcast()->__get_value() = *__first; - __next_pointer __next = __cache->__next_; + __assign_value(__cache->__upcast()->__get_value(), *__first); + __next_pointer __next = __cache->__next_; __node_insert_unique(__cache->__upcast()); __cache = __next; } @@ -1276,7 +1260,7 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __ __deallocate_node(__cache); } for (; __first != __last; ++__first) - __insert_unique(*__first); + __emplace_unique(*__first); } template @@ -1284,17 +1268,15 @@ template void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first, _InputIterator __last) { typedef iterator_traits<_InputIterator> _ITraits; typedef typename _ITraits::value_type _ItValueType; - static_assert( - (is_same<_ItValueType, __container_value_type>::value || is_same<_ItValueType, __node_value_type>::value), - "__assign_multi may only be called with the containers value type" - " or the nodes value type"); + static_assert(is_same<_ItValueType, value_type>::value, + "__assign_multi may only be called with the containers value type or the nodes value type"); if (bucket_count() != 0) { __next_pointer __cache = __detach(); #if _LIBCPP_HAS_EXCEPTIONS try { #endif // _LIBCPP_HAS_EXCEPTIONS for (; __cache != nullptr && __first != __last; ++__first) { - __cache->__upcast()->__get_value() = *__first; + __assign_value(__cache->__upcast()->__get_value(), *__first); __next_pointer __next = __cache->__next_; __node_insert_multi(__cache->__upcast()); __cache = __next; @@ -1308,7 +1290,7 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __f __deallocate_node(__cache); } for (; __first != __last; ++__first) - __insert_multi(_NodeTypes::__get_value(*__first)); + __emplace_multi(*__first); } template @@ -1727,41 +1709,45 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __n) _LIBCPP_D template template -void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__do_rehash(size_type __nbc) { - __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc(); - __bucket_list_.reset(__nbc > 0 ? __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr); - __bucket_list_.get_deleter().size() = __nbc; - if (__nbc > 0) { - for (size_type __i = 0; __i < __nbc; ++__i) - __bucket_list_[__i] = nullptr; - __next_pointer __pp = __first_node_.__ptr(); - __next_pointer __cp = __pp->__next_; - if (__cp != nullptr) { - size_type __chash = std::__constrain_hash(__cp->__hash(), __nbc); - __bucket_list_[__chash] = __pp; - size_type __phash = __chash; - for (__pp = __cp, void(), __cp = __cp->__next_; __cp != nullptr; __cp = __pp->__next_) { - __chash = std::__constrain_hash(__cp->__hash(), __nbc); - if (__chash == __phash) - __pp = __cp; - else { - if (__bucket_list_[__chash] == nullptr) { - __bucket_list_[__chash] = __pp; - __pp = __cp; - __phash = __chash; - } else { - __next_pointer __np = __cp; - if _LIBCPP_CONSTEXPR_SINCE_CXX17 (!_UniqueKeys) { - for (; __np->__next_ != nullptr && - key_eq()(__cp->__upcast()->__get_value(), __np->__next_->__upcast()->__get_value()); - __np = __np->__next_) - ; - } - __pp->__next_ = __np->__next_; - __np->__next_ = __bucket_list_[__chash]->__next_; - __bucket_list_[__chash]->__next_ = __cp; - } +void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__do_rehash(size_type __bucket_count) { + __pointer_allocator& __ptr_alloc = __bucket_list_.get_deleter().__alloc(); + __bucket_list_.reset(__bucket_count > 0 ? __pointer_alloc_traits::allocate(__ptr_alloc, __bucket_count) : nullptr); + __bucket_list_.get_deleter().size() = __bucket_count; + + if (__bucket_count == 0) + return; + + for (size_type __i = 0; __i < __bucket_count; ++__i) + __bucket_list_[__i] = nullptr; + __next_pointer __pp = __first_node_.__ptr(); + __next_pointer __cp = __pp->__next_; + + if (!__cp) + return; + + size_type __chash = std::__constrain_hash(__cp->__hash(), __bucket_count); + __bucket_list_[__chash] = __pp; + size_type __phash = __chash; + for (__pp = __cp, void(), __cp = __cp->__next_; __cp != nullptr; __cp = __pp->__next_) { + __chash = std::__constrain_hash(__cp->__hash(), __bucket_count); + if (__chash == __phash) + __pp = __cp; + else { + if (__bucket_list_[__chash] == nullptr) { + __bucket_list_[__chash] = __pp; + __pp = __cp; + __phash = __chash; + } else { + __next_pointer __np = __cp; + if _LIBCPP_CONSTEXPR (!_UniqueKeys) { + for (; __np->__next_ != nullptr && + key_eq()(__cp->__upcast()->__get_value(), __np->__next_->__upcast()->__get_value()); + __np = __np->__next_) + ; } + __pp->__next_ = __np->__next_; + __np->__next_ = __bucket_list_[__chash]->__next_; + __bucket_list_[__chash]->__next_ = __cp; } } } @@ -1771,9 +1757,9 @@ template template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) { - size_t __hash = hash_function()(__k); size_type __bc = bucket_count(); - if (__bc != 0) { + if (__bc != 0 && size() != 0) { + size_t __hash = hash_function()(__k); size_t __chash = std::__constrain_hash(__hash, __bc); __next_pointer __nd = __bucket_list_[__chash]; if (__nd != nullptr) { @@ -1792,9 +1778,9 @@ template template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const { - size_t __hash = hash_function()(__k); size_type __bc = bucket_count(); - if (__bc != 0) { + if (__bc != 0 && size() != 0) { + size_t __hash = hash_function()(__k); size_t __chash = std::__constrain_hash(__hash, __bc); __next_pointer __nd = __bucket_list_[__chash]; if (__nd != nullptr) { @@ -1826,7 +1812,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&&... __args) { std::__construct_at(std::addressof(*__h), /* next = */ nullptr, /* hash = */ 0); // Now construct the value_type using the allocator's construct() method. - __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__get_value()), std::forward<_Args>(__args)...); + __node_traits::construct(__na, std::addressof(__h->__get_value()), std::forward<_Args>(__args)...); __h.get_deleter().__value_constructed = true; __h->__hash_ = hash_function()(__h->__get_value()); @@ -1842,7 +1828,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(size_t __hash, _ __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); std::__construct_at(std::addressof(*__h), /* next = */ nullptr, /* hash = */ __hash); __node_traits::construct( - __na, _NodeTypes::__get_ptr(__h->__get_value()), std::forward<_First>(__f), std::forward<_Rest>(__rest)...); + __na, std::addressof(__h->__get_value()), std::forward<_First>(__f), std::forward<_Rest>(__rest)...); __h.get_deleter().__value_constructed = true; return __h; } diff --git a/naiveproxy/src/third_party/libc++/src/include/__iterator/iterator_traits.h b/naiveproxy/src/third_party/libc++/src/include/__iterator/iterator_traits.h index 221d36614d..f727e8ff36 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__iterator/iterator_traits.h +++ b/naiveproxy/src/third_party/libc++/src/include/__iterator/iterator_traits.h @@ -71,23 +71,6 @@ struct random_access_iterator_tag : public bidirectional_iterator_tag {}; struct contiguous_iterator_tag : public random_access_iterator_tag {}; #endif -template -struct __has_iterator_typedefs { -private: - template - static false_type __test(...); - template - static true_type - __test(__void_t* = nullptr, - __void_t* = nullptr, - __void_t* = nullptr, - __void_t* = nullptr, - __void_t* = nullptr); - -public: - static const bool value = decltype(__test<_Tp>(nullptr, nullptr, nullptr, nullptr, nullptr))::value; -}; - #if _LIBCPP_STD_VER >= 20 // The `cpp17-*-iterator` exposition-only concepts have very similar names to the `Cpp17*Iterator` named requirements @@ -322,6 +305,23 @@ struct __iterator_traits<_Iter, true> is_convertible::value || is_convertible::value > {}; +template +struct __has_iterator_typedefs { +private: + template + static false_type __test(...); + template + static true_type + __test(__void_t* = nullptr, + __void_t* = nullptr, + __void_t* = nullptr, + __void_t* = nullptr, + __void_t* = nullptr); + +public: + static const bool value = decltype(__test<_Tp>(nullptr, nullptr, nullptr, nullptr, nullptr))::value; +}; + // iterator_traits will only have the nested types if Iterator::iterator_category // exists. Else iterator_traits will be an empty class. This is a // conforming extension which allows some programs to compile and behave as diff --git a/naiveproxy/src/third_party/libc++/src/include/__iterator/product_iterator.h b/naiveproxy/src/third_party/libc++/src/include/__iterator/product_iterator.h new file mode 100644 index 0000000000..1db673bafd --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__iterator/product_iterator.h @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// 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_PRODUCT_ITERATOR_H +#define _LIBCPP___ITERATOR_PRODUCT_ITERATOR_H + +// Product iterators are iterators that contain two or more underlying iterators. +// +// For example, std::flat_map stores its data into two separate containers, and its iterator +// is a proxy over two separate underlying iterators. The concept of product iterators +// allows algorithms to operate over these underlying iterators separately, opening the +// door to various optimizations. +// +// If __product_iterator_traits can be instantiated, the following functions and associated types must be provided: +// - static constexpr size_t Traits::__size +// The number of underlying iterators inside the product iterator. +// +// - template +// static decltype(auto) Traits::__get_iterator_element(It&& __it) +// Returns the _Nth iterator element of the given product iterator. +// +// - template +// static _Iterator __make_product_iterator(_Iters&&...); +// Creates a product iterator from the given underlying iterators. + +#include <__config> +#include <__cstddef/size_t.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__utility/declval.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct __product_iterator_traits; +/* exposition-only: +{ + static constexpr size_t __size = ...; + + template + static decltype(auto) __get_iterator_element(_Iter&&); + + template + static _Iterator __make_product_iterator(_Iters&&...); +}; +*/ + +template +struct __is_product_iterator : false_type {}; + +template +struct __is_product_iterator<_Tp, sizeof(__product_iterator_traits<_Tp>) * 0> : true_type {}; + +template +struct __is_product_iterator_of_size : false_type {}; + +template +struct __is_product_iterator_of_size<_Tp, _Size, __enable_if_t<__product_iterator_traits<_Tp>::__size == _Size> > + : true_type {}; + +template +using __product_iterator_element_t _LIBCPP_NODEBUG = + decltype(__product_iterator_traits<_Iterator>::template __get_iterator_element<_Nth>(std::declval<_Iterator>())); + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_PRODUCT_ITERATOR_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__iterator/segmented_iterator.h b/naiveproxy/src/third_party/libc++/src/include/__iterator/segmented_iterator.h index af27a7be41..5df9737137 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__iterator/segmented_iterator.h +++ b/naiveproxy/src/third_party/libc++/src/include/__iterator/segmented_iterator.h @@ -67,13 +67,13 @@ struct __segmented_iterator_traits; */ template -struct __has_specialization : false_type {}; +inline const bool __has_specialization_v = false; template -struct __has_specialization<_Tp, sizeof(_Tp) * 0> : true_type {}; +inline const bool __has_specialization_v<_Tp, sizeof(_Tp) * 0> = true; template -using __is_segmented_iterator _LIBCPP_NODEBUG = __has_specialization<__segmented_iterator_traits<_Iterator> >; +inline const bool __is_segmented_iterator_v = __has_specialization_v<__segmented_iterator_traits<_Iterator> >; template struct __has_random_access_local_iterator diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale b/naiveproxy/src/third_party/libc++/src/include/__locale index 92e45e2531..757a53951f 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__locale +++ b/naiveproxy/src/third_party/libc++/src/include/__locale @@ -589,18 +589,6 @@ public: # endif _LIBCPP_HIDE_FROM_ABI const mask* table() const _NOEXCEPT { return __tab_; } static const mask* classic_table() _NOEXCEPT; -# if defined(__GLIBC__) || defined(__EMSCRIPTEN__) - static const int* __classic_upper_table() _NOEXCEPT; - static const int* __classic_lower_table() _NOEXCEPT; -# endif -# if defined(__NetBSD__) - static const short* __classic_upper_table() _NOEXCEPT; - static const short* __classic_lower_table() _NOEXCEPT; -# endif -# if defined(__MVS__) - static const unsigned short* __classic_upper_table() _NOEXCEPT; - static const unsigned short* __classic_lower_table() _NOEXCEPT; -# endif protected: ~ctype() override; diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/check_grouping.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/check_grouping.h new file mode 100644 index 0000000000..93e9e404bb --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/check_grouping.h @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// 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___LOCALE_DIR_CHECK_GROUPING_H +#define _LIBCPP___LOCALE_DIR_CHECK_GROUPING_H + +#include <__config> +#include <__fwd/string.h> +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +_LIBCPP_EXPORTED_FROM_ABI void +__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end, ios_base::iostate& __err); + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_CHECK_GROUPING_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/get_c_locale.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/get_c_locale.h new file mode 100644 index 0000000000..e8bac9a870 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/get_c_locale.h @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// 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___LOCALE_DIR_GET_C_LOCALE_H +#define _LIBCPP___LOCALE_DIR_GET_C_LOCALE_H + +#include <__config> +#include <__locale_dir/locale_base_api.h> + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// FIXME: This should really be part of the locale base API + +# if defined(__APPLE__) || defined(__FreeBSD__) +# define _LIBCPP_GET_C_LOCALE 0 +# elif defined(__NetBSD__) +# define _LIBCPP_GET_C_LOCALE LC_C_LOCALE +# else +# define _LIBCPP_GET_C_LOCALE __cloc() +// Get the C locale object +_LIBCPP_EXPORTED_FROM_ABI __locale::__locale_t __cloc(); +# define __cloc_defined +# endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_GET_C_LOCALE_H 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 bbc30b1cfe..9f3ce02a3a 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 @@ -64,8 +64,6 @@ // Character manipulation functions // -------------------------------- // namespace __locale { -// int __islower(int, __locale_t); -// int __isupper(int, __locale_t); // int __isdigit(int, __locale_t); // required by the headers // int __isxdigit(int, __locale_t); // required by the headers // int __toupper(int, __locale_t); @@ -131,8 +129,6 @@ // will define those directly. # if defined(_AIX) || defined(__MVS__) # include <__locale_dir/locale_base_api/ibm.h> -# elif defined(__ANDROID__) -# include <__locale_dir/locale_base_api/android.h> # elif defined(__OpenBSD__) # include <__locale_dir/locale_base_api/openbsd.h> # elif defined(__wasi__) || _LIBCPP_HAS_MUSL_LIBC @@ -208,11 +204,6 @@ __strtoull(const char* __nptr, char** __endptr, int __base, __locale_t __loc) { // // Character manipulation functions // -# if defined(_LIBCPP_BUILDING_LIBRARY) -inline _LIBCPP_HIDE_FROM_ABI int __islower(int __ch, __locale_t __loc) { return islower_l(__ch, __loc); } -inline _LIBCPP_HIDE_FROM_ABI int __isupper(int __ch, __locale_t __loc) { return isupper_l(__ch, __loc); } -# endif - inline _LIBCPP_HIDE_FROM_ABI int __isdigit(int __ch, __locale_t __loc) { return isdigit_l(__ch, __loc); } inline _LIBCPP_HIDE_FROM_ABI int __isxdigit(int __ch, __locale_t __loc) { return isxdigit_l(__ch, __loc); } 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 deleted file mode 100644 index 36b8d93e1b..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/android.h +++ /dev/null @@ -1,45 +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___LOCALE_DIR_LOCALE_BASE_API_ANDROID_H -#define _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_ANDROID_H - -#include - -// FIXME: Is this actually required? -extern "C" { -#include -} - -#include - -// 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 -// In NDK versions later than 16, locale-aware functions are provided by -// legacy_stdlib_inlines.h -# if __NDK_MAJOR__ <= 16 -# if __ANDROID_API__ < 26 - -inline _LIBCPP_HIDE_FROM_ABI float strtof_l(const char* __nptr, char** __endptr, locale_t) { - return ::strtof(__nptr, __endptr); -} - -inline _LIBCPP_HIDE_FROM_ABI double strtod_l(const char* __nptr, char** __endptr, locale_t) { - return ::strtod(__nptr, __endptr); -} - -# endif // __ANDROID_API__ < 26 - -# endif // __NDK_MAJOR__ <= 16 -#endif // __has_include() - -#endif // _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_ANDROID_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/messages.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/messages.h new file mode 100644 index 0000000000..c04bf04025 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/messages.h @@ -0,0 +1,143 @@ +//===----------------------------------------------------------------------===// +// +// 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___LOCALE_DIR_MESSAGES_H +#define _LIBCPP___LOCALE_DIR_MESSAGES_H + +#include <__config> +#include <__iterator/back_insert_iterator.h> +#include <__locale> +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +# if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +// Most unix variants have catopen. These are the specific ones that don't. +# if !defined(__BIONIC__) && !defined(_NEWLIB_VERSION) && !defined(__EMSCRIPTEN__) +# define _LIBCPP_HAS_CATOPEN 1 +# include +# else +# define _LIBCPP_HAS_CATOPEN 0 +# endif +# else +# define _LIBCPP_HAS_CATOPEN 0 +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +class _LIBCPP_EXPORTED_FROM_ABI messages_base { +public: + typedef intptr_t catalog; + + _LIBCPP_HIDE_FROM_ABI messages_base() {} +}; + +template +class messages : public locale::facet, public messages_base { +public: + typedef _CharT char_type; + typedef basic_string<_CharT> string_type; + + _LIBCPP_HIDE_FROM_ABI explicit messages(size_t __refs = 0) : locale::facet(__refs) {} + + _LIBCPP_HIDE_FROM_ABI catalog open(const basic_string& __nm, const locale& __loc) const { + return do_open(__nm, __loc); + } + + _LIBCPP_HIDE_FROM_ABI string_type get(catalog __c, int __set, int __msgid, const string_type& __dflt) const { + return do_get(__c, __set, __msgid, __dflt); + } + + _LIBCPP_HIDE_FROM_ABI void close(catalog __c) const { do_close(__c); } + + static locale::id id; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~messages() override {} + + virtual catalog do_open(const basic_string&, const locale&) const; + virtual string_type do_get(catalog, int __set, int __msgid, const string_type& __dflt) const; + virtual void do_close(catalog) const; +}; + +template +locale::id messages<_CharT>::id; + +template +typename messages<_CharT>::catalog messages<_CharT>::do_open(const basic_string& __nm, const locale&) const { +# if _LIBCPP_HAS_CATOPEN + return (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE); +# else // !_LIBCPP_HAS_CATOPEN + (void)__nm; + return -1; +# endif // _LIBCPP_HAS_CATOPEN +} + +template +typename messages<_CharT>::string_type +messages<_CharT>::do_get(catalog __c, int __set, int __msgid, const string_type& __dflt) const { +# if _LIBCPP_HAS_CATOPEN + string __ndflt; + __narrow_to_utf8()( + std::back_inserter(__ndflt), __dflt.c_str(), __dflt.c_str() + __dflt.size()); + nl_catd __cat = (nl_catd)__c; + static_assert(sizeof(catalog) >= sizeof(nl_catd), "Unexpected nl_catd type"); + char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str()); + string_type __w; + __widen_from_utf8()(std::back_inserter(__w), __n, __n + std::strlen(__n)); + return __w; +# else // !_LIBCPP_HAS_CATOPEN + (void)__c; + (void)__set; + (void)__msgid; + return __dflt; +# endif // _LIBCPP_HAS_CATOPEN +} + +template +void messages<_CharT>::do_close(catalog __c) const { +# if _LIBCPP_HAS_CATOPEN + catclose((nl_catd)__c); +# else // !_LIBCPP_HAS_CATOPEN + (void)__c; +# endif // _LIBCPP_HAS_CATOPEN +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages; +# endif + +template +class messages_byname : public messages<_CharT> { +public: + typedef messages_base::catalog catalog; + typedef basic_string<_CharT> string_type; + + _LIBCPP_HIDE_FROM_ABI explicit messages_byname(const char*, size_t __refs = 0) : messages<_CharT>(__refs) {} + + _LIBCPP_HIDE_FROM_ABI explicit messages_byname(const string&, size_t __refs = 0) : messages<_CharT>(__refs) {} + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~messages_byname() override {} +}; + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname; +# endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_MESSAGES_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/money.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/money.h new file mode 100644 index 0000000000..c129666550 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/money.h @@ -0,0 +1,873 @@ +//===----------------------------------------------------------------------===// +// +// 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___LOCALE_DIR_MONEY_H +#define _LIBCPP___LOCALE_DIR_MONEY_H + +#include <__algorithm/copy.h> +#include <__algorithm/equal.h> +#include <__algorithm/find.h> +#include <__algorithm/reverse.h> +#include <__config> +#include <__locale> +#include <__locale_dir/check_grouping.h> +#include <__locale_dir/get_c_locale.h> +#include <__locale_dir/pad_and_output.h> +#include <__memory/unique_ptr.h> +#include +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_PUSH_MACROS +# include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +// money_base + +class _LIBCPP_EXPORTED_FROM_ABI money_base { +public: + enum part { none, space, symbol, sign, value }; + struct pattern { + char field[4]; + }; + + _LIBCPP_HIDE_FROM_ABI money_base() {} +}; + +// moneypunct + +template +class moneypunct : public locale::facet, public money_base { +public: + typedef _CharT char_type; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI explicit moneypunct(size_t __refs = 0) : locale::facet(__refs) {} + + _LIBCPP_HIDE_FROM_ABI char_type decimal_point() const { return do_decimal_point(); } + _LIBCPP_HIDE_FROM_ABI char_type thousands_sep() const { return do_thousands_sep(); } + _LIBCPP_HIDE_FROM_ABI string grouping() const { return do_grouping(); } + _LIBCPP_HIDE_FROM_ABI string_type curr_symbol() const { return do_curr_symbol(); } + _LIBCPP_HIDE_FROM_ABI string_type positive_sign() const { return do_positive_sign(); } + _LIBCPP_HIDE_FROM_ABI string_type negative_sign() const { return do_negative_sign(); } + _LIBCPP_HIDE_FROM_ABI int frac_digits() const { return do_frac_digits(); } + _LIBCPP_HIDE_FROM_ABI pattern pos_format() const { return do_pos_format(); } + _LIBCPP_HIDE_FROM_ABI pattern neg_format() const { return do_neg_format(); } + + static locale::id id; + static const bool intl = _International; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~moneypunct() override {} + + virtual char_type do_decimal_point() const { return numeric_limits::max(); } + virtual char_type do_thousands_sep() const { return numeric_limits::max(); } + virtual string do_grouping() const { return string(); } + virtual string_type do_curr_symbol() const { return string_type(); } + virtual string_type do_positive_sign() const { return string_type(); } + virtual string_type do_negative_sign() const { return string_type(1, '-'); } + virtual int do_frac_digits() const { return 0; } + virtual pattern do_pos_format() const { + pattern __p = {{symbol, sign, none, value}}; + return __p; + } + virtual pattern do_neg_format() const { + pattern __p = {{symbol, sign, none, value}}; + return __p; + } +}; + +template +locale::id moneypunct<_CharT, _International>::id; + +template +const bool moneypunct<_CharT, _International>::intl; + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct; +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct; +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct; +# endif + +// moneypunct_byname + +template +class moneypunct_byname : public moneypunct<_CharT, _International> { +public: + typedef money_base::pattern pattern; + typedef _CharT char_type; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI explicit moneypunct_byname(const char* __nm, size_t __refs = 0) + : moneypunct<_CharT, _International>(__refs) { + init(__nm); + } + + _LIBCPP_HIDE_FROM_ABI explicit moneypunct_byname(const string& __nm, size_t __refs = 0) + : moneypunct<_CharT, _International>(__refs) { + init(__nm.c_str()); + } + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~moneypunct_byname() override {} + + char_type do_decimal_point() const override { return __decimal_point_; } + char_type do_thousands_sep() const override { return __thousands_sep_; } + string do_grouping() const override { return __grouping_; } + string_type do_curr_symbol() const override { return __curr_symbol_; } + string_type do_positive_sign() const override { return __positive_sign_; } + string_type do_negative_sign() const override { return __negative_sign_; } + int do_frac_digits() const override { return __frac_digits_; } + pattern do_pos_format() const override { return __pos_format_; } + pattern do_neg_format() const override { return __neg_format_; } + +private: + char_type __decimal_point_; + char_type __thousands_sep_; + string __grouping_; + string_type __curr_symbol_; + string_type __positive_sign_; + string_type __negative_sign_; + int __frac_digits_; + pattern __pos_format_; + pattern __neg_format_; + + void init(const char*); +}; + +template <> +_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname::init(const char*); +template <> +_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname::init(const char*); +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname; +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname; + +# if _LIBCPP_HAS_WIDE_CHARACTERS +template <> +_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname::init(const char*); +template <> +_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname::init(const char*); +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname; +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname; +# endif + +// money_get + +template +class __money_get { +protected: + typedef _CharT char_type; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI __money_get() {} + + static void __gather_info( + bool __intl, + const locale& __loc, + money_base::pattern& __pat, + char_type& __dp, + char_type& __ts, + string& __grp, + string_type& __sym, + string_type& __psn, + string_type& __nsn, + int& __fd); +}; + +template +void __money_get<_CharT>::__gather_info( + bool __intl, + const locale& __loc, + money_base::pattern& __pat, + char_type& __dp, + char_type& __ts, + string& __grp, + string_type& __sym, + string_type& __psn, + string_type& __nsn, + int& __fd) { + if (__intl) { + const moneypunct& __mp = std::use_facet >(__loc); + __pat = __mp.neg_format(); + __nsn = __mp.negative_sign(); + __psn = __mp.positive_sign(); + __dp = __mp.decimal_point(); + __ts = __mp.thousands_sep(); + __grp = __mp.grouping(); + __sym = __mp.curr_symbol(); + __fd = __mp.frac_digits(); + } else { + const moneypunct& __mp = std::use_facet >(__loc); + __pat = __mp.neg_format(); + __nsn = __mp.negative_sign(); + __psn = __mp.positive_sign(); + __dp = __mp.decimal_point(); + __ts = __mp.thousands_sep(); + __grp = __mp.grouping(); + __sym = __mp.curr_symbol(); + __fd = __mp.frac_digits(); + } +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get; +# endif + +template > +class money_get : public locale::facet, private __money_get<_CharT> { +public: + typedef _CharT char_type; + typedef _InputIterator iter_type; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI explicit money_get(size_t __refs = 0) : locale::facet(__refs) {} + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { + return do_get(__b, __e, __intl, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const { + return do_get(__b, __e, __intl, __iob, __err, __v); + } + + static locale::id id; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~money_get() override {} + + virtual iter_type + do_get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const; + virtual iter_type + do_get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const; + +private: + static bool __do_get( + iter_type& __b, + iter_type __e, + bool __intl, + const locale& __loc, + ios_base::fmtflags __flags, + ios_base::iostate& __err, + bool& __neg, + const ctype& __ct, + unique_ptr& __wb, + char_type*& __wn, + char_type* __we); +}; + +template +locale::id money_get<_CharT, _InputIterator>::id; + +_LIBCPP_EXPORTED_FROM_ABI void __do_nothing(void*); + +template +_LIBCPP_HIDE_FROM_ABI void __double_or_nothing(unique_ptr<_Tp, void (*)(void*)>& __b, _Tp*& __n, _Tp*& __e) { + bool __owns = __b.get_deleter() != __do_nothing; + size_t __cur_cap = static_cast(__e - __b.get()) * sizeof(_Tp); + size_t __new_cap = __cur_cap < numeric_limits::max() / 2 ? 2 * __cur_cap : numeric_limits::max(); + if (__new_cap == 0) + __new_cap = sizeof(_Tp); + size_t __n_off = static_cast(__n - __b.get()); + _Tp* __t = (_Tp*)std::realloc(__owns ? __b.get() : 0, __new_cap); + if (__t == 0) + std::__throw_bad_alloc(); + if (__owns) + __b.release(); + else + std::memcpy(__t, __b.get(), __cur_cap); + __b = unique_ptr<_Tp, void (*)(void*)>(__t, free); + __new_cap /= sizeof(_Tp); + __n = __b.get() + __n_off; + __e = __b.get() + __new_cap; +} + +// true == success +template +bool money_get<_CharT, _InputIterator>::__do_get( + iter_type& __b, + iter_type __e, + bool __intl, + const locale& __loc, + ios_base::fmtflags __flags, + ios_base::iostate& __err, + bool& __neg, + const ctype& __ct, + unique_ptr& __wb, + char_type*& __wn, + char_type* __we) { + if (__b == __e) { + __err |= ios_base::failbit; + return false; + } + const unsigned __bz = 100; + unsigned __gbuf[__bz]; + unique_ptr __gb(__gbuf, __do_nothing); + unsigned* __gn = __gb.get(); + unsigned* __ge = __gn + __bz; + money_base::pattern __pat; + char_type __dp; + char_type __ts; + string __grp; + string_type __sym; + string_type __psn; + string_type __nsn; + // Capture the spaces read into money_base::{space,none} so they + // can be compared to initial spaces in __sym. + string_type __spaces; + int __fd; + __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp, __sym, __psn, __nsn, __fd); + const string_type* __trailing_sign = 0; + __wn = __wb.get(); + for (unsigned __p = 0; __p < 4 && __b != __e; ++__p) { + switch (__pat.field[__p]) { + case money_base::space: + if (__p != 3) { + if (__ct.is(ctype_base::space, *__b)) + __spaces.push_back(*__b++); + else { + __err |= ios_base::failbit; + return false; + } + } + [[__fallthrough__]]; + case money_base::none: + if (__p != 3) { + while (__b != __e && __ct.is(ctype_base::space, *__b)) + __spaces.push_back(*__b++); + } + break; + case money_base::sign: + if (__psn.size() > 0 && *__b == __psn[0]) { + ++__b; + __neg = false; + if (__psn.size() > 1) + __trailing_sign = std::addressof(__psn); + break; + } + if (__nsn.size() > 0 && *__b == __nsn[0]) { + ++__b; + __neg = true; + if (__nsn.size() > 1) + __trailing_sign = std::addressof(__nsn); + break; + } + if (__psn.size() > 0 && __nsn.size() > 0) { // sign is required + __err |= ios_base::failbit; + return false; + } + if (__psn.size() == 0 && __nsn.size() == 0) + // locale has no way of specifying a sign. Use the initial value of __neg as a default + break; + __neg = (__nsn.size() == 0); + break; + case money_base::symbol: { + bool __more_needed = + __trailing_sign || (__p < 2) || (__p == 2 && __pat.field[3] != static_cast(money_base::none)); + bool __sb = (__flags & ios_base::showbase) != 0; + if (__sb || __more_needed) { + typename string_type::const_iterator __sym_space_end = __sym.begin(); + if (__p > 0 && (__pat.field[__p - 1] == money_base::none || __pat.field[__p - 1] == money_base::space)) { + // Match spaces we've already read against spaces at + // the beginning of __sym. + while (__sym_space_end != __sym.end() && __ct.is(ctype_base::space, *__sym_space_end)) + ++__sym_space_end; + const size_t __num_spaces = __sym_space_end - __sym.begin(); + if (__num_spaces > __spaces.size() || + !std::equal(__spaces.end() - __num_spaces, __spaces.end(), __sym.begin())) { + // No match. Put __sym_space_end back at the + // beginning of __sym, which will prevent a + // match in the next loop. + __sym_space_end = __sym.begin(); + } + } + typename string_type::const_iterator __sym_curr_char = __sym_space_end; + while (__sym_curr_char != __sym.end() && __b != __e && *__b == *__sym_curr_char) { + ++__b; + ++__sym_curr_char; + } + if (__sb && __sym_curr_char != __sym.end()) { + __err |= ios_base::failbit; + return false; + } + } + } break; + case money_base::value: { + unsigned __ng = 0; + for (; __b != __e; ++__b) { + char_type __c = *__b; + if (__ct.is(ctype_base::digit, __c)) { + if (__wn == __we) + std::__double_or_nothing(__wb, __wn, __we); + *__wn++ = __c; + ++__ng; + } else if (__grp.size() > 0 && __ng > 0 && __c == __ts) { + if (__gn == __ge) + std::__double_or_nothing(__gb, __gn, __ge); + *__gn++ = __ng; + __ng = 0; + } else + break; + } + if (__gb.get() != __gn && __ng > 0) { + if (__gn == __ge) + std::__double_or_nothing(__gb, __gn, __ge); + *__gn++ = __ng; + } + if (__fd > 0) { + if (__b == __e || *__b != __dp) { + __err |= ios_base::failbit; + return false; + } + for (++__b; __fd > 0; --__fd, ++__b) { + if (__b == __e || !__ct.is(ctype_base::digit, *__b)) { + __err |= ios_base::failbit; + return false; + } + if (__wn == __we) + std::__double_or_nothing(__wb, __wn, __we); + *__wn++ = *__b; + } + } + if (__wn == __wb.get()) { + __err |= ios_base::failbit; + return false; + } + } break; + } + } + if (__trailing_sign) { + for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b) { + if (__b == __e || *__b != (*__trailing_sign)[__i]) { + __err |= ios_base::failbit; + return false; + } + } + } + if (__gb.get() != __gn) { + ios_base::iostate __et = ios_base::goodbit; + __check_grouping(__grp, __gb.get(), __gn, __et); + if (__et) { + __err |= ios_base::failbit; + return false; + } + } + return true; +} + +template +_InputIterator money_get<_CharT, _InputIterator>::do_get( + iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { + const int __bz = 100; + char_type __wbuf[__bz]; + unique_ptr __wb(__wbuf, __do_nothing); + char_type* __wn; + char_type* __we = __wbuf + __bz; + locale __loc = __iob.getloc(); + const ctype& __ct = std::use_facet >(__loc); + bool __neg = false; + if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct, __wb, __wn, __we)) { + const char __src[] = "0123456789"; + char_type __atoms[sizeof(__src) - 1]; + __ct.widen(__src, __src + (sizeof(__src) - 1), __atoms); + char __nbuf[__bz]; + char* __nc = __nbuf; + const char* __nc_in = __nc; + unique_ptr __h(nullptr, free); + if (__wn - __wb.get() > __bz - 2) { + __h.reset((char*)malloc(static_cast(__wn - __wb.get() + 2))); + if (__h.get() == nullptr) + std::__throw_bad_alloc(); + __nc = __h.get(); + __nc_in = __nc; + } + if (__neg) + *__nc++ = '-'; + for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc) + *__nc = __src[std::find(__atoms, std::end(__atoms), *__w) - __atoms]; + *__nc = char(); + if (sscanf(__nc_in, "%Lf", &__v) != 1) + std::__throw_runtime_error("money_get error"); + } + if (__b == __e) + __err |= ios_base::eofbit; + return __b; +} + +template +_InputIterator money_get<_CharT, _InputIterator>::do_get( + iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const { + const int __bz = 100; + char_type __wbuf[__bz]; + unique_ptr __wb(__wbuf, __do_nothing); + char_type* __wn; + char_type* __we = __wbuf + __bz; + locale __loc = __iob.getloc(); + const ctype& __ct = std::use_facet >(__loc); + bool __neg = false; + if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct, __wb, __wn, __we)) { + __v.clear(); + if (__neg) + __v.push_back(__ct.widen('-')); + char_type __z = __ct.widen('0'); + char_type* __w; + for (__w = __wb.get(); __w < __wn - 1; ++__w) + if (*__w != __z) + break; + __v.append(__w, __wn); + } + if (__b == __e) + __err |= ios_base::eofbit; + return __b; +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get; +# endif + +// money_put + +template +class __money_put { +protected: + typedef _CharT char_type; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI __money_put() {} + + static void __gather_info( + bool __intl, + bool __neg, + const locale& __loc, + money_base::pattern& __pat, + char_type& __dp, + char_type& __ts, + string& __grp, + string_type& __sym, + string_type& __sn, + int& __fd); + static void __format( + char_type* __mb, + char_type*& __mi, + char_type*& __me, + ios_base::fmtflags __flags, + const char_type* __db, + const char_type* __de, + const ctype& __ct, + bool __neg, + const money_base::pattern& __pat, + char_type __dp, + char_type __ts, + const string& __grp, + const string_type& __sym, + const string_type& __sn, + int __fd); +}; + +template +void __money_put<_CharT>::__gather_info( + bool __intl, + bool __neg, + const locale& __loc, + money_base::pattern& __pat, + char_type& __dp, + char_type& __ts, + string& __grp, + string_type& __sym, + string_type& __sn, + int& __fd) { + if (__intl) { + const moneypunct& __mp = std::use_facet >(__loc); + if (__neg) { + __pat = __mp.neg_format(); + __sn = __mp.negative_sign(); + } else { + __pat = __mp.pos_format(); + __sn = __mp.positive_sign(); + } + __dp = __mp.decimal_point(); + __ts = __mp.thousands_sep(); + __grp = __mp.grouping(); + __sym = __mp.curr_symbol(); + __fd = __mp.frac_digits(); + } else { + const moneypunct& __mp = std::use_facet >(__loc); + if (__neg) { + __pat = __mp.neg_format(); + __sn = __mp.negative_sign(); + } else { + __pat = __mp.pos_format(); + __sn = __mp.positive_sign(); + } + __dp = __mp.decimal_point(); + __ts = __mp.thousands_sep(); + __grp = __mp.grouping(); + __sym = __mp.curr_symbol(); + __fd = __mp.frac_digits(); + } +} + +template +void __money_put<_CharT>::__format( + char_type* __mb, + char_type*& __mi, + char_type*& __me, + ios_base::fmtflags __flags, + const char_type* __db, + const char_type* __de, + const ctype& __ct, + bool __neg, + const money_base::pattern& __pat, + char_type __dp, + char_type __ts, + const string& __grp, + const string_type& __sym, + const string_type& __sn, + int __fd) { + __me = __mb; + for (char __p : __pat.field) { + switch (__p) { + case money_base::none: + __mi = __me; + break; + case money_base::space: + __mi = __me; + *__me++ = __ct.widen(' '); + break; + case money_base::sign: + if (!__sn.empty()) + *__me++ = __sn[0]; + break; + case money_base::symbol: + if (!__sym.empty() && (__flags & ios_base::showbase)) + __me = std::copy(__sym.begin(), __sym.end(), __me); + break; + case money_base::value: { + // remember start of value so we can reverse it + char_type* __t = __me; + // find beginning of digits + if (__neg) + ++__db; + // find end of digits + const char_type* __d; + for (__d = __db; __d < __de; ++__d) + if (!__ct.is(ctype_base::digit, *__d)) + break; + // print fractional part + if (__fd > 0) { + int __f; + for (__f = __fd; __d > __db && __f > 0; --__f) + *__me++ = *--__d; + char_type __z = __f > 0 ? __ct.widen('0') : char_type(); + for (; __f > 0; --__f) + *__me++ = __z; + *__me++ = __dp; + } + // print units part + if (__d == __db) { + *__me++ = __ct.widen('0'); + } else { + unsigned __ng = 0; + unsigned __ig = 0; + unsigned __gl = __grp.empty() ? numeric_limits::max() : static_cast(__grp[__ig]); + while (__d != __db) { + if (__ng == __gl) { + *__me++ = __ts; + __ng = 0; + if (++__ig < __grp.size()) + __gl = __grp[__ig] == numeric_limits::max() + ? numeric_limits::max() + : static_cast(__grp[__ig]); + } + *__me++ = *--__d; + ++__ng; + } + } + // reverse it + std::reverse(__t, __me); + } break; + } + } + // print rest of sign, if any + if (__sn.size() > 1) + __me = std::copy(__sn.begin() + 1, __sn.end(), __me); + // set alignment + if ((__flags & ios_base::adjustfield) == ios_base::left) + __mi = __me; + else if ((__flags & ios_base::adjustfield) != ios_base::internal) + __mi = __mb; +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put; +# endif + +template > +class money_put : public locale::facet, private __money_put<_CharT> { +public: + typedef _CharT char_type; + typedef _OutputIterator iter_type; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI explicit money_put(size_t __refs = 0) : locale::facet(__refs) {} + + _LIBCPP_HIDE_FROM_ABI iter_type + put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const { + return do_put(__s, __intl, __iob, __fl, __units); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const { + return do_put(__s, __intl, __iob, __fl, __digits); + } + + static locale::id id; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~money_put() override {} + + virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const; + virtual iter_type + do_put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const; +}; + +template +locale::id money_put<_CharT, _OutputIterator>::id; + +template +_OutputIterator money_put<_CharT, _OutputIterator>::do_put( + iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const { + // convert to char + const size_t __bs = 100; + char __buf[__bs]; + char* __bb = __buf; + char_type __digits[__bs]; + char_type* __db = __digits; + int __n = snprintf(__bb, __bs, "%.0Lf", __units); + unique_ptr __hn(nullptr, free); + unique_ptr __hd(0, free); + // secure memory for digit storage + if (static_cast(__n) > __bs - 1) { + __n = __locale::__asprintf(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units); + if (__n == -1) + std::__throw_bad_alloc(); + __hn.reset(__bb); + __hd.reset((char_type*)malloc(static_cast(__n) * sizeof(char_type))); + if (__hd == nullptr) + std::__throw_bad_alloc(); + __db = __hd.get(); + } + // gather info + locale __loc = __iob.getloc(); + const ctype& __ct = std::use_facet >(__loc); + __ct.widen(__bb, __bb + __n, __db); + bool __neg = __n > 0 && __bb[0] == '-'; + money_base::pattern __pat; + char_type __dp; + char_type __ts; + string __grp; + string_type __sym; + string_type __sn; + int __fd; + this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd); + // secure memory for formatting + char_type __mbuf[__bs]; + char_type* __mb = __mbuf; + unique_ptr __hw(0, free); + size_t __exn = __n > __fd ? (static_cast(__n) - static_cast(__fd)) * 2 + __sn.size() + __sym.size() + + static_cast(__fd) + 1 + : __sn.size() + __sym.size() + static_cast(__fd) + 2; + if (__exn > __bs) { + __hw.reset((char_type*)malloc(__exn * sizeof(char_type))); + __mb = __hw.get(); + if (__mb == 0) + std::__throw_bad_alloc(); + } + // format + char_type* __mi; + char_type* __me; + this->__format( + __mb, __mi, __me, __iob.flags(), __db, __db + __n, __ct, __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd); + return std::__pad_and_output(__s, __mb, __mi, __me, __iob, __fl); +} + +template +_OutputIterator money_put<_CharT, _OutputIterator>::do_put( + iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const { + // gather info + locale __loc = __iob.getloc(); + const ctype& __ct = std::use_facet >(__loc); + bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-'); + money_base::pattern __pat; + char_type __dp; + char_type __ts; + string __grp; + string_type __sym; + string_type __sn; + int __fd; + this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd); + // secure memory for formatting + char_type __mbuf[100]; + char_type* __mb = __mbuf; + unique_ptr __h(0, free); + size_t __exn = + static_cast(__digits.size()) > __fd + ? (__digits.size() - static_cast(__fd)) * 2 + __sn.size() + __sym.size() + static_cast(__fd) + + 1 + : __sn.size() + __sym.size() + static_cast(__fd) + 2; + if (__exn > 100) { + __h.reset((char_type*)malloc(__exn * sizeof(char_type))); + __mb = __h.get(); + if (__mb == 0) + std::__throw_bad_alloc(); + } + // format + char_type* __mi; + char_type* __me; + this->__format( + __mb, + __mi, + __me, + __iob.flags(), + __digits.data(), + __digits.data() + __digits.size(), + __ct, + __neg, + __pat, + __dp, + __ts, + __grp, + __sym, + __sn, + __fd); + return std::__pad_and_output(__s, __mb, __mi, __me, __iob, __fl); +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put; +# endif + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_MONEY_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/num.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/num.h new file mode 100644 index 0000000000..7ca8ffe348 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/num.h @@ -0,0 +1,1072 @@ +//===----------------------------------------------------------------------===// +// +// 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___LOCALE_DIR_NUM_H +#define _LIBCPP___LOCALE_DIR_NUM_H + +#include <__algorithm/find.h> +#include <__algorithm/reverse.h> +#include <__charconv/to_chars_integral.h> +#include <__charconv/traits.h> +#include <__config> +#include <__iterator/istreambuf_iterator.h> +#include <__iterator/ostreambuf_iterator.h> +#include <__locale_dir/check_grouping.h> +#include <__locale_dir/get_c_locale.h> +#include <__locale_dir/pad_and_output.h> +#include <__locale_dir/scan_keyword.h> +#include <__memory/unique_ptr.h> +#include <__system_error/errc.h> +#include +#include +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +// TODO: Properly qualify calls now that the locale base API defines functions instead of macros +// NOLINTBEGIN(libcpp-robust-against-adl) + +_LIBCPP_PUSH_MACROS +# include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct _LIBCPP_EXPORTED_FROM_ABI __num_get_base { + static const int __num_get_buf_sz = 40; + + static int __get_base(ios_base&); + static const char __src[33]; // "0123456789abcdefABCDEFxX+-pPiInN" + // count of leading characters in __src used for parsing integers ("012..X+-") + static const size_t __int_chr_cnt = 26; + // count of leading characters in __src used for parsing floating-point values ("012..-pP") + static const size_t __fp_chr_cnt = 28; +}; + +template +struct __num_get : protected __num_get_base { + static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point, _CharT& __thousands_sep); + + static int __stage2_float_loop( + _CharT __ct, + bool& __in_units, + char& __exp, + char* __a, + char*& __a_end, + _CharT __decimal_point, + _CharT __thousands_sep, + const string& __grouping, + unsigned* __g, + unsigned*& __g_end, + unsigned& __dc, + _CharT* __atoms); + + [[__deprecated__("This exists only for ABI compatibility")]] static string + __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep); + static int __stage2_int_loop( + _CharT __ct, + int __base, + char* __a, + char*& __a_end, + unsigned& __dc, + _CharT __thousands_sep, + const string& __grouping, + unsigned* __g, + unsigned*& __g_end, + _CharT* __atoms); + + _LIBCPP_HIDE_FROM_ABI static string __stage2_int_prep(ios_base& __iob, _CharT& __thousands_sep) { + locale __loc = __iob.getloc(); + const numpunct<_CharT>& __np = use_facet >(__loc); + __thousands_sep = __np.thousands_sep(); + return __np.grouping(); + } + + _LIBCPP_HIDE_FROM_ABI const _CharT* __do_widen(ios_base& __iob, _CharT* __atoms) const { + return __do_widen_p(__iob, __atoms); + } + +private: + template + _LIBCPP_HIDE_FROM_ABI const _Tp* __do_widen_p(ios_base& __iob, _Tp* __atoms) const { + locale __loc = __iob.getloc(); + use_facet >(__loc).widen(__src, __src + __int_chr_cnt, __atoms); + return __atoms; + } + + _LIBCPP_HIDE_FROM_ABI const char* __do_widen_p(ios_base& __iob, char* __atoms) const { + (void)__iob; + (void)__atoms; + return __src; + } +}; + +template +string __num_get<_CharT>::__stage2_float_prep( + ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point, _CharT& __thousands_sep) { + locale __loc = __iob.getloc(); + std::use_facet >(__loc).widen(__src, __src + __fp_chr_cnt, __atoms); + const numpunct<_CharT>& __np = std::use_facet >(__loc); + __decimal_point = __np.decimal_point(); + __thousands_sep = __np.thousands_sep(); + return __np.grouping(); +} + +template +int __num_get<_CharT>::__stage2_int_loop( + _CharT __ct, + int __base, + char* __a, + char*& __a_end, + unsigned& __dc, + _CharT __thousands_sep, + const string& __grouping, + unsigned* __g, + unsigned*& __g_end, + _CharT* __atoms) { + if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25])) { + *__a_end++ = __ct == __atoms[24] ? '+' : '-'; + __dc = 0; + return 0; + } + if (__grouping.size() != 0 && __ct == __thousands_sep) { + if (__g_end - __g < __num_get_buf_sz) { + *__g_end++ = __dc; + __dc = 0; + } + return 0; + } + ptrdiff_t __f = std::find(__atoms, __atoms + __int_chr_cnt, __ct) - __atoms; + if (__f >= 24) + return -1; + switch (__base) { + case 8: + case 10: + if (__f >= __base) + return -1; + break; + case 16: + if (__f < 22) + break; + if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0') { + __dc = 0; + *__a_end++ = __src[__f]; + return 0; + } + return -1; + } + *__a_end++ = __src[__f]; + ++__dc; + return 0; +} + +template +int __num_get<_CharT>::__stage2_float_loop( + _CharT __ct, + bool& __in_units, + char& __exp, + char* __a, + char*& __a_end, + _CharT __decimal_point, + _CharT __thousands_sep, + const string& __grouping, + unsigned* __g, + unsigned*& __g_end, + unsigned& __dc, + _CharT* __atoms) { + if (__ct == __decimal_point) { + if (!__in_units) + return -1; + __in_units = false; + *__a_end++ = '.'; + if (__grouping.size() != 0 && __g_end - __g < __num_get_buf_sz) + *__g_end++ = __dc; + return 0; + } + if (__ct == __thousands_sep && __grouping.size() != 0) { + if (!__in_units) + return -1; + if (__g_end - __g < __num_get_buf_sz) { + *__g_end++ = __dc; + __dc = 0; + } + return 0; + } + ptrdiff_t __f = std::find(__atoms, __atoms + __num_get_base::__fp_chr_cnt, __ct) - __atoms; + if (__f >= static_cast(__num_get_base::__fp_chr_cnt)) + return -1; + char __x = __src[__f]; + if (__x == '-' || __x == '+') { + if (__a_end == __a || (std::toupper(__a_end[-1]) == std::toupper(__exp))) { + *__a_end++ = __x; + return 0; + } + return -1; + } + if (__x == 'x' || __x == 'X') + __exp = 'P'; + else if (std::toupper(__x) == __exp) { + __exp = std::tolower(__exp); + if (__in_units) { + __in_units = false; + if (__grouping.size() != 0 && __g_end - __g < __num_get_buf_sz) + *__g_end++ = __dc; + } + } + *__a_end++ = __x; + if (__f >= 22) + return 0; + ++__dc; + return 0; +} + +extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get; +# endif + +template +_LIBCPP_HIDE_FROM_ABI _Tp __do_strtod(const char* __a, char** __p2); + +template <> +inline _LIBCPP_HIDE_FROM_ABI float __do_strtod(const char* __a, char** __p2) { + return __locale::__strtof(__a, __p2, _LIBCPP_GET_C_LOCALE); +} + +template <> +inline _LIBCPP_HIDE_FROM_ABI double __do_strtod(const char* __a, char** __p2) { + return __locale::__strtod(__a, __p2, _LIBCPP_GET_C_LOCALE); +} + +template <> +inline _LIBCPP_HIDE_FROM_ABI long double __do_strtod(const char* __a, char** __p2) { + return __locale::__strtold(__a, __p2, _LIBCPP_GET_C_LOCALE); +} + +template +_LIBCPP_HIDE_FROM_ABI _Tp __num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err) { + if (__a != __a_end) { + __libcpp_remove_reference_t __save_errno = errno; + errno = 0; + char* __p2; + _Tp __ld = std::__do_strtod<_Tp>(__a, &__p2); + __libcpp_remove_reference_t __current_errno = errno; + if (__current_errno == 0) + errno = __save_errno; + if (__p2 != __a_end) { + __err = ios_base::failbit; + return 0; + } else if (__current_errno == ERANGE) + __err = ios_base::failbit; + return __ld; + } + __err = ios_base::failbit; + return 0; +} + +template +_LIBCPP_HIDE_FROM_ABI _Tp +__num_get_signed_integral(const char* __a, const char* __a_end, ios_base::iostate& __err, int __base) { + if (__a != __a_end) { + __libcpp_remove_reference_t __save_errno = errno; + errno = 0; + char* __p2; + long long __ll = __locale::__strtoll(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE); + __libcpp_remove_reference_t __current_errno = errno; + if (__current_errno == 0) + errno = __save_errno; + if (__p2 != __a_end) { + __err = ios_base::failbit; + return 0; + } else if (__current_errno == ERANGE || __ll < numeric_limits<_Tp>::min() || numeric_limits<_Tp>::max() < __ll) { + __err = ios_base::failbit; + if (__ll > 0) + return numeric_limits<_Tp>::max(); + else + return numeric_limits<_Tp>::min(); + } + return static_cast<_Tp>(__ll); + } + __err = ios_base::failbit; + return 0; +} + +template +_LIBCPP_HIDE_FROM_ABI _Tp +__num_get_unsigned_integral(const char* __a, const char* __a_end, ios_base::iostate& __err, int __base) { + if (__a != __a_end) { + const bool __negate = *__a == '-'; + if (__negate && ++__a == __a_end) { + __err = ios_base::failbit; + return 0; + } + __libcpp_remove_reference_t __save_errno = errno; + errno = 0; + char* __p2; + unsigned long long __ll = __locale::__strtoull(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE); + __libcpp_remove_reference_t __current_errno = errno; + if (__current_errno == 0) + errno = __save_errno; + if (__p2 != __a_end) { + __err = ios_base::failbit; + return 0; + } else if (__current_errno == ERANGE || numeric_limits<_Tp>::max() < __ll) { + __err = ios_base::failbit; + return numeric_limits<_Tp>::max(); + } + _Tp __res = static_cast<_Tp>(__ll); + if (__negate) + __res = -__res; + return __res; + } + __err = ios_base::failbit; + return 0; +} + +template > +class num_get : public locale::facet, private __num_get<_CharT> { +public: + typedef _CharT char_type; + typedef _InputIterator iter_type; + + _LIBCPP_HIDE_FROM_ABI explicit num_get(size_t __refs = 0) : locale::facet(__refs) {} + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long long& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned short& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned int& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long long& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, float& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, double& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + static locale::id id; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~num_get() override {} + + template + _LIBCPP_HIDE_FROM_ABI iter_type + __do_get_floating_point(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Fp& __v) const { + // Stage 1, nothing to do + // Stage 2 + char_type __atoms[__num_get_base::__fp_chr_cnt]; + char_type __decimal_point; + char_type __thousands_sep; + string __grouping = this->__stage2_float_prep(__iob, __atoms, __decimal_point, __thousands_sep); + string __buf; + __buf.resize(__buf.capacity()); + char* __a = &__buf[0]; + char* __a_end = __a; + unsigned __g[__num_get_base::__num_get_buf_sz]; + unsigned* __g_end = __g; + unsigned __dc = 0; + bool __in_units = true; + char __exp = 'E'; + bool __is_leading_parsed = false; + for (; __b != __e; ++__b) { + if (__a_end == __a + __buf.size()) { + size_t __tmp = __buf.size(); + __buf.resize(2 * __buf.size()); + __buf.resize(__buf.capacity()); + __a = &__buf[0]; + __a_end = __a + __tmp; + } + if (this->__stage2_float_loop( + *__b, + __in_units, + __exp, + __a, + __a_end, + __decimal_point, + __thousands_sep, + __grouping, + __g, + __g_end, + __dc, + __atoms)) + break; + + // the leading character excluding the sign must be a decimal digit + if (!__is_leading_parsed) { + if (__a_end - __a >= 1 && __a[0] != '-' && __a[0] != '+') { + if (('0' <= __a[0] && __a[0] <= '9') || __a[0] == '.') + __is_leading_parsed = true; + else + break; + } else if (__a_end - __a >= 2 && (__a[0] == '-' || __a[0] == '+')) { + if (('0' <= __a[1] && __a[1] <= '9') || __a[1] == '.') + __is_leading_parsed = true; + else + break; + } + } + } + if (__grouping.size() != 0 && __in_units && __g_end - __g < __num_get_base::__num_get_buf_sz) + *__g_end++ = __dc; + // Stage 3 + __v = std::__num_get_float<_Fp>(__a, __a_end, __err); + // Digit grouping checked + __check_grouping(__grouping, __g, __g_end, __err); + // EOF checked + if (__b == __e) + __err |= ios_base::eofbit; + return __b; + } + + template + _LIBCPP_HIDE_FROM_ABI iter_type + __do_get_signed(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Signed& __v) const { + // Stage 1 + int __base = this->__get_base(__iob); + // Stage 2 + char_type __thousands_sep; + const int __atoms_size = __num_get_base::__int_chr_cnt; + char_type __atoms1[__atoms_size]; + const char_type* __atoms = this->__do_widen(__iob, __atoms1); + string __grouping = this->__stage2_int_prep(__iob, __thousands_sep); + string __buf; + __buf.resize(__buf.capacity()); + char* __a = &__buf[0]; + char* __a_end = __a; + unsigned __g[__num_get_base::__num_get_buf_sz]; + unsigned* __g_end = __g; + unsigned __dc = 0; + for (; __b != __e; ++__b) { + if (__a_end == __a + __buf.size()) { + size_t __tmp = __buf.size(); + __buf.resize(2 * __buf.size()); + __buf.resize(__buf.capacity()); + __a = &__buf[0]; + __a_end = __a + __tmp; + } + if (this->__stage2_int_loop( + *__b, + __base, + __a, + __a_end, + __dc, + __thousands_sep, + __grouping, + __g, + __g_end, + const_cast(__atoms))) + break; + } + if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz) + *__g_end++ = __dc; + // Stage 3 + __v = std::__num_get_signed_integral<_Signed>(__a, __a_end, __err, __base); + // Digit grouping checked + __check_grouping(__grouping, __g, __g_end, __err); + // EOF checked + if (__b == __e) + __err |= ios_base::eofbit; + return __b; + } + + template + _LIBCPP_HIDE_FROM_ABI iter_type + __do_get_unsigned(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Unsigned& __v) const { + // Stage 1 + int __base = this->__get_base(__iob); + // Stage 2 + char_type __thousands_sep; + const int __atoms_size = __num_get_base::__int_chr_cnt; + char_type __atoms1[__atoms_size]; + const char_type* __atoms = this->__do_widen(__iob, __atoms1); + string __grouping = this->__stage2_int_prep(__iob, __thousands_sep); + string __buf; + __buf.resize(__buf.capacity()); + char* __a = &__buf[0]; + char* __a_end = __a; + unsigned __g[__num_get_base::__num_get_buf_sz]; + unsigned* __g_end = __g; + unsigned __dc = 0; + for (; __b != __e; ++__b) { + if (__a_end == __a + __buf.size()) { + size_t __tmp = __buf.size(); + __buf.resize(2 * __buf.size()); + __buf.resize(__buf.capacity()); + __a = &__buf[0]; + __a_end = __a + __tmp; + } + if (this->__stage2_int_loop( + *__b, + __base, + __a, + __a_end, + __dc, + __thousands_sep, + __grouping, + __g, + __g_end, + const_cast(__atoms))) + break; + } + if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz) + *__g_end++ = __dc; + // Stage 3 + __v = std::__num_get_unsigned_integral<_Unsigned>(__a, __a_end, __err, __base); + // Digit grouping checked + __check_grouping(__grouping, __g, __g_end, __err); + // EOF checked + if (__b == __e) + __err |= ios_base::eofbit; + return __b; + } + + virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const; + + virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long& __v) const { + return this->__do_get_signed(__b, __e, __iob, __err, __v); + } + + virtual iter_type + do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long long& __v) const { + return this->__do_get_signed(__b, __e, __iob, __err, __v); + } + + virtual iter_type + do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned short& __v) const { + return this->__do_get_unsigned(__b, __e, __iob, __err, __v); + } + + virtual iter_type + do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned int& __v) const { + return this->__do_get_unsigned(__b, __e, __iob, __err, __v); + } + + virtual iter_type + do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long& __v) const { + return this->__do_get_unsigned(__b, __e, __iob, __err, __v); + } + + virtual iter_type + do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long long& __v) const { + return this->__do_get_unsigned(__b, __e, __iob, __err, __v); + } + + virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, float& __v) const { + return this->__do_get_floating_point(__b, __e, __iob, __err, __v); + } + + virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, double& __v) const { + return this->__do_get_floating_point(__b, __e, __iob, __err, __v); + } + + virtual iter_type + do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { + return this->__do_get_floating_point(__b, __e, __iob, __err, __v); + } + + virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const; +}; + +template +locale::id num_get<_CharT, _InputIterator>::id; + +template +_InputIterator num_get<_CharT, _InputIterator>::do_get( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const { + if ((__iob.flags() & ios_base::boolalpha) == 0) { + long __lv = -1; + __b = do_get(__b, __e, __iob, __err, __lv); + switch (__lv) { + case 0: + __v = false; + break; + case 1: + __v = true; + break; + default: + __v = true; + __err = ios_base::failbit; + break; + } + return __b; + } + const ctype<_CharT>& __ct = std::use_facet >(__iob.getloc()); + const numpunct<_CharT>& __np = std::use_facet >(__iob.getloc()); + typedef typename numpunct<_CharT>::string_type string_type; + const string_type __names[2] = {__np.truename(), __np.falsename()}; + const string_type* __i = std::__scan_keyword(__b, __e, __names, __names + 2, __ct, __err); + __v = __i == __names; + return __b; +} + +template +_InputIterator num_get<_CharT, _InputIterator>::do_get( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const { + // Stage 1 + int __base = 16; + // Stage 2 + char_type __atoms[__num_get_base::__int_chr_cnt]; + char_type __thousands_sep = char_type(); + string __grouping; + std::use_facet >(__iob.getloc()) + .widen(__num_get_base::__src, __num_get_base::__src + __num_get_base::__int_chr_cnt, __atoms); + string __buf; + __buf.resize(__buf.capacity()); + char* __a = &__buf[0]; + char* __a_end = __a; + unsigned __g[__num_get_base::__num_get_buf_sz]; + unsigned* __g_end = __g; + unsigned __dc = 0; + for (; __b != __e; ++__b) { + if (__a_end == __a + __buf.size()) { + size_t __tmp = __buf.size(); + __buf.resize(2 * __buf.size()); + __buf.resize(__buf.capacity()); + __a = &__buf[0]; + __a_end = __a + __tmp; + } + if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc, __thousands_sep, __grouping, __g, __g_end, __atoms)) + break; + } + // Stage 3 + __buf.resize(__a_end - __a); + if (__locale::__sscanf(__buf.c_str(), _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1) + __err = ios_base::failbit; + // EOF checked + if (__b == __e) + __err |= ios_base::eofbit; + return __b; +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get; +# endif + +struct _LIBCPP_EXPORTED_FROM_ABI __num_put_base { +protected: + static void __format_int(char* __fmt, const char* __len, bool __signd, ios_base::fmtflags __flags); + static bool __format_float(char* __fmt, const char* __len, ios_base::fmtflags __flags); + static char* __identify_padding(char* __nb, char* __ne, const ios_base& __iob); +}; + +template +struct __num_put : protected __num_put_base { + static void __widen_and_group_int( + char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc); + static void __widen_and_group_float( + char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc); +}; + +template +void __num_put<_CharT>::__widen_and_group_int( + char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc) { + const ctype<_CharT>& __ct = std::use_facet >(__loc); + const numpunct<_CharT>& __npt = std::use_facet >(__loc); + string __grouping = __npt.grouping(); + if (__grouping.empty()) { + __ct.widen(__nb, __ne, __ob); + __oe = __ob + (__ne - __nb); + } else { + __oe = __ob; + char* __nf = __nb; + if (*__nf == '-' || *__nf == '+') + *__oe++ = __ct.widen(*__nf++); + if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' || __nf[1] == 'X')) { + *__oe++ = __ct.widen(*__nf++); + *__oe++ = __ct.widen(*__nf++); + } + std::reverse(__nf, __ne); + _CharT __thousands_sep = __npt.thousands_sep(); + unsigned __dc = 0; + unsigned __dg = 0; + for (char* __p = __nf; __p < __ne; ++__p) { + if (static_cast(__grouping[__dg]) > 0 && __dc == static_cast(__grouping[__dg])) { + *__oe++ = __thousands_sep; + __dc = 0; + if (__dg < __grouping.size() - 1) + ++__dg; + } + *__oe++ = __ct.widen(*__p); + ++__dc; + } + std::reverse(__ob + (__nf - __nb), __oe); + } + if (__np == __ne) + __op = __oe; + else + __op = __ob + (__np - __nb); +} + +template +void __num_put<_CharT>::__widen_and_group_float( + char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc) { + const ctype<_CharT>& __ct = std::use_facet >(__loc); + const numpunct<_CharT>& __npt = std::use_facet >(__loc); + string __grouping = __npt.grouping(); + __oe = __ob; + char* __nf = __nb; + if (*__nf == '-' || *__nf == '+') + *__oe++ = __ct.widen(*__nf++); + char* __ns; + if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' || __nf[1] == 'X')) { + *__oe++ = __ct.widen(*__nf++); + *__oe++ = __ct.widen(*__nf++); + for (__ns = __nf; __ns < __ne; ++__ns) + if (!__locale::__isxdigit(*__ns, _LIBCPP_GET_C_LOCALE)) + break; + } else { + for (__ns = __nf; __ns < __ne; ++__ns) + if (!__locale::__isdigit(*__ns, _LIBCPP_GET_C_LOCALE)) + break; + } + if (__grouping.empty()) { + __ct.widen(__nf, __ns, __oe); + __oe += __ns - __nf; + } else { + std::reverse(__nf, __ns); + _CharT __thousands_sep = __npt.thousands_sep(); + unsigned __dc = 0; + unsigned __dg = 0; + for (char* __p = __nf; __p < __ns; ++__p) { + if (__grouping[__dg] > 0 && __dc == static_cast(__grouping[__dg])) { + *__oe++ = __thousands_sep; + __dc = 0; + if (__dg < __grouping.size() - 1) + ++__dg; + } + *__oe++ = __ct.widen(*__p); + ++__dc; + } + std::reverse(__ob + (__nf - __nb), __oe); + } + for (__nf = __ns; __nf < __ne; ++__nf) { + if (*__nf == '.') { + *__oe++ = __npt.decimal_point(); + ++__nf; + break; + } else + *__oe++ = __ct.widen(*__nf); + } + __ct.widen(__nf, __ne, __oe); + __oe += __ne - __nf; + if (__np == __ne) + __op = __oe; + else + __op = __ob + (__np - __nb); +} + +extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put; +# endif + +template > +class num_put : public locale::facet, private __num_put<_CharT> { +public: + typedef _CharT char_type; + typedef _OutputIterator iter_type; + + _LIBCPP_HIDE_FROM_ABI explicit num_put(size_t __refs = 0) : locale::facet(__refs) {} + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const { + return do_put(__s, __iob, __fl, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long __v) const { + return do_put(__s, __iob, __fl, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const { + return do_put(__s, __iob, __fl, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long __v) const { + return do_put(__s, __iob, __fl, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long __v) const { + return do_put(__s, __iob, __fl, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, double __v) const { + return do_put(__s, __iob, __fl, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const { + return do_put(__s, __iob, __fl, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const { + return do_put(__s, __iob, __fl, __v); + } + + static locale::id id; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~num_put() override {} + + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const; + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, long __v) const; + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const; + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long) const; + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long) const; + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, double __v) const; + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const; + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const; + + template + _LIBCPP_HIDE_FROM_ABI inline _OutputIterator + __do_put_integral(iter_type __s, ios_base& __iob, char_type __fl, _Integral __v) const; + + template + _LIBCPP_HIDE_FROM_ABI inline _OutputIterator + __do_put_floating_point(iter_type __s, ios_base& __iob, char_type __fl, _Float __v, char const* __len) const; +}; + +template +locale::id num_put<_CharT, _OutputIterator>::id; + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const { + if ((__iob.flags() & ios_base::boolalpha) == 0) + return do_put(__s, __iob, __fl, (unsigned long)__v); + const numpunct& __np = std::use_facet >(__iob.getloc()); + typedef typename numpunct::string_type string_type; + string_type __nm = __v ? __np.truename() : __np.falsename(); + for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s) + *__s = *__i; + return __s; +} + +template +template +_LIBCPP_HIDE_FROM_ABI inline _OutputIterator num_put<_CharT, _OutputIterator>::__do_put_integral( + iter_type __s, ios_base& __iob, char_type __fl, _Integral __v) const { + // Stage 1 - Get number in narrow char + + // Worst case is octal, with showbase enabled. Note that octal is always + // printed as an unsigned value. + using _Unsigned = typename make_unsigned<_Integral>::type; + _LIBCPP_CONSTEXPR const unsigned __buffer_size = + (numeric_limits<_Unsigned>::digits / 3) // 1 char per 3 bits + + ((numeric_limits<_Unsigned>::digits % 3) != 0) // round up + + 2; // base prefix + terminating null character + + char __char_buffer[__buffer_size]; + char* __buffer_ptr = __char_buffer; + + auto __flags = __iob.flags(); + + auto __basefield = (__flags & ios_base::basefield); + + // Extract base + int __base = 10; + if (__basefield == ios_base::oct) + __base = 8; + else if (__basefield == ios_base::hex) + __base = 16; + + // Print '-' and make the argument unsigned + auto __uval = std::__to_unsigned_like(__v); + if (__basefield != ios_base::oct && __basefield != ios_base::hex && __v < 0) { + *__buffer_ptr++ = '-'; + __uval = std::__complement(__uval); + } + + // Maybe add '+' prefix + if (std::is_signed<_Integral>::value && (__flags & ios_base::showpos) && __basefield != ios_base::oct && + __basefield != ios_base::hex && __v >= 0) + *__buffer_ptr++ = '+'; + + // Add base prefix + if (__v != 0 && __flags & ios_base::showbase) { + if (__basefield == ios_base::oct) { + *__buffer_ptr++ = '0'; + } else if (__basefield == ios_base::hex) { + *__buffer_ptr++ = '0'; + *__buffer_ptr++ = (__flags & ios_base::uppercase ? 'X' : 'x'); + } + } + + auto __res = std::__to_chars_integral(__buffer_ptr, __char_buffer + __buffer_size, __uval, __base); + _LIBCPP_ASSERT_INTERNAL(__res.__ec == std::errc(0), "to_chars: invalid maximum buffer size computed?"); + + // Make letters uppercase + if (__flags & ios_base::hex && __flags & ios_base::uppercase) { + for (; __buffer_ptr != __res.__ptr; ++__buffer_ptr) + *__buffer_ptr = std::__hex_to_upper(*__buffer_ptr); + } + + char* __np = this->__identify_padding(__char_buffer, __res.__ptr, __iob); + // Stage 2 - Widen __nar while adding thousands separators + char_type __o[2 * (__buffer_size - 1) - 1]; + char_type* __op; // pad here + char_type* __oe; // end of output + this->__widen_and_group_int(__char_buffer, __np, __res.__ptr, __o, __op, __oe, __iob.getloc()); + // [__o, __oe) contains thousands_sep'd wide number + // Stage 3 & 4 + return std::__pad_and_output(__s, __o, __op, __oe, __iob, __fl); +} + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, long __v) const { + return this->__do_put_integral(__s, __iob, __fl, __v); +} + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const { + return this->__do_put_integral(__s, __iob, __fl, __v); +} + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long __v) const { + return this->__do_put_integral(__s, __iob, __fl, __v); +} + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long __v) const { + return this->__do_put_integral(__s, __iob, __fl, __v); +} + +template +template +_LIBCPP_HIDE_FROM_ABI inline _OutputIterator num_put<_CharT, _OutputIterator>::__do_put_floating_point( + iter_type __s, ios_base& __iob, char_type __fl, _Float __v, char const* __len) const { + // Stage 1 - Get number in narrow char + char __fmt[8] = {'%', 0}; + bool __specify_precision = this->__format_float(__fmt + 1, __len, __iob.flags()); + const unsigned __nbuf = 30; + char __nar[__nbuf]; + char* __nb = __nar; + int __nc; + _LIBCPP_DIAGNOSTIC_PUSH + _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral") + _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wformat-nonliteral") + if (__specify_precision) + __nc = __locale::__snprintf(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v); + else + __nc = __locale::__snprintf(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v); + unique_ptr __nbh(nullptr, free); + if (__nc > static_cast(__nbuf - 1)) { + if (__specify_precision) + __nc = __locale::__asprintf(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v); + else + __nc = __locale::__asprintf(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v); + if (__nc == -1) + std::__throw_bad_alloc(); + __nbh.reset(__nb); + } + _LIBCPP_DIAGNOSTIC_POP + char* __ne = __nb + __nc; + char* __np = this->__identify_padding(__nb, __ne, __iob); + // Stage 2 - Widen __nar while adding thousands separators + char_type __o[2 * (__nbuf - 1) - 1]; + char_type* __ob = __o; + unique_ptr __obh(0, free); + if (__nb != __nar) { + __ob = (char_type*)malloc(2 * static_cast(__nc) * sizeof(char_type)); + if (__ob == 0) + std::__throw_bad_alloc(); + __obh.reset(__ob); + } + char_type* __op; // pad here + char_type* __oe; // end of output + this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc()); + // [__o, __oe) contains thousands_sep'd wide number + // Stage 3 & 4 + __s = std::__pad_and_output(__s, __ob, __op, __oe, __iob, __fl); + return __s; +} + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, double __v) const { + return this->__do_put_floating_point(__s, __iob, __fl, __v, ""); +} + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const { + return this->__do_put_floating_point(__s, __iob, __fl, __v, "L"); +} + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const { + auto __flags = __iob.flags(); + __iob.flags((__flags & ~ios_base::basefield & ~ios_base::uppercase) | ios_base::hex | ios_base::showbase); + auto __res = __do_put_integral(__s, __iob, __fl, reinterpret_cast(__v)); + __iob.flags(__flags); + return __res; +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put; +# endif + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +// NOLINTEND(libcpp-robust-against-adl) + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_NUM_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/scan_keyword.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/scan_keyword.h new file mode 100644 index 0000000000..78dd0a46a8 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/scan_keyword.h @@ -0,0 +1,143 @@ +//===----------------------------------------------------------------------===// +// +// 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___LOCALE_DIR_SCAN_KEYWORD_H +#define _LIBCPP___LOCALE_DIR_SCAN_KEYWORD_H + +#include <__config> +#include <__memory/unique_ptr.h> +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// __scan_keyword +// Scans [__b, __e) until a match is found in the basic_strings range +// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke). +// __b will be incremented (visibly), consuming CharT until a match is found +// or proved to not exist. A keyword may be "", in which will match anything. +// If one keyword is a prefix of another, and the next CharT in the input +// might match another keyword, the algorithm will attempt to find the longest +// matching keyword. If the longer matching keyword ends up not matching, then +// no keyword match is found. If no keyword match is found, __ke is returned +// and failbit is set in __err. +// Else an iterator pointing to the matching keyword is found. If more than +// one keyword matches, an iterator to the first matching keyword is returned. +// If on exit __b == __e, eofbit is set in __err. If __case_sensitive is false, +// __ct is used to force to lower case before comparing characters. +// Examples: +// Keywords: "a", "abb" +// If the input is "a", the first keyword matches and eofbit is set. +// If the input is "abc", no match is found and "ab" are consumed. +template +_LIBCPP_HIDE_FROM_ABI _ForwardIterator __scan_keyword( + _InputIterator& __b, + _InputIterator __e, + _ForwardIterator __kb, + _ForwardIterator __ke, + const _Ctype& __ct, + ios_base::iostate& __err, + bool __case_sensitive = true) { + typedef typename iterator_traits<_InputIterator>::value_type _CharT; + size_t __nkw = static_cast(std::distance(__kb, __ke)); + const unsigned char __doesnt_match = '\0'; + const unsigned char __might_match = '\1'; + const unsigned char __does_match = '\2'; + unsigned char __statbuf[100]; + unsigned char* __status = __statbuf; + unique_ptr __stat_hold(nullptr, free); + if (__nkw > sizeof(__statbuf)) { + __status = (unsigned char*)malloc(__nkw); + if (__status == nullptr) + std::__throw_bad_alloc(); + __stat_hold.reset(__status); + } + size_t __n_might_match = __nkw; // At this point, any keyword might match + size_t __n_does_match = 0; // but none of them definitely do + // Initialize all statuses to __might_match, except for "" keywords are __does_match + unsigned char* __st = __status; + for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void)++__st) { + if (!__ky->empty()) + *__st = __might_match; + else { + *__st = __does_match; + --__n_might_match; + ++__n_does_match; + } + } + // While there might be a match, test keywords against the next CharT + for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx) { + // Peek at the next CharT but don't consume it + _CharT __c = *__b; + if (!__case_sensitive) + __c = __ct.toupper(__c); + bool __consume = false; + // For each keyword which might match, see if the __indx character is __c + // If a match if found, consume __c + // If a match is found, and that is the last character in the keyword, + // then that keyword matches. + // If the keyword doesn't match this character, then change the keyword + // to doesn't match + __st = __status; + for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void)++__st) { + if (*__st == __might_match) { + _CharT __kc = (*__ky)[__indx]; + if (!__case_sensitive) + __kc = __ct.toupper(__kc); + if (__c == __kc) { + __consume = true; + if (__ky->size() == __indx + 1) { + *__st = __does_match; + --__n_might_match; + ++__n_does_match; + } + } else { + *__st = __doesnt_match; + --__n_might_match; + } + } + } + // consume if we matched a character + if (__consume) { + ++__b; + // If we consumed a character and there might be a matched keyword that + // was marked matched on a previous iteration, then such keywords + // which are now marked as not matching. + if (__n_might_match + __n_does_match > 1) { + __st = __status; + for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void)++__st) { + if (*__st == __does_match && __ky->size() != __indx + 1) { + *__st = __doesnt_match; + --__n_does_match; + } + } + } + } + } + // We've exited the loop because we hit eof and/or we have no more "might matches". + if (__b == __e) + __err |= ios_base::eofbit; + // Return the first matching result + for (__st = __status; __kb != __ke; ++__kb, (void)++__st) + if (*__st == __does_match) + break; + if (__kb == __ke) + __err |= ios_base::failbit; + return __kb; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_SCAN_KEYWORD_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/support/bsd_like.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/support/bsd_like.h index 54eb397358..ac40292470 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/support/bsd_like.h +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/support/bsd_like.h @@ -89,12 +89,6 @@ __strtoull(const char* __nptr, char** __endptr, int __base, __locale_t __loc) { // // Character manipulation functions // -#if defined(_LIBCPP_BUILDING_LIBRARY) -inline _LIBCPP_HIDE_FROM_ABI int __islower(int __c, __locale_t __loc) { return ::islower_l(__c, __loc); } - -inline _LIBCPP_HIDE_FROM_ABI int __isupper(int __c, __locale_t __loc) { return ::isupper_l(__c, __loc); } -#endif - inline _LIBCPP_HIDE_FROM_ABI int __isdigit(int __c, __locale_t __loc) { return ::isdigit_l(__c, __loc); } inline _LIBCPP_HIDE_FROM_ABI int __isxdigit(int __c, __locale_t __loc) { return ::isxdigit_l(__c, __loc); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/support/linux.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/support/linux.h index fa0b03c646..23bcf44c31 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/support/linux.h +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/support/linux.h @@ -116,12 +116,6 @@ __strtoull(const char* __nptr, char** __endptr, int __base, __locale_t __loc) { // // Character manipulation functions // -#if defined(_LIBCPP_BUILDING_LIBRARY) -inline _LIBCPP_HIDE_FROM_ABI int __islower(int __c, __locale_t __loc) { return islower_l(__c, __loc); } - -inline _LIBCPP_HIDE_FROM_ABI int __isupper(int __c, __locale_t __loc) { return isupper_l(__c, __loc); } -#endif - inline _LIBCPP_HIDE_FROM_ABI int __isdigit(int __c, __locale_t __loc) { return isdigit_l(__c, __loc); } inline _LIBCPP_HIDE_FROM_ABI int __isxdigit(int __c, __locale_t __loc) { return isxdigit_l(__c, __loc); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/support/no_locale/characters.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/support/no_locale/characters.h index 4fb48ed9ce..1281b8bd13 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/support/no_locale/characters.h +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/support/no_locale/characters.h @@ -29,12 +29,6 @@ namespace __locale { // // Character manipulation functions // -#if defined(_LIBCPP_BUILDING_LIBRARY) -inline _LIBCPP_HIDE_FROM_ABI int __islower(int __c, __locale_t) { return std::islower(__c); } - -inline _LIBCPP_HIDE_FROM_ABI int __isupper(int __c, __locale_t) { return std::isupper(__c); } -#endif - inline _LIBCPP_HIDE_FROM_ABI int __isdigit(int __c, __locale_t) { return std::isdigit(__c); } inline _LIBCPP_HIDE_FROM_ABI int __isxdigit(int __c, __locale_t) { return std::isxdigit(__c); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/support/windows.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/support/windows.h index 0d3089c150..0df8709f11 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/support/windows.h +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/support/windows.h @@ -197,12 +197,6 @@ __strtoull(const char* __nptr, char** __endptr, int __base, __locale_t __loc) { // // Character manipulation functions // -#if defined(_LIBCPP_BUILDING_LIBRARY) -inline _LIBCPP_HIDE_FROM_ABI int __islower(int __c, __locale_t __loc) { return _islower_l(__c, __loc); } - -inline _LIBCPP_HIDE_FROM_ABI int __isupper(int __c, __locale_t __loc) { return _isupper_l(__c, __loc); } -#endif - inline _LIBCPP_HIDE_FROM_ABI int __isdigit(int __c, __locale_t __loc) { return _isdigit_l(__c, __loc); } inline _LIBCPP_HIDE_FROM_ABI int __isxdigit(int __c, __locale_t __loc) { return _isxdigit_l(__c, __loc); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/time.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/time.h new file mode 100644 index 0000000000..5f60d5f36b --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/time.h @@ -0,0 +1,766 @@ +//===----------------------------------------------------------------------===// +// +// 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___LOCALE_DIR_TIME_H +#define _LIBCPP___LOCALE_DIR_TIME_H + +#include <__algorithm/copy.h> +#include <__config> +#include <__locale_dir/get_c_locale.h> +#include <__locale_dir/scan_keyword.h> +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI int __get_up_to_n_digits( + _InputIterator& __b, _InputIterator __e, ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n) { + // Precondition: __n >= 1 + if (__b == __e) { + __err |= ios_base::eofbit | ios_base::failbit; + return 0; + } + // get first digit + _CharT __c = *__b; + if (!__ct.is(ctype_base::digit, __c)) { + __err |= ios_base::failbit; + return 0; + } + int __r = __ct.narrow(__c, 0) - '0'; + for (++__b, (void)--__n; __b != __e && __n > 0; ++__b, (void)--__n) { + // get next digit + __c = *__b; + if (!__ct.is(ctype_base::digit, __c)) + return __r; + __r = __r * 10 + __ct.narrow(__c, 0) - '0'; + } + if (__b == __e) + __err |= ios_base::eofbit; + return __r; +} + +class _LIBCPP_EXPORTED_FROM_ABI time_base { +public: + enum dateorder { no_order, dmy, mdy, ymd, ydm }; +}; + +template +class __time_get_c_storage { +protected: + typedef basic_string<_CharT> string_type; + + virtual const string_type* __weeks() const; + virtual const string_type* __months() const; + virtual const string_type* __am_pm() const; + virtual const string_type& __c() const; + virtual const string_type& __r() const; + virtual const string_type& __x() const; + virtual const string_type& __X() const; + + _LIBCPP_HIDE_FROM_ABI ~__time_get_c_storage() {} +}; + +template <> +_LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage::__weeks() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage::__months() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage::__am_pm() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage::__c() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage::__r() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage::__x() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage::__X() const; + +# if _LIBCPP_HAS_WIDE_CHARACTERS +template <> +_LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage::__weeks() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage::__months() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage::__am_pm() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage::__c() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage::__r() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage::__x() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage::__X() const; +# endif + +template > +class time_get : public locale::facet, public time_base, private __time_get_c_storage<_CharT> { +public: + typedef _CharT char_type; + typedef _InputIterator iter_type; + typedef time_base::dateorder dateorder; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI explicit time_get(size_t __refs = 0) : locale::facet(__refs) {} + + _LIBCPP_HIDE_FROM_ABI dateorder date_order() const { return this->do_date_order(); } + + _LIBCPP_HIDE_FROM_ABI iter_type + get_time(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + return do_get_time(__b, __e, __iob, __err, __tm); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get_date(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + return do_get_date(__b, __e, __iob, __err, __tm); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get_weekday(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + return do_get_weekday(__b, __e, __iob, __err, __tm); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get_monthname(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + return do_get_monthname(__b, __e, __iob, __err, __tm); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get_year(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + return do_get_year(__b, __e, __iob, __err, __tm); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm, char __fmt, char __mod = 0) + const { + return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod); + } + + iter_type + get(iter_type __b, + iter_type __e, + ios_base& __iob, + ios_base::iostate& __err, + tm* __tm, + const char_type* __fmtb, + const char_type* __fmte) const; + + static locale::id id; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_get() override {} + + virtual dateorder do_date_order() const; + virtual iter_type + do_get_time(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const; + virtual iter_type + do_get_date(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const; + virtual iter_type + do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const; + virtual iter_type + do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const; + virtual iter_type + do_get_year(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const; + virtual iter_type do_get( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm, char __fmt, char __mod) const; + +private: + void __get_white_space(iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + + void __get_weekdayname( + int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void __get_monthname( + int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void __get_day(int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_month(int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_year(int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_year4(int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_hour(int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_12_hour(int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_am_pm(int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_minute(int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_second(int& __s, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_weekday(int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void __get_day_year_num( + int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; +}; + +template +locale::id time_get<_CharT, _InputIterator>::id; + +// time_get primitives + +template +void time_get<_CharT, _InputIterator>::__get_weekdayname( + int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + // Note: ignoring case comes from the POSIX strptime spec + const string_type* __wk = this->__weeks(); + ptrdiff_t __i = std::__scan_keyword(__b, __e, __wk, __wk + 14, __ct, __err, false) - __wk; + if (__i < 14) + __w = __i % 7; +} + +template +void time_get<_CharT, _InputIterator>::__get_monthname( + int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + // Note: ignoring case comes from the POSIX strptime spec + const string_type* __month = this->__months(); + ptrdiff_t __i = std::__scan_keyword(__b, __e, __month, __month + 24, __ct, __err, false) - __month; + if (__i < 24) + __m = __i % 12; +} + +template +void time_get<_CharT, _InputIterator>::__get_day( + int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); + if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31) + __d = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_month( + int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1; + if (!(__err & ios_base::failbit) && 0 <= __t && __t <= 11) + __m = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_year( + int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 4); + if (!(__err & ios_base::failbit)) { + if (__t < 69) + __t += 2000; + else if (69 <= __t && __t <= 99) + __t += 1900; + __y = __t - 1900; + } +} + +template +void time_get<_CharT, _InputIterator>::__get_year4( + int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 4); + if (!(__err & ios_base::failbit)) + __y = __t - 1900; +} + +template +void time_get<_CharT, _InputIterator>::__get_hour( + int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); + if (!(__err & ios_base::failbit) && __t <= 23) + __h = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_12_hour( + int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); + if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12) + __h = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_minute( + int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); + if (!(__err & ios_base::failbit) && __t <= 59) + __m = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_second( + int& __s, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); + if (!(__err & ios_base::failbit) && __t <= 60) + __s = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_weekday( + int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 1); + if (!(__err & ios_base::failbit) && __t <= 6) + __w = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_day_year_num( + int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 3); + if (!(__err & ios_base::failbit) && __t <= 365) + __d = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_white_space( + iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b) + ; + if (__b == __e) + __err |= ios_base::eofbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_am_pm( + int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + const string_type* __ap = this->__am_pm(); + if (__ap[0].size() + __ap[1].size() == 0) { + __err |= ios_base::failbit; + return; + } + ptrdiff_t __i = std::__scan_keyword(__b, __e, __ap, __ap + 2, __ct, __err, false) - __ap; + if (__i == 0 && __h == 12) + __h = 0; + else if (__i == 1 && __h < 12) + __h += 12; +} + +template +void time_get<_CharT, _InputIterator>::__get_percent( + iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + if (__b == __e) { + __err |= ios_base::eofbit | ios_base::failbit; + return; + } + if (__ct.narrow(*__b, 0) != '%') + __err |= ios_base::failbit; + else if (++__b == __e) + __err |= ios_base::eofbit; +} + +// time_get end primitives + +template +_InputIterator time_get<_CharT, _InputIterator>::get( + iter_type __b, + iter_type __e, + ios_base& __iob, + ios_base::iostate& __err, + tm* __tm, + const char_type* __fmtb, + const char_type* __fmte) const { + const ctype& __ct = std::use_facet >(__iob.getloc()); + __err = ios_base::goodbit; + while (__fmtb != __fmte && __err == ios_base::goodbit) { + if (__b == __e) { + __err = ios_base::failbit; + break; + } + if (__ct.narrow(*__fmtb, 0) == '%') { + if (++__fmtb == __fmte) { + __err = ios_base::failbit; + break; + } + char __cmd = __ct.narrow(*__fmtb, 0); + char __opt = '\0'; + if (__cmd == 'E' || __cmd == '0') { + if (++__fmtb == __fmte) { + __err = ios_base::failbit; + break; + } + __opt = __cmd; + __cmd = __ct.narrow(*__fmtb, 0); + } + __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt); + ++__fmtb; + } else if (__ct.is(ctype_base::space, *__fmtb)) { + for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb) + ; + for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b) + ; + } else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb)) { + ++__b; + ++__fmtb; + } else + __err = ios_base::failbit; + } + if (__b == __e) + __err |= ios_base::eofbit; + return __b; +} + +template +typename time_get<_CharT, _InputIterator>::dateorder time_get<_CharT, _InputIterator>::do_date_order() const { + return mdy; +} + +template +_InputIterator time_get<_CharT, _InputIterator>::do_get_time( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'}; + return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt) / sizeof(__fmt[0])); +} + +template +_InputIterator time_get<_CharT, _InputIterator>::do_get_date( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + const string_type& __fmt = this->__x(); + return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size()); +} + +template +_InputIterator time_get<_CharT, _InputIterator>::do_get_weekday( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + const ctype& __ct = std::use_facet >(__iob.getloc()); + __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct); + return __b; +} + +template +_InputIterator time_get<_CharT, _InputIterator>::do_get_monthname( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + const ctype& __ct = std::use_facet >(__iob.getloc()); + __get_monthname(__tm->tm_mon, __b, __e, __err, __ct); + return __b; +} + +template +_InputIterator time_get<_CharT, _InputIterator>::do_get_year( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + const ctype& __ct = std::use_facet >(__iob.getloc()); + __get_year(__tm->tm_year, __b, __e, __err, __ct); + return __b; +} + +template +_InputIterator time_get<_CharT, _InputIterator>::do_get( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm, char __fmt, char) const { + __err = ios_base::goodbit; + const ctype& __ct = std::use_facet >(__iob.getloc()); + switch (__fmt) { + case 'a': + case 'A': + __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct); + break; + case 'b': + case 'B': + case 'h': + __get_monthname(__tm->tm_mon, __b, __e, __err, __ct); + break; + case 'c': { + const string_type& __fm = this->__c(); + __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size()); + } break; + case 'd': + case 'e': + __get_day(__tm->tm_mday, __b, __e, __err, __ct); + break; + case 'D': { + const char_type __fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'}; + __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0])); + } break; + case 'F': { + const char_type __fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'}; + __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0])); + } break; + case 'H': + __get_hour(__tm->tm_hour, __b, __e, __err, __ct); + break; + case 'I': + __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct); + break; + case 'j': + __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct); + break; + case 'm': + __get_month(__tm->tm_mon, __b, __e, __err, __ct); + break; + case 'M': + __get_minute(__tm->tm_min, __b, __e, __err, __ct); + break; + case 'n': + case 't': + __get_white_space(__b, __e, __err, __ct); + break; + case 'p': + __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct); + break; + case 'r': { + const char_type __fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'}; + __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0])); + } break; + case 'R': { + const char_type __fm[] = {'%', 'H', ':', '%', 'M'}; + __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0])); + } break; + case 'S': + __get_second(__tm->tm_sec, __b, __e, __err, __ct); + break; + case 'T': { + const char_type __fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'}; + __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0])); + } break; + case 'w': + __get_weekday(__tm->tm_wday, __b, __e, __err, __ct); + break; + case 'x': + return do_get_date(__b, __e, __iob, __err, __tm); + case 'X': { + const string_type& __fm = this->__X(); + __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size()); + } break; + case 'y': + __get_year(__tm->tm_year, __b, __e, __err, __ct); + break; + case 'Y': + __get_year4(__tm->tm_year, __b, __e, __err, __ct); + break; + case '%': + __get_percent(__b, __e, __err, __ct); + break; + default: + __err |= ios_base::failbit; + } + return __b; +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get; +# endif + +class _LIBCPP_EXPORTED_FROM_ABI __time_get { +protected: + __locale::__locale_t __loc_; + + __time_get(const char* __nm); + __time_get(const string& __nm); + ~__time_get(); +}; + +template +class __time_get_storage : public __time_get { +protected: + typedef basic_string<_CharT> string_type; + + string_type __weeks_[14]; + string_type __months_[24]; + string_type __am_pm_[2]; + string_type __c_; + string_type __r_; + string_type __x_; + string_type __X_; + + explicit __time_get_storage(const char* __nm); + explicit __time_get_storage(const string& __nm); + + _LIBCPP_HIDE_FROM_ABI ~__time_get_storage() {} + + time_base::dateorder __do_date_order() const; + +private: + void init(const ctype<_CharT>&); + string_type __analyze(char __fmt, const ctype<_CharT>&); +}; + +# define _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(_CharT) \ + template <> \ + _LIBCPP_EXPORTED_FROM_ABI time_base::dateorder __time_get_storage<_CharT>::__do_date_order() const; \ + template <> \ + _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const char*); \ + template <> \ + _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const string&); \ + template <> \ + _LIBCPP_EXPORTED_FROM_ABI void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \ + template <> \ + _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::string_type __time_get_storage<_CharT>::__analyze( \ + char, const ctype<_CharT>&); \ + extern template _LIBCPP_EXPORTED_FROM_ABI time_base::dateorder __time_get_storage<_CharT>::__do_date_order() \ + const; \ + extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const char*); \ + extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const string&); \ + extern template _LIBCPP_EXPORTED_FROM_ABI void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \ + extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::string_type \ + __time_get_storage<_CharT>::__analyze(char, const ctype<_CharT>&); + +_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(char) +# if _LIBCPP_HAS_WIDE_CHARACTERS +_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(wchar_t) +# endif +# undef _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION + +template > +class time_get_byname : public time_get<_CharT, _InputIterator>, private __time_get_storage<_CharT> { +public: + typedef time_base::dateorder dateorder; + typedef _InputIterator iter_type; + typedef _CharT char_type; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI explicit time_get_byname(const char* __nm, size_t __refs = 0) + : time_get<_CharT, _InputIterator>(__refs), __time_get_storage<_CharT>(__nm) {} + _LIBCPP_HIDE_FROM_ABI explicit time_get_byname(const string& __nm, size_t __refs = 0) + : time_get<_CharT, _InputIterator>(__refs), __time_get_storage<_CharT>(__nm) {} + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_get_byname() override {} + + _LIBCPP_HIDE_FROM_ABI_VIRTUAL dateorder do_date_order() const override { return this->__do_date_order(); } + +private: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type* __weeks() const override { return this->__weeks_; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type* __months() const override { return this->__months_; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type* __am_pm() const override { return this->__am_pm_; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __c() const override { return this->__c_; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __r() const override { return this->__r_; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __x() const override { return this->__x_; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __X() const override { return this->__X_; } +}; + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname; +# endif + +class _LIBCPP_EXPORTED_FROM_ABI __time_put { + __locale::__locale_t __loc_; + +protected: + _LIBCPP_HIDE_FROM_ABI __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {} + __time_put(const char* __nm); + __time_put(const string& __nm); + ~__time_put(); + void __do_put(char* __nb, char*& __ne, const tm* __tm, char __fmt, char __mod) const; +# if _LIBCPP_HAS_WIDE_CHARACTERS + void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm, char __fmt, char __mod) const; +# endif +}; + +template > +class time_put : public locale::facet, private __time_put { +public: + typedef _CharT char_type; + typedef _OutputIterator iter_type; + + _LIBCPP_HIDE_FROM_ABI explicit time_put(size_t __refs = 0) : locale::facet(__refs) {} + + iter_type + put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, const char_type* __pb, const char_type* __pe) + const; + + _LIBCPP_HIDE_FROM_ABI iter_type + put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, char __fmt, char __mod = 0) const { + return do_put(__s, __iob, __fl, __tm, __fmt, __mod); + } + + static locale::id id; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_put() override {} + virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm, char __fmt, char __mod) const; + + _LIBCPP_HIDE_FROM_ABI explicit time_put(const char* __nm, size_t __refs) : locale::facet(__refs), __time_put(__nm) {} + _LIBCPP_HIDE_FROM_ABI explicit time_put(const string& __nm, size_t __refs) + : locale::facet(__refs), __time_put(__nm) {} +}; + +template +locale::id time_put<_CharT, _OutputIterator>::id; + +template +_OutputIterator time_put<_CharT, _OutputIterator>::put( + iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, const char_type* __pb, const char_type* __pe) + const { + const ctype& __ct = std::use_facet >(__iob.getloc()); + for (; __pb != __pe; ++__pb) { + if (__ct.narrow(*__pb, 0) == '%') { + if (++__pb == __pe) { + *__s++ = __pb[-1]; + break; + } + char __mod = 0; + char __fmt = __ct.narrow(*__pb, 0); + if (__fmt == 'E' || __fmt == 'O') { + if (++__pb == __pe) { + *__s++ = __pb[-2]; + *__s++ = __pb[-1]; + break; + } + __mod = __fmt; + __fmt = __ct.narrow(*__pb, 0); + } + __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod); + } else + *__s++ = *__pb; + } + return __s; +} + +template +_OutputIterator time_put<_CharT, _OutputIterator>::do_put( + iter_type __s, ios_base&, char_type, const tm* __tm, char __fmt, char __mod) const { + char_type __nar[100]; + char_type* __nb = __nar; + char_type* __ne = __nb + 100; + __do_put(__nb, __ne, __tm, __fmt, __mod); + return std::copy(__nb, __ne, __s); +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put; +# endif + +template > +class time_put_byname : public time_put<_CharT, _OutputIterator> { +public: + _LIBCPP_HIDE_FROM_ABI explicit time_put_byname(const char* __nm, size_t __refs = 0) + : time_put<_CharT, _OutputIterator>(__nm, __refs) {} + + _LIBCPP_HIDE_FROM_ABI explicit time_put_byname(const string& __nm, size_t __refs = 0) + : time_put<_CharT, _OutputIterator>(__nm, __refs) {} + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_put_byname() override {} +}; + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname; +# endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_TIME_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/wbuffer_convert.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/wbuffer_convert.h new file mode 100644 index 0000000000..a6818aadf5 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/wbuffer_convert.h @@ -0,0 +1,430 @@ +//===----------------------------------------------------------------------===// +// +// 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___LOCALE_DIR_WBUFFER_CONVERT_H +#define _LIBCPP___LOCALE_DIR_WBUFFER_CONVERT_H + +#include <__algorithm/reverse.h> +#include <__config> +#include <__string/char_traits.h> +#include +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +# if _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT) + +_LIBCPP_PUSH_MACROS +# include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +template > +class _LIBCPP_DEPRECATED_IN_CXX17 wbuffer_convert : public basic_streambuf<_Elem, _Tr> { +public: + // types: + typedef _Elem char_type; + typedef _Tr 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; + typedef typename _Codecvt::state_type state_type; + +private: + char* __extbuf_; + const char* __extbufnext_; + const char* __extbufend_; + char __extbuf_min_[8]; + size_t __ebs_; + char_type* __intbuf_; + size_t __ibs_; + streambuf* __bufptr_; + _Codecvt* __cv_; + state_type __st_; + ios_base::openmode __cm_; + bool __owns_eb_; + bool __owns_ib_; + bool __always_noconv_; + +public: +# ifndef _LIBCPP_CXX03_LANG + _LIBCPP_HIDE_FROM_ABI wbuffer_convert() : wbuffer_convert(nullptr) {} + explicit _LIBCPP_HIDE_FROM_ABI + wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt = new _Codecvt, state_type __state = state_type()); +# else + _LIBCPP_EXPLICIT_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI + wbuffer_convert(streambuf* __bytebuf = nullptr, _Codecvt* __pcvt = new _Codecvt, state_type __state = state_type()); +# endif + + _LIBCPP_HIDE_FROM_ABI ~wbuffer_convert(); + + _LIBCPP_HIDE_FROM_ABI streambuf* rdbuf() const { return __bufptr_; } + _LIBCPP_HIDE_FROM_ABI streambuf* rdbuf(streambuf* __bytebuf) { + streambuf* __r = __bufptr_; + __bufptr_ = __bytebuf; + return __r; + } + + wbuffer_convert(const wbuffer_convert&) = delete; + wbuffer_convert& operator=(const wbuffer_convert&) = delete; + + _LIBCPP_HIDE_FROM_ABI state_type state() const { return __st_; } + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int_type underflow(); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int_type pbackfail(int_type __c = traits_type::eof()); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int_type overflow(int_type __c = traits_type::eof()); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual basic_streambuf* setbuf(char_type* __s, streamsize __n); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual pos_type + seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __wch = ios_base::in | ios_base::out); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual pos_type + seekpos(pos_type __sp, ios_base::openmode __wch = ios_base::in | ios_base::out); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int sync(); + +private: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL bool __read_mode(); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __write_mode(); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL wbuffer_convert* __close(); +}; + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +wbuffer_convert<_Codecvt, _Elem, _Tr>::wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state) + : __extbuf_(nullptr), + __extbufnext_(nullptr), + __extbufend_(nullptr), + __ebs_(0), + __intbuf_(0), + __ibs_(0), + __bufptr_(__bytebuf), + __cv_(__pcvt), + __st_(__state), + __cm_(0), + __owns_eb_(false), + __owns_ib_(false), + __always_noconv_(__cv_ ? __cv_->always_noconv() : false) { + setbuf(0, 4096); +} + +template +wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert() { + __close(); + delete __cv_; + if (__owns_eb_) + delete[] __extbuf_; + if (__owns_ib_) + delete[] __intbuf_; +} + +template +typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow() { + _LIBCPP_SUPPRESS_DEPRECATED_POP + if (__cv_ == 0 || __bufptr_ == nullptr) + return traits_type::eof(); + bool __initial = __read_mode(); + char_type __1buf; + if (this->gptr() == 0) + this->setg(std::addressof(__1buf), std::addressof(__1buf) + 1, std::addressof(__1buf) + 1); + const size_t __unget_sz = __initial ? 0 : std::min((this->egptr() - this->eback()) / 2, 4); + int_type __c = traits_type::eof(); + if (this->gptr() == this->egptr()) { + std::memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type)); + if (__always_noconv_) { + streamsize __nmemb = static_cast(this->egptr() - this->eback() - __unget_sz); + __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb); + if (__nmemb != 0) { + this->setg(this->eback(), this->eback() + __unget_sz, this->eback() + __unget_sz + __nmemb); + __c = *this->gptr(); + } + } else { + if (__extbufend_ != __extbufnext_) { + _LIBCPP_ASSERT_NON_NULL(__extbufnext_ != nullptr, "underflow moving from nullptr"); + _LIBCPP_ASSERT_NON_NULL(__extbuf_ != nullptr, "underflow moving into nullptr"); + std::memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_); + } + __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_); + __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_); + streamsize __nmemb = std::min(static_cast(this->egptr() - this->eback() - __unget_sz), + static_cast(__extbufend_ - __extbufnext_)); + codecvt_base::result __r; + // FIXME: Do we ever need to restore the state here? + // state_type __svs = __st_; + streamsize __nr = __bufptr_->sgetn(const_cast(__extbufnext_), __nmemb); + if (__nr != 0) { + __extbufend_ = __extbufnext_ + __nr; + char_type* __inext; + __r = __cv_->in( + __st_, __extbuf_, __extbufend_, __extbufnext_, this->eback() + __unget_sz, this->egptr(), __inext); + if (__r == codecvt_base::noconv) { + this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)const_cast(__extbufend_)); + __c = *this->gptr(); + } else if (__inext != this->eback() + __unget_sz) { + this->setg(this->eback(), this->eback() + __unget_sz, __inext); + __c = *this->gptr(); + } + } + } + } else + __c = *this->gptr(); + if (this->eback() == std::addressof(__1buf)) + this->setg(0, 0, 0); + return __c; +} + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type +wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c) { + _LIBCPP_SUPPRESS_DEPRECATED_POP + if (__cv_ != 0 && __bufptr_ && this->eback() < this->gptr()) { + if (traits_type::eq_int_type(__c, traits_type::eof())) { + this->gbump(-1); + return traits_type::not_eof(__c); + } + if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1])) { + this->gbump(-1); + *this->gptr() = traits_type::to_char_type(__c); + return __c; + } + } + return traits_type::eof(); +} + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c) { + _LIBCPP_SUPPRESS_DEPRECATED_POP + if (__cv_ == 0 || !__bufptr_) + return traits_type::eof(); + __write_mode(); + char_type __1buf; + char_type* __pb_save = this->pbase(); + char_type* __epb_save = this->epptr(); + if (!traits_type::eq_int_type(__c, traits_type::eof())) { + if (this->pptr() == 0) + this->setp(std::addressof(__1buf), std::addressof(__1buf) + 1); + *this->pptr() = traits_type::to_char_type(__c); + this->pbump(1); + } + if (this->pptr() != this->pbase()) { + if (__always_noconv_) { + streamsize __nmemb = static_cast(this->pptr() - this->pbase()); + if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb) + return traits_type::eof(); + } else { + char* __extbe = __extbuf_; + codecvt_base::result __r; + do { + const char_type* __e; + __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e, __extbuf_, __extbuf_ + __ebs_, __extbe); + if (__e == this->pbase()) + return traits_type::eof(); + if (__r == codecvt_base::noconv) { + streamsize __nmemb = static_cast(this->pptr() - this->pbase()); + if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb) + return traits_type::eof(); + } else if (__r == codecvt_base::ok || __r == codecvt_base::partial) { + streamsize __nmemb = static_cast(__extbe - __extbuf_); + if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb) + return traits_type::eof(); + if (__r == codecvt_base::partial) { + this->setp(const_cast(__e), this->pptr()); + this->__pbump(this->epptr() - this->pbase()); + } + } else + return traits_type::eof(); + } while (__r == codecvt_base::partial); + } + this->setp(__pb_save, __epb_save); + } + return traits_type::not_eof(__c); +} + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +basic_streambuf<_Elem, _Tr>* wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n) { + _LIBCPP_SUPPRESS_DEPRECATED_POP + this->setg(0, 0, 0); + this->setp(0, 0); + if (__owns_eb_) + delete[] __extbuf_; + if (__owns_ib_) + delete[] __intbuf_; + __ebs_ = __n; + if (__ebs_ > sizeof(__extbuf_min_)) { + if (__always_noconv_ && __s) { + __extbuf_ = (char*)__s; + __owns_eb_ = false; + } else { + __extbuf_ = new char[__ebs_]; + __owns_eb_ = true; + } + } else { + __extbuf_ = __extbuf_min_; + __ebs_ = sizeof(__extbuf_min_); + __owns_eb_ = false; + } + if (!__always_noconv_) { + __ibs_ = max(__n, sizeof(__extbuf_min_)); + if (__s && __ibs_ >= sizeof(__extbuf_min_)) { + __intbuf_ = __s; + __owns_ib_ = false; + } else { + __intbuf_ = new char_type[__ibs_]; + __owns_ib_ = true; + } + } else { + __ibs_ = 0; + __intbuf_ = 0; + __owns_ib_ = false; + } + return this; +} + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type +wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __om) { + int __width = __cv_->encoding(); + if (__cv_ == 0 || !__bufptr_ || (__width <= 0 && __off != 0) || sync()) + return pos_type(off_type(-1)); + // __width > 0 || __off == 0, now check __way + if (__way != ios_base::beg && __way != ios_base::cur && __way != ios_base::end) + return pos_type(off_type(-1)); + pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om); + __r.state(__st_); + return __r; +} + +template +typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type +wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch) { + if (__cv_ == 0 || !__bufptr_ || sync()) + return pos_type(off_type(-1)); + if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1))) + return pos_type(off_type(-1)); + return __sp; +} + +template +int wbuffer_convert<_Codecvt, _Elem, _Tr>::sync() { + _LIBCPP_SUPPRESS_DEPRECATED_POP + if (__cv_ == 0 || !__bufptr_) + return 0; + if (__cm_ & ios_base::out) { + if (this->pptr() != this->pbase()) + if (overflow() == traits_type::eof()) + return -1; + codecvt_base::result __r; + do { + char* __extbe; + __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe); + streamsize __nmemb = static_cast(__extbe - __extbuf_); + if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb) + return -1; + } while (__r == codecvt_base::partial); + if (__r == codecvt_base::error) + return -1; + if (__bufptr_->pubsync()) + return -1; + } else if (__cm_ & ios_base::in) { + off_type __c; + if (__always_noconv_) + __c = this->egptr() - this->gptr(); + else { + int __width = __cv_->encoding(); + __c = __extbufend_ - __extbufnext_; + if (__width > 0) + __c += __width * (this->egptr() - this->gptr()); + else { + if (this->gptr() != this->egptr()) { + std::reverse(this->gptr(), this->egptr()); + codecvt_base::result __r; + const char_type* __e = this->gptr(); + char* __extbe; + do { + __r = __cv_->out(__st_, __e, this->egptr(), __e, __extbuf_, __extbuf_ + __ebs_, __extbe); + switch (__r) { + case codecvt_base::noconv: + __c += this->egptr() - this->gptr(); + break; + case codecvt_base::ok: + case codecvt_base::partial: + __c += __extbe - __extbuf_; + break; + default: + return -1; + } + } while (__r == codecvt_base::partial); + } + } + } + if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1))) + return -1; + this->setg(0, 0, 0); + __cm_ = 0; + } + return 0; +} + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +bool wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode() { + if (!(__cm_ & ios_base::in)) { + this->setp(0, 0); + if (__always_noconv_) + this->setg((char_type*)__extbuf_, (char_type*)__extbuf_ + __ebs_, (char_type*)__extbuf_ + __ebs_); + else + this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_); + __cm_ = ios_base::in; + return true; + } + return false; +} + +template +void wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode() { + if (!(__cm_ & ios_base::out)) { + this->setg(0, 0, 0); + if (__ebs_ > sizeof(__extbuf_min_)) { + if (__always_noconv_) + this->setp((char_type*)__extbuf_, (char_type*)__extbuf_ + (__ebs_ - 1)); + else + this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1)); + } else + this->setp(0, 0); + __cm_ = ios_base::out; + } +} + +template +wbuffer_convert<_Codecvt, _Elem, _Tr>* wbuffer_convert<_Codecvt, _Elem, _Tr>::__close() { + wbuffer_convert* __rt = nullptr; + if (__cv_ != nullptr && __bufptr_ != nullptr) { + __rt = this; + if ((__cm_ & ios_base::out) && sync()) + __rt = nullptr; + } + return __rt; +} + +_LIBCPP_SUPPRESS_DEPRECATED_POP + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +# endif // _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT) + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_WBUFFER_CONVERT_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/wstring_convert.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/wstring_convert.h new file mode 100644 index 0000000000..42a56eb857 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/wstring_convert.h @@ -0,0 +1,254 @@ +//===----------------------------------------------------------------------===// +// +// 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___LOCALE_DIR_WSTRING_CONVERT_H +#define _LIBCPP___LOCALE_DIR_WSTRING_CONVERT_H + +#include <__config> +#include <__locale> +#include <__memory/allocator.h> +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +# if _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT) + +_LIBCPP_PUSH_MACROS +# include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +template , + class _ByteAlloc = allocator > +class _LIBCPP_DEPRECATED_IN_CXX17 wstring_convert { +public: + typedef basic_string, _ByteAlloc> byte_string; + typedef basic_string<_Elem, char_traits<_Elem>, _WideAlloc> wide_string; + typedef typename _Codecvt::state_type state_type; + typedef typename wide_string::traits_type::int_type int_type; + +private: + byte_string __byte_err_string_; + wide_string __wide_err_string_; + _Codecvt* __cvtptr_; + state_type __cvtstate_; + size_t __cvtcount_; + +public: +# ifndef _LIBCPP_CXX03_LANG + _LIBCPP_HIDE_FROM_ABI wstring_convert() : wstring_convert(new _Codecvt) {} + _LIBCPP_HIDE_FROM_ABI explicit wstring_convert(_Codecvt* __pcvt); +# else + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXPLICIT_SINCE_CXX14 wstring_convert(_Codecvt* __pcvt = new _Codecvt); +# endif + + _LIBCPP_HIDE_FROM_ABI wstring_convert(_Codecvt* __pcvt, state_type __state); + _LIBCPP_EXPLICIT_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI + wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err = wide_string()); +# ifndef _LIBCPP_CXX03_LANG + _LIBCPP_HIDE_FROM_ABI wstring_convert(wstring_convert&& __wc); +# endif + _LIBCPP_HIDE_FROM_ABI ~wstring_convert(); + + wstring_convert(const wstring_convert& __wc) = delete; + wstring_convert& operator=(const wstring_convert& __wc) = delete; + + _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(char __byte) { return from_bytes(&__byte, &__byte + 1); } + _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const char* __ptr) { + return from_bytes(__ptr, __ptr + char_traits::length(__ptr)); + } + _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const byte_string& __str) { + return from_bytes(__str.data(), __str.data() + __str.size()); + } + _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const char* __first, const char* __last); + + _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(_Elem __wchar) { + return to_bytes(std::addressof(__wchar), std::addressof(__wchar) + 1); + } + _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const _Elem* __wptr) { + return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr)); + } + _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const wide_string& __wstr) { + return to_bytes(__wstr.data(), __wstr.data() + __wstr.size()); + } + _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const _Elem* __first, const _Elem* __last); + + _LIBCPP_HIDE_FROM_ABI size_t converted() const _NOEXCEPT { return __cvtcount_; } + _LIBCPP_HIDE_FROM_ABI state_type state() const { return __cvtstate_; } +}; + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +inline wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wstring_convert(_Codecvt* __pcvt) + : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0) {} +_LIBCPP_SUPPRESS_DEPRECATED_POP + +template +inline wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wstring_convert(_Codecvt* __pcvt, state_type __state) + : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0) {} + +template +wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wstring_convert( + const byte_string& __byte_err, const wide_string& __wide_err) + : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err), __cvtstate_(), __cvtcount_(0) { + __cvtptr_ = new _Codecvt; +} + +# ifndef _LIBCPP_CXX03_LANG + +template +inline wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wstring_convert(wstring_convert&& __wc) + : __byte_err_string_(std::move(__wc.__byte_err_string_)), + __wide_err_string_(std::move(__wc.__wide_err_string_)), + __cvtptr_(__wc.__cvtptr_), + __cvtstate_(__wc.__cvtstate_), + __cvtcount_(__wc.__cvtcount_) { + __wc.__cvtptr_ = nullptr; +} + +# endif // _LIBCPP_CXX03_LANG + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::~wstring_convert() { + delete __cvtptr_; +} + +template +typename wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wide_string +wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::from_bytes(const char* __frm, const char* __frm_end) { + _LIBCPP_SUPPRESS_DEPRECATED_POP + __cvtcount_ = 0; + if (__cvtptr_ != nullptr) { + wide_string __ws(2 * (__frm_end - __frm), _Elem()); + if (__frm != __frm_end) + __ws.resize(__ws.capacity()); + codecvt_base::result __r = codecvt_base::ok; + state_type __st = __cvtstate_; + if (__frm != __frm_end) { + _Elem* __to = std::addressof(__ws[0]); + _Elem* __to_end = __to + __ws.size(); + const char* __frm_nxt; + do { + _Elem* __to_nxt; + __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); + __cvtcount_ += __frm_nxt - __frm; + if (__frm_nxt == __frm) { + __r = codecvt_base::error; + } else if (__r == codecvt_base::noconv) { + __ws.resize(__to - std::addressof(__ws[0])); + // This only gets executed if _Elem is char + __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end); + __frm = __frm_nxt; + __r = codecvt_base::ok; + } else if (__r == codecvt_base::ok) { + __ws.resize(__to_nxt - std::addressof(__ws[0])); + __frm = __frm_nxt; + } else if (__r == codecvt_base::partial) { + ptrdiff_t __s = __to_nxt - std::addressof(__ws[0]); + __ws.resize(2 * __s); + __to = std::addressof(__ws[0]) + __s; + __to_end = std::addressof(__ws[0]) + __ws.size(); + __frm = __frm_nxt; + } + } while (__r == codecvt_base::partial && __frm_nxt < __frm_end); + } + if (__r == codecvt_base::ok) + return __ws; + } + + if (__wide_err_string_.empty()) + std::__throw_range_error("wstring_convert: from_bytes error"); + + return __wide_err_string_; +} + +template +typename wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::byte_string +wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::to_bytes(const _Elem* __frm, const _Elem* __frm_end) { + __cvtcount_ = 0; + if (__cvtptr_ != nullptr) { + byte_string __bs(2 * (__frm_end - __frm), char()); + if (__frm != __frm_end) + __bs.resize(__bs.capacity()); + codecvt_base::result __r = codecvt_base::ok; + state_type __st = __cvtstate_; + if (__frm != __frm_end) { + char* __to = std::addressof(__bs[0]); + char* __to_end = __to + __bs.size(); + const _Elem* __frm_nxt; + do { + char* __to_nxt; + __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); + __cvtcount_ += __frm_nxt - __frm; + if (__frm_nxt == __frm) { + __r = codecvt_base::error; + } else if (__r == codecvt_base::noconv) { + __bs.resize(__to - std::addressof(__bs[0])); + // This only gets executed if _Elem is char + __bs.append((const char*)__frm, (const char*)__frm_end); + __frm = __frm_nxt; + __r = codecvt_base::ok; + } else if (__r == codecvt_base::ok) { + __bs.resize(__to_nxt - std::addressof(__bs[0])); + __frm = __frm_nxt; + } else if (__r == codecvt_base::partial) { + ptrdiff_t __s = __to_nxt - std::addressof(__bs[0]); + __bs.resize(2 * __s); + __to = std::addressof(__bs[0]) + __s; + __to_end = std::addressof(__bs[0]) + __bs.size(); + __frm = __frm_nxt; + } + } while (__r == codecvt_base::partial && __frm_nxt < __frm_end); + } + if (__r == codecvt_base::ok) { + size_t __s = __bs.size(); + __bs.resize(__bs.capacity()); + char* __to = std::addressof(__bs[0]) + __s; + char* __to_end = __to + __bs.size(); + do { + char* __to_nxt; + __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt); + if (__r == codecvt_base::noconv) { + __bs.resize(__to - std::addressof(__bs[0])); + __r = codecvt_base::ok; + } else if (__r == codecvt_base::ok) { + __bs.resize(__to_nxt - std::addressof(__bs[0])); + } else if (__r == codecvt_base::partial) { + ptrdiff_t __sp = __to_nxt - std::addressof(__bs[0]); + __bs.resize(2 * __sp); + __to = std::addressof(__bs[0]) + __sp; + __to_end = std::addressof(__bs[0]) + __bs.size(); + } + } while (__r == codecvt_base::partial); + if (__r == codecvt_base::ok) + return __bs; + } + } + + if (__byte_err_string_.empty()) + std::__throw_range_error("wstring_convert: to_bytes error"); + + return __byte_err_string_; +} + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +# endif // _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT) + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_WSTRING_CONVERT_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__log_hardening_failure b/naiveproxy/src/third_party/libc++/src/include/__log_hardening_failure new file mode 100644 index 0000000000..d1805306f6 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__log_hardening_failure @@ -0,0 +1,42 @@ +// -*- 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___LOG_HARDENING_FAILURE +#define _LIBCPP___LOG_HARDENING_FAILURE + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +// Hardening logging is not available in the C++03 mode; moreover, it is currently only available in the experimental +// library. +#if _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC && !defined(_LIBCPP_CXX03_LANG) + +_LIBCPP_BEGIN_NAMESPACE_STD + +// This function should never be called directly from the code -- it should only be called through the +// `_LIBCPP_LOG_HARDENING_FAILURE` macro. +[[__gnu__::__cold__]] _LIBCPP_EXPORTED_FROM_ABI void __log_hardening_failure(const char* __message) noexcept; + +// _LIBCPP_LOG_HARDENING_FAILURE(message) +// +// This macro is used to log an error without terminating the program (as is the case for hardening failures if the +// `observe` assertion semantic is used). + +# if !defined(_LIBCPP_LOG_HARDENING_FAILURE) +# define _LIBCPP_LOG_HARDENING_FAILURE(__message) ::std::__log_hardening_failure(__message) +# endif // !defined(_LIBCPP_LOG_HARDENING_FAILURE) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC && !defined(_LIBCPP_CXX03_LANG) + +#endif // _LIBCPP___LOG_HARDENING_FAILURE 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 fc3bf3a2c7..b780159f11 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__math/abs.h +++ b/naiveproxy/src/third_party/libc++/src/include/__math/abs.h @@ -39,6 +39,30 @@ template ::value, int> = 0> return __builtin_fabs((double)__x); } +// abs + +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline float abs(float __x) _NOEXCEPT { return __builtin_fabsf(__x); } +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline double abs(double __x) _NOEXCEPT { return __builtin_fabs(__x); } + +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline long double abs(long double __x) _NOEXCEPT { + return __builtin_fabsl(__x); +} + +template +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline int abs(int __x) _NOEXCEPT { + return __builtin_abs(__x); +} + +template +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline long abs(long __x) _NOEXCEPT { + return __builtin_labs(__x); +} + +template +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline long long abs(long long __x) _NOEXCEPT { + return __builtin_llabs(__x); +} + } // namespace __math _LIBCPP_END_NAMESPACE_STD diff --git a/naiveproxy/src/third_party/libc++/src/include/__math/logarithms.h b/naiveproxy/src/third_party/libc++/src/include/__math/logarithms.h index 5f5f943977..7343d6a84a 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__math/logarithms.h +++ b/naiveproxy/src/third_party/libc++/src/include/__math/logarithms.h @@ -58,7 +58,7 @@ inline _LIBCPP_HIDE_FROM_ABI double log10(_A1 __x) _NOEXCEPT { inline _LIBCPP_HIDE_FROM_ABI int ilogb(float __x) _NOEXCEPT { return __builtin_ilogbf(__x); } template -_LIBCPP_HIDE_FROM_ABI double ilogb(double __x) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI int ilogb(double __x) _NOEXCEPT { return __builtin_ilogb(__x); } 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 0045400485..99b54badf8 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__mdspan/extents.h +++ b/naiveproxy/src/third_party/libc++/src/include/__mdspan/extents.h @@ -21,11 +21,10 @@ #include <__config> #include <__concepts/arithmetic.h> -#include <__cstddef/byte.h> #include <__type_traits/common_type.h> +#include <__type_traits/integer_traits.h> #include <__type_traits/is_convertible.h> #include <__type_traits/is_nothrow_constructible.h> -#include <__type_traits/is_same.h> #include <__type_traits/make_unsigned.h> #include <__utility/integer_sequence.h> #include <__utility/unreachable.h> @@ -283,7 +282,8 @@ public: using size_type = make_unsigned_t; using rank_type = size_t; - static_assert(__libcpp_integer, "extents::index_type must be a signed or unsigned integer type"); + static_assert(__signed_or_unsigned_integer, + "extents::index_type must be a signed or unsigned integer type"); static_assert(((__mdspan_detail::__is_representable_as(_Extents) || (_Extents == dynamic_extent)) && ...), "extents ctor: arguments must be representable as index_type and nonnegative"); diff --git a/naiveproxy/src/third_party/libc++/src/include/__memory/addressof.h b/naiveproxy/src/third_party/libc++/src/include/__memory/addressof.h index 98b08958a6..667071dfc6 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__memory/addressof.h +++ b/naiveproxy/src/third_party/libc++/src/include/__memory/addressof.h @@ -23,7 +23,7 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX17 _LIBCPP_NO_CFI _LIBCPP_HIDE_FROM_ABI _Tp* a return __builtin_addressof(__x); } -#if _LIBCPP_HAS_OBJC_ARC +#if __has_feature(objc_arc) // Objective-C++ Automatic Reference Counting uses qualified pointers // that require special addressof() signatures. template @@ -31,7 +31,7 @@ inline _LIBCPP_HIDE_FROM_ABI __strong _Tp* addressof(__strong _Tp& __x) _NOEXCEP return &__x; } -# if _LIBCPP_HAS_OBJC_ARC_WEAK +# if __has_feature(objc_arc_weak) template inline _LIBCPP_HIDE_FROM_ABI __weak _Tp* addressof(__weak _Tp& __x) _NOEXCEPT { return &__x; diff --git a/naiveproxy/src/third_party/libc++/src/include/__memory/allocation_guard.h b/naiveproxy/src/third_party/libc++/src/include/__memory/allocation_guard.h index 66edcd92ed..016e1a3a42 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__memory/allocation_guard.h +++ b/naiveproxy/src/third_party/libc++/src/include/__memory/allocation_guard.h @@ -49,24 +49,26 @@ struct __allocation_guard { using _Size _LIBCPP_NODEBUG = typename allocator_traits<_Alloc>::size_type; template // we perform the allocator conversion inside the constructor - _LIBCPP_HIDE_FROM_ABI explicit __allocation_guard(_AllocT __alloc, _Size __n) + _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit __allocation_guard(_AllocT __alloc, _Size __n) : __alloc_(std::move(__alloc)), __n_(__n), __ptr_(allocator_traits<_Alloc>::allocate(__alloc_, __n_)) // initialization order is important {} - _LIBCPP_HIDE_FROM_ABI ~__allocation_guard() _NOEXCEPT { __destroy(); } + _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI ~__allocation_guard() _NOEXCEPT { __destroy(); } - _LIBCPP_HIDE_FROM_ABI __allocation_guard(const __allocation_guard&) = delete; - _LIBCPP_HIDE_FROM_ABI __allocation_guard(__allocation_guard&& __other) _NOEXCEPT + __allocation_guard(const __allocation_guard&) = delete; + __allocation_guard& operator=(const __allocation_guard& __other) = delete; + + _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __allocation_guard(__allocation_guard&& __other) _NOEXCEPT : __alloc_(std::move(__other.__alloc_)), __n_(__other.__n_), __ptr_(__other.__ptr_) { __other.__ptr_ = nullptr; } - _LIBCPP_HIDE_FROM_ABI __allocation_guard& operator=(const __allocation_guard& __other) = delete; - _LIBCPP_HIDE_FROM_ABI __allocation_guard& operator=(__allocation_guard&& __other) _NOEXCEPT { + _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __allocation_guard& + operator=(__allocation_guard&& __other) _NOEXCEPT { if (std::addressof(__other) != this) { __destroy(); @@ -79,17 +81,17 @@ struct __allocation_guard { return *this; } - _LIBCPP_HIDE_FROM_ABI _Pointer + _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI _Pointer __release_ptr() _NOEXCEPT { // not called __release() because it's a keyword in objective-c++ _Pointer __tmp = __ptr_; __ptr_ = nullptr; return __tmp; } - _LIBCPP_HIDE_FROM_ABI _Pointer __get() const _NOEXCEPT { return __ptr_; } + _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI _Pointer __get() const _NOEXCEPT { return __ptr_; } private: - _LIBCPP_HIDE_FROM_ABI void __destroy() _NOEXCEPT { + _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __destroy() _NOEXCEPT { if (__ptr_ != nullptr) { allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __n_); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__memory/construct_at.h b/naiveproxy/src/third_party/libc++/src/include/__memory/construct_at.h index 21337e766b..658269158d 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__memory/construct_at.h +++ b/naiveproxy/src/third_party/libc++/src/include/__memory/construct_at.h @@ -12,14 +12,12 @@ #include <__assert> #include <__config> -#include <__iterator/access.h> #include <__memory/addressof.h> #include <__new/placement_new_delete.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_array.h> #include <__utility/declval.h> #include <__utility/forward.h> -#include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -35,7 +33,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template ()) _Tp(std::declval<_Args>()...))> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp* construct_at(_Tp* __location, _Args&&... __args) { +_LIBCPP_HIDE_FROM_ABI constexpr _Tp* construct_at(_Tp* _LIBCPP_DIAGNOSE_NULLPTR __location, _Args&&... __args) { _LIBCPP_ASSERT_NON_NULL(__location != nullptr, "null pointer given to construct_at"); return ::new (static_cast(__location)) _Tp(std::forward<_Args>(__args)...); } @@ -65,24 +63,23 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __destroy_at(_Tp* __loc #if _LIBCPP_STD_VER >= 20 template ::value, int> = 0> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __destroy_at(_Tp* __loc) { +_LIBCPP_HIDE_FROM_ABI constexpr void __destroy_at(_Tp* __loc) { _LIBCPP_ASSERT_NON_NULL(__loc != nullptr, "null pointer given to destroy_at"); - auto const __end = std::end(*__loc); - for (auto __it = std::begin(*__loc); __it != __end; ++__it) - std::__destroy_at(__it); + for (auto&& __val : *__loc) + std::__destroy_at(std::addressof(__val)); } #endif #if _LIBCPP_STD_VER >= 17 template , int> = 0> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void destroy_at(_Tp* __loc) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void destroy_at(_Tp* _LIBCPP_DIAGNOSE_NULLPTR __loc) { std::__destroy_at(__loc); } # if _LIBCPP_STD_VER >= 20 template , int> = 0> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void destroy_at(_Tp* __loc) { +_LIBCPP_HIDE_FROM_ABI constexpr void destroy_at(_Tp* _LIBCPP_DIAGNOSE_NULLPTR __loc) { std::__destroy_at(__loc); } # endif 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 4ba50898fb..8c7f8dff1b 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 @@ -16,11 +16,13 @@ #include <__type_traits/conditional.h> #include <__type_traits/conjunction.h> #include <__type_traits/decay.h> +#include <__type_traits/detected_or.h> #include <__type_traits/enable_if.h> #include <__type_traits/integral_constant.h> #include <__type_traits/is_class.h> #include <__type_traits/is_function.h> #include <__type_traits/is_void.h> +#include <__type_traits/nat.h> #include <__type_traits/void_t.h> #include <__utility/declval.h> #include <__utility/forward.h> @@ -34,67 +36,37 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -// clang-format off -#define _LIBCPP_CLASS_TRAITS_HAS_XXX(NAME, PROPERTY) \ - template \ - struct NAME : false_type {}; \ - template \ - struct NAME<_Tp, __void_t > : true_type {} -// clang-format on - -_LIBCPP_CLASS_TRAITS_HAS_XXX(__has_pointer, pointer); -_LIBCPP_CLASS_TRAITS_HAS_XXX(__has_element_type, element_type); - -template ::value> -struct __pointer_traits_element_type {}; - template -struct __pointer_traits_element_type<_Ptr, true> { - using type _LIBCPP_NODEBUG = typename _Ptr::element_type; -}; +struct __pointer_traits_element_type_impl {}; template