mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e2dac668c6 | ||
|
|
54dee45d47 | ||
|
|
1c1c13234f | ||
|
|
d892c2b1c8 | ||
|
|
6132e80a4f | ||
|
|
a953199af3 | ||
|
|
056eacf1ce | ||
|
|
5f8ef81277 | ||
|
|
4995c9ee97 | ||
|
|
e29cdacb13 | ||
|
|
b58903d195 | ||
|
|
33f9dce7c2 | ||
|
|
4938ca50f0 | ||
|
|
e940852250 | ||
|
|
2598dc0ce6 | ||
|
|
2dee8783cc | ||
|
|
b026a66172 | ||
|
|
7a4948bd80 | ||
|
|
878f18474e | ||
|
|
bbe9d8b8c9 |
@@ -65,6 +65,9 @@ jobs:
|
||||
curl -fLSs https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/master/install.sh | DESTDIR=$CIRCLECI_BINARY bash
|
||||
node build.js
|
||||
name: Pack config.yml
|
||||
- run:
|
||||
name: Set params
|
||||
command: node .circleci/config/params.js
|
||||
- continuation/continue:
|
||||
configuration_path: .circleci/config-staging/built.yml
|
||||
parameters: /tmp/pipeline-parameters.json
|
||||
|
||||
@@ -34,6 +34,11 @@ parameters:
|
||||
type: enum
|
||||
default: all
|
||||
enum: ["all", "osx-x64", "osx-arm64", "mas-x64", "mas-arm64"]
|
||||
|
||||
large-linux-executor:
|
||||
type: enum
|
||||
default: electronjs/aks-linux-large
|
||||
enum: ["electronjs/aks-linux-large", "2xlarge"]
|
||||
|
||||
# Executors
|
||||
executors:
|
||||
@@ -42,7 +47,9 @@ executors:
|
||||
size:
|
||||
description: "Docker executor size"
|
||||
type: enum
|
||||
enum: ["medium", "xlarge", "2xlarge"]
|
||||
# aks-linux-large === 32 core
|
||||
# 2xlarge should not be used directly, use the pipeline param instead
|
||||
enum: ["medium", "xlarge", "electronjs/aks-linux-large", "2xlarge"]
|
||||
docker:
|
||||
- image: ghcr.io/electron/build:e6bebd08a51a0d78ec23e5b3fd7e7c0846412328
|
||||
resource_class: << parameters.size >>
|
||||
@@ -245,19 +252,19 @@ step-depot-tools-get: &step-depot-tools-get
|
||||
cd depot_tools
|
||||
cat > gclient.diff \<< 'EOF'
|
||||
diff --git a/gclient.py b/gclient.py
|
||||
index 3a9c5c6..f222043 100755
|
||||
index c305c248..e6e0fbdc 100755
|
||||
--- a/gclient.py
|
||||
+++ b/gclient.py
|
||||
@@ -712,7 +712,8 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
|
||||
|
||||
if dep_type == 'cipd':
|
||||
cipd_root = self.GetCipdRoot()
|
||||
- for package in dep_value.get('packages', []):
|
||||
+ packages = dep_value.get('packages', [])
|
||||
+ for package in (x for x in packages if "infra/3pp/tools/swift-format" not in x.get('package')):
|
||||
deps_to_add.append(
|
||||
CipdDependency(
|
||||
parent=self,
|
||||
@@ -735,7 +735,8 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
|
||||
|
||||
if dep_type == 'cipd':
|
||||
cipd_root = self.GetCipdRoot()
|
||||
- for package in dep_value.get('packages', []):
|
||||
+ packages = dep_value.get('packages', [])
|
||||
+ for package in (x for x in packages if "infra/3pp/tools/swift-format" not in x.get('package')):
|
||||
deps_to_add.append(
|
||||
CipdDependency(parent=self,
|
||||
name=name,
|
||||
EOF
|
||||
git apply --3way gclient.diff
|
||||
fi
|
||||
@@ -345,7 +352,7 @@ step-setup-goma-for-build: &step-setup-goma-for-build
|
||||
exit 1
|
||||
fi
|
||||
echo 'export GN_GOMA_FILE='`node -e "console.log(require('./src/utils/goma.js').gnFilePath)"` >> $BASH_ENV
|
||||
echo 'export LOCAL_GOMA_DIR='`node -e "console.log(require('./src/utils/goma.js').dir)"` >> $BASH_ENV
|
||||
echo 'export GOMA_DIR='`node -e "console.log(require('./src/utils/goma.js').dir)"` >> $BASH_ENV
|
||||
echo 'export GOMA_FALLBACK_ON_AUTH_FAILURE=true' >> $BASH_ENV
|
||||
cd ..
|
||||
touch "${TMPDIR:=/tmp}"/.goma-ready
|
||||
@@ -774,8 +781,8 @@ step-show-goma-stats: &step-show-goma-stats
|
||||
command: |
|
||||
set +e
|
||||
set +o pipefail
|
||||
$LOCAL_GOMA_DIR/goma_ctl.py stat
|
||||
$LOCAL_GOMA_DIR/diagnose_goma_log.py
|
||||
$GOMA_DIR/goma_ctl.py stat
|
||||
$GOMA_DIR/diagnose_goma_log.py
|
||||
true
|
||||
when: always
|
||||
background: true
|
||||
@@ -1481,6 +1488,7 @@ commands:
|
||||
- *step-minimize-workspace-size-from-checkout
|
||||
- *step-fix-sync
|
||||
- *step-setup-env-for-build
|
||||
- *step-fix-known-hosts-linux
|
||||
- *step-setup-goma-for-build
|
||||
- *step-wait-for-goma
|
||||
- *step-gn-gen-default
|
||||
@@ -1586,7 +1594,7 @@ jobs:
|
||||
linux-x64-testing:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: xlarge
|
||||
size: << pipeline.parameters.large-linux-executor >>
|
||||
environment:
|
||||
<<: *env-global
|
||||
<<: *env-testing-build
|
||||
@@ -1601,7 +1609,7 @@ jobs:
|
||||
linux-x64-testing-asan:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: 2xlarge
|
||||
size: << pipeline.parameters.large-linux-executor >>
|
||||
environment:
|
||||
<<: *env-global
|
||||
<<: *env-testing-build
|
||||
@@ -1643,7 +1651,7 @@ jobs:
|
||||
linux-x64-publish:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: 2xlarge
|
||||
size: << pipeline.parameters.large-linux-executor >>
|
||||
environment:
|
||||
<<: *env-linux-2xlarge-release
|
||||
<<: *env-release-build
|
||||
@@ -1665,7 +1673,7 @@ jobs:
|
||||
linux-arm-testing:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: 2xlarge
|
||||
size: << pipeline.parameters.large-linux-executor >>
|
||||
environment:
|
||||
<<: *env-global
|
||||
<<: *env-arm
|
||||
@@ -1683,7 +1691,7 @@ jobs:
|
||||
linux-arm-publish:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: 2xlarge
|
||||
size: << pipeline.parameters.large-linux-executor >>
|
||||
environment:
|
||||
<<: *env-linux-2xlarge-release
|
||||
<<: *env-arm
|
||||
@@ -1707,7 +1715,7 @@ jobs:
|
||||
linux-arm64-testing:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: 2xlarge
|
||||
size: << pipeline.parameters.large-linux-executor >>
|
||||
environment:
|
||||
<<: *env-global
|
||||
<<: *env-arm64
|
||||
@@ -1736,7 +1744,7 @@ jobs:
|
||||
linux-arm64-publish:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: 2xlarge
|
||||
size: << pipeline.parameters.large-linux-executor >>
|
||||
environment:
|
||||
<<: *env-linux-2xlarge-release
|
||||
<<: *env-arm64
|
||||
|
||||
11
.circleci/config/params.js
Normal file
11
.circleci/config/params.js
Normal file
@@ -0,0 +1,11 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const PARAMS_PATH = '/tmp/pipeline-parameters.json';
|
||||
|
||||
const content = JSON.parse(fs.readFileSync(PARAMS_PATH, 'utf-8'));
|
||||
|
||||
// Choose resource class for linux hosts
|
||||
const currentBranch = process.env.CIRCLE_BRANCH || '';
|
||||
content['large-linux-executor'] = /^pull\/[0-9-]+$/.test(currentBranch) ? '2xlarge' : 'electronjs/aks-linux-large';
|
||||
|
||||
fs.writeFileSync(PARAMS_PATH, JSON.stringify(content));
|
||||
@@ -3,5 +3,6 @@
|
||||
set -e
|
||||
|
||||
mkdir -p ~/.ssh
|
||||
echo "|1|B3r+7aO0/x90IdefihIjxIoJrrk=|OJddGDfhbuLFc1bUyy84hhIw57M= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|
||||
|1|rGlEvW55DtzNZp+pzw9gvyOyKi4=|LLWr+7qlkAlw3YGGVfLHHxB/kR0= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==" >> ~/.ssh/known_hosts
|
||||
echo "github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
|
||||
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
|
||||
github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=" >> ~/.ssh/known_hosts
|
||||
|
||||
@@ -107,7 +107,7 @@ for:
|
||||
- ps: .\src\electron\script\start-goma.ps1 -gomaDir $env:LOCAL_GOMA_DIR
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$goma_login = python $env:LOCAL_GOMA_DIR\goma_auth.py info
|
||||
$goma_login = python3 $env:LOCAL_GOMA_DIR\goma_auth.py info
|
||||
if ($goma_login -eq 'Login as Fermi Planck') {
|
||||
Write-warning "Goma authentication is correct";
|
||||
} else {
|
||||
@@ -157,7 +157,7 @@ for:
|
||||
- ninja -C out/Default electron:hunspell_dictionaries_zip
|
||||
- ninja -C out/Default electron:electron_chromedriver_zip
|
||||
- ninja -C out/Default third_party/electron_node:headers
|
||||
- python %LOCAL_GOMA_DIR%\goma_ctl.py stat
|
||||
- python3 %LOCAL_GOMA_DIR%\goma_ctl.py stat
|
||||
- ps: >-
|
||||
Get-CimInstance -Namespace root\cimv2 -Class Win32_product | Select vendor, description, @{l='install_location';e='InstallLocation'}, @{l='install_date';e='InstallDate'}, @{l='install_date_2';e='InstallDate2'}, caption, version, name, @{l='sku_number';e='SKUNumber'} | ConvertTo-Json | Out-File -Encoding utf8 -FilePath .\installed_software.json
|
||||
- python3 electron/build/profile_toolchain.py --output-json=out/Default/windows_toolchain_profile.json
|
||||
@@ -178,6 +178,30 @@ for:
|
||||
7z a pdb.zip out\Default\*.pdb
|
||||
}
|
||||
- python3 electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.win.%TARGET_ARCH%.manifest
|
||||
- ps: |
|
||||
cd C:\projects\src
|
||||
$missing_artifacts = $false
|
||||
if ($env:SHOULD_SKIP_ARTIFACT_VALIDATION -eq 'true') {
|
||||
Write-warning "Skipping artifact validation for doc-only PR"
|
||||
} else {
|
||||
$artifacts_to_validate = 'dist.zip','windows_toolchain_profile.json','shell_browser_ui_unittests.exe','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib','hunspell_dictionaries.zip'
|
||||
foreach($artifact_name in $artifacts_to_validate) {
|
||||
if ($artifact_name -eq 'ffmpeg.zip') {
|
||||
$artifact_file = "out\ffmpeg\ffmpeg.zip"
|
||||
} elseif ($artifact_name -eq 'node_headers.zip') {
|
||||
$artifact_file = $artifact_name
|
||||
} else {
|
||||
$artifact_file = "out\Default\$artifact_name"
|
||||
}
|
||||
if (-not(Test-Path $artifact_file)) {
|
||||
Write-warning "$artifact_name is missing and cannot be added to artifacts"
|
||||
$missing_artifacts = $true
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($missing_artifacts) {
|
||||
throw "Build failed due to missing artifacts"
|
||||
}
|
||||
|
||||
deploy_script:
|
||||
- cd electron
|
||||
@@ -203,7 +227,7 @@ for:
|
||||
- if exist node_headers.zip (appveyor-retry appveyor PushArtifact node_headers.zip)
|
||||
- if exist out\Default\mksnapshot.zip (appveyor-retry appveyor PushArtifact out\Default\mksnapshot.zip)
|
||||
- if exist out\Default\hunspell_dictionaries.zip (appveyor-retry appveyor PushArtifact out\Default\hunspell_dictionaries.zip)
|
||||
- if exist out\Default\electron.lib (appveyor-retry appveyor PushArtifact out\Default\electron.lib)
|
||||
- if exist out\Default\electron.lib (appveyor-retry appveyor PushArtifact out\Default\electron.lib)
|
||||
- ps: >-
|
||||
if ((Test-Path "pdb.zip") -And ($env:GN_CONFIG -ne 'release')) {
|
||||
appveyor-retry appveyor PushArtifact pdb.zip
|
||||
@@ -234,7 +258,7 @@ for:
|
||||
# Download build artifacts
|
||||
$apiUrl = 'https://ci.appveyor.com/api'
|
||||
$build_info = Invoke-RestMethod -Method Get -Uri "$apiUrl/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/builds/$env:APPVEYOR_BUILD_ID"
|
||||
$artifacts_to_download = @('dist.zip','ffmpeg.zip','node_headers.zip','pdb.zip','electron.lib')
|
||||
$artifacts_to_download = @('dist.zip','ffmpeg.zip','node_headers.zip','electron.lib')
|
||||
foreach ($job in $build_info.build.jobs) {
|
||||
if ($job.name -eq "Build Arm on X64 Windows") {
|
||||
$jobId = $job.jobId
|
||||
@@ -246,10 +270,13 @@ for:
|
||||
}
|
||||
Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts/$artifact_name" -OutFile $outfile
|
||||
}
|
||||
# Uncomment the following lines to download the pdb.zip to show real stacktraces when crashes happen during testing
|
||||
# Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts/pdb.zip" -OutFile pdb.zip
|
||||
# 7z x -y -osrc pdb.zip
|
||||
}
|
||||
}
|
||||
- ps: |
|
||||
$out_default_zips = @('dist.zip','pdb.zip')
|
||||
$out_default_zips = @('dist.zip')
|
||||
foreach($zip_name in $out_default_zips) {
|
||||
7z x -y -osrc\out\Default $zip_name
|
||||
}
|
||||
|
||||
33
appveyor.yml
33
appveyor.yml
@@ -105,7 +105,7 @@ for:
|
||||
- ps: .\src\electron\script\start-goma.ps1 -gomaDir $env:LOCAL_GOMA_DIR
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$goma_login = python $env:LOCAL_GOMA_DIR\goma_auth.py info
|
||||
$goma_login = python3 $env:LOCAL_GOMA_DIR\goma_auth.py info
|
||||
if ($goma_login -eq 'Login as Fermi Planck') {
|
||||
Write-warning "Goma authentication is correct";
|
||||
} else {
|
||||
@@ -155,7 +155,7 @@ for:
|
||||
- ninja -C out/Default electron:hunspell_dictionaries_zip
|
||||
- ninja -C out/Default electron:electron_chromedriver_zip
|
||||
- ninja -C out/Default third_party/electron_node:headers
|
||||
- python %LOCAL_GOMA_DIR%\goma_ctl.py stat
|
||||
- pytho3 %LOCAL_GOMA_DIR%\goma_ctl.py stat
|
||||
- ps: >-
|
||||
Get-CimInstance -Namespace root\cimv2 -Class Win32_product | Select vendor, description, @{l='install_location';e='InstallLocation'}, @{l='install_date';e='InstallDate'}, @{l='install_date_2';e='InstallDate2'}, caption, version, name, @{l='sku_number';e='SKUNumber'} | ConvertTo-Json | Out-File -Encoding utf8 -FilePath .\installed_software.json
|
||||
- python3 electron/build/profile_toolchain.py --output-json=out/Default/windows_toolchain_profile.json
|
||||
@@ -176,6 +176,30 @@ for:
|
||||
7z a pdb.zip out\Default\*.pdb
|
||||
}
|
||||
- python3 electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.win.%TARGET_ARCH%.manifest
|
||||
- ps: |
|
||||
cd C:\projects\src
|
||||
$missing_artifacts = $false
|
||||
if ($env:SHOULD_SKIP_ARTIFACT_VALIDATION -eq 'true') {
|
||||
Write-warning "Skipping artifact validation for doc-only PR"
|
||||
} else {
|
||||
$artifacts_to_validate = 'dist.zip','windows_toolchain_profile.json','shell_browser_ui_unittests.exe','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib','hunspell_dictionaries.zip'
|
||||
foreach($artifact_name in $artifacts_to_validate) {
|
||||
if ($artifact_name -eq 'ffmpeg.zip') {
|
||||
$artifact_file = "out\ffmpeg\ffmpeg.zip"
|
||||
} elseif ($artifact_name -eq 'node_headers.zip') {
|
||||
$artifact_file = $artifact_name
|
||||
} else {
|
||||
$artifact_file = "out\Default\$artifact_name"
|
||||
}
|
||||
if (-not(Test-Path $artifact_file)) {
|
||||
Write-warning "$artifact_name is missing and cannot be added to artifacts"
|
||||
$missing_artifacts = $true
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($missing_artifacts) {
|
||||
throw "Build failed due to missing artifacts"
|
||||
}
|
||||
|
||||
deploy_script:
|
||||
- cd electron
|
||||
@@ -201,7 +225,7 @@ for:
|
||||
- if exist node_headers.zip (appveyor-retry appveyor PushArtifact node_headers.zip)
|
||||
- if exist out\Default\mksnapshot.zip (appveyor-retry appveyor PushArtifact out\Default\mksnapshot.zip)
|
||||
- if exist out\Default\hunspell_dictionaries.zip (appveyor-retry appveyor PushArtifact out\Default\hunspell_dictionaries.zip)
|
||||
- if exist out\Default\electron.lib (appveyor-retry appveyor PushArtifact out\Default\electron.lib)
|
||||
- if exist out\Default\electron.lib (appveyor-retry appveyor PushArtifact out\Default\electron.lib)
|
||||
- ps: >-
|
||||
if ((Test-Path "pdb.zip") -And ($env:GN_CONFIG -ne 'release')) {
|
||||
appveyor-retry appveyor PushArtifact pdb.zip
|
||||
@@ -242,6 +266,9 @@ for:
|
||||
}
|
||||
Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts/$artifact_name" -OutFile $outfile
|
||||
}
|
||||
# Uncomment the following lines to download the pdb.zip to show real stacktraces when crashes happen during testing
|
||||
# Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts/pdb.zip" -OutFile pdb.zip
|
||||
# 7z x -y -osrc pdb.zip
|
||||
}
|
||||
}
|
||||
- ps: |
|
||||
|
||||
@@ -27,7 +27,7 @@ const cachedArchives = new Map<string, NodeJS.AsarArchive>();
|
||||
const getOrCreateArchive = (archivePath: string) => {
|
||||
const isCached = cachedArchives.has(archivePath);
|
||||
if (isCached) {
|
||||
return cachedArchives.get(archivePath);
|
||||
return cachedArchives.get(archivePath)!;
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -39,6 +39,8 @@ const getOrCreateArchive = (archivePath: string) => {
|
||||
}
|
||||
};
|
||||
|
||||
process._getOrCreateArchive = getOrCreateArchive;
|
||||
|
||||
const asarRe = /\.asar/i;
|
||||
|
||||
// Separate asar package's path from full path.
|
||||
|
||||
@@ -114,5 +114,11 @@ for (const name of events) {
|
||||
}
|
||||
|
||||
// Deprecation.
|
||||
deprecate.event(app, 'gpu-process-crashed', 'child-process-gone');
|
||||
deprecate.event(app, 'renderer-process-crashed', 'render-process-gone');
|
||||
deprecate.event(app, 'gpu-process-crashed', 'child-process-gone', () => {
|
||||
// the old event is still emitted by App::OnGpuProcessCrashed()
|
||||
return undefined;
|
||||
});
|
||||
|
||||
deprecate.event(app, 'renderer-process-crashed', 'render-process-gone', (event: Electron.Event, webContents: Electron.WebContents, details: Electron.RenderProcessGoneDetails) => {
|
||||
return [event, webContents, details.reason === 'killed'];
|
||||
});
|
||||
|
||||
@@ -656,8 +656,8 @@ WebContents.prototype._init = function () {
|
||||
ipcMain.emit(channel, event, message);
|
||||
});
|
||||
|
||||
this.on('crashed', (event, ...args) => {
|
||||
app.emit('renderer-process-crashed', event, this, ...args);
|
||||
deprecate.event(this, 'crashed', 'render-process-gone', (event: Electron.Event, details: Electron.RenderProcessGoneDetails) => {
|
||||
return [event, details.reason === 'killed'];
|
||||
});
|
||||
|
||||
this.on('render-process-gone', (event, details) => {
|
||||
|
||||
@@ -84,11 +84,20 @@ const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
let packagePath = null;
|
||||
let packageJson = null;
|
||||
const searchPaths: string[] = v8Util.getHiddenValue(global, 'appSearchPaths');
|
||||
const searchPathsOnlyLoadASAR: boolean = v8Util.getHiddenValue(global, 'appSearchPathsOnlyLoadASAR');
|
||||
// Borrow the _getOrCreateArchive asar helper
|
||||
const getOrCreateArchive = process._getOrCreateArchive;
|
||||
delete process._getOrCreateArchive;
|
||||
|
||||
if (process.resourcesPath) {
|
||||
for (packagePath of searchPaths) {
|
||||
try {
|
||||
packagePath = path.join(process.resourcesPath, packagePath);
|
||||
if (searchPathsOnlyLoadASAR) {
|
||||
if (!getOrCreateArchive?.(packagePath)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
packageJson = Module._load(path.join(packagePath, 'package.json'));
|
||||
break;
|
||||
} catch {
|
||||
|
||||
@@ -66,14 +66,17 @@ export function renameFunction<T extends Function> (fn: T, newName: string): T {
|
||||
}
|
||||
|
||||
// change the name of an event
|
||||
export function event (emitter: NodeJS.EventEmitter, oldName: string, newName: string) {
|
||||
export function event (emitter: NodeJS.EventEmitter, oldName: string, newName: string, transformer: (...args: any[]) => any[] | undefined = (...args) => args) {
|
||||
const warn = newName.startsWith('-') /* internal event */
|
||||
? warnOnce(`${oldName} event`)
|
||||
: warnOnce(`${oldName} event`, `${newName} event`);
|
||||
return emitter.on(newName, function (this: NodeJS.EventEmitter, ...args) {
|
||||
if (this.listenerCount(oldName) !== 0) {
|
||||
warn();
|
||||
this.emit(oldName, ...args);
|
||||
const transformedArgs = transformer(...args);
|
||||
if (transformedArgs) {
|
||||
this.emit(oldName, ...transformedArgs);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,3 +4,4 @@ cherry-pick-ce029c91a662.patch
|
||||
cherry-pick-aed05b609629.patch
|
||||
translator_limit_the_size_of_private_variables_in_webgl_shaders.patch
|
||||
webgl_limit_total_size_of_private_data.patch
|
||||
cherry-pick-5486190be556.patch
|
||||
|
||||
41
patches/angle/cherry-pick-5486190be556.patch
Normal file
41
patches/angle/cherry-pick-5486190be556.patch
Normal file
@@ -0,0 +1,41 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Geoff Lang <geofflang@chromium.org>
|
||||
Date: Fri, 21 Jul 2023 13:45:52 -0400
|
||||
Subject: Fix read size validation for RGBX formats.
|
||||
|
||||
GL_RGBX8_ANGLE is the only format where the upload format is 3-channel
|
||||
RGB, whilethe download format is 4-channel RGBX. As such, the internal
|
||||
format corresponding to format+type expects 3-byte input/output. The
|
||||
format is fixed here for readPixels to output 4 bytes per pixel.
|
||||
|
||||
Bug: chromium:1458046
|
||||
Change-Id: Iec737ed64bade003cfab50dc5f595eb4875e81e4
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4706957
|
||||
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
(cherry picked from commit 430a4f559cbc2bcd5d026e8b36ee46ddd80e9651)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4765136
|
||||
Commit-Queue: Daniel Yip <danielyip@google.com>
|
||||
Auto-Submit: Daniel Yip <danielyip@google.com>
|
||||
(cherry picked from commit 4a372ad49ceddea6c13f79adb212a777ec770a66)
|
||||
|
||||
diff --git a/src/libANGLE/formatutils.cpp b/src/libANGLE/formatutils.cpp
|
||||
index 4014953311976b0f1ae2d1842e8fced75ffecfc9..6c8d3680b7a8bb78894120ca6cac7882827a98e4 100644
|
||||
--- a/src/libANGLE/formatutils.cpp
|
||||
+++ b/src/libANGLE/formatutils.cpp
|
||||
@@ -1710,7 +1710,15 @@ const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, GLenum type)
|
||||
GLuint InternalFormat::computePixelBytes(GLenum formatType) const
|
||||
{
|
||||
const auto &typeInfo = GetTypeInfo(formatType);
|
||||
- GLuint components = typeInfo.specialInterpretation ? 1u : componentCount;
|
||||
+ GLuint components = componentCount;
|
||||
+ if (sizedInternalFormat == GL_RGBX8_ANGLE)
|
||||
+ {
|
||||
+ components = 4;
|
||||
+ }
|
||||
+ else if (typeInfo.specialInterpretation)
|
||||
+ {
|
||||
+ components = 1;
|
||||
+ }
|
||||
return components * typeInfo.bytes;
|
||||
}
|
||||
|
||||
@@ -166,3 +166,10 @@ m114_merge_fix_a_crash_caused_by_calling_trace_event.patch
|
||||
base_do_not_use_va_args_twice_in_asprintf.patch
|
||||
cherry-pick-85beff6fd302.patch
|
||||
m114_webcodecs_fix_crash_when_changing_temporal_layer_count_in_av1.patch
|
||||
cherry-pick-933b9fad3a53.patch
|
||||
cherry-pick-b03973561862.patch
|
||||
cherry-pick-c60a1ab717c7.patch
|
||||
networkcontext_don_t_access_url_loader_factories_during_destruction.patch
|
||||
don_t_keep_pointer_to_popped_stack_memory_for_has.patch
|
||||
cherry-pick-35c06406a658.patch
|
||||
cherry-pick-b11e7d07a6f4.patch
|
||||
|
||||
162
patches/chromium/cherry-pick-35c06406a658.patch
Normal file
162
patches/chromium/cherry-pick-35c06406a658.patch
Normal file
@@ -0,0 +1,162 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Guido Urdaneta <guidou@chromium.org>
|
||||
Date: Thu, 24 Aug 2023 11:12:43 +0000
|
||||
Subject: Handle object destruction in MediaStreamDeviceObserver
|
||||
|
||||
MSDO executes some callbacks that can result in the destruction of
|
||||
MSDO upon an external event such as removing a media device or the
|
||||
user revoking permission.
|
||||
This CL adds code to detect this condition and prevent further
|
||||
processing that would result in UAF. It also removes some invalid
|
||||
DCHECKs.
|
||||
|
||||
Drive-by: minor style fixes
|
||||
|
||||
(cherry picked from commit 7337133682ab0404b753c563dde2ae2b1dc13171)
|
||||
|
||||
Bug: 1472492, b/296997707
|
||||
Change-Id: I76f019bb110e7d9cca276444bc23a7e43114d2cc
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4798398
|
||||
Reviewed-by: Palak Agarwal <agpalak@chromium.org>
|
||||
Commit-Queue: Guido Urdaneta <guidou@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1186452}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4810035
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5845@{#1586}
|
||||
Cr-Branched-From: 5a5dff63a4a4c63b9b18589819bebb2566c85443-refs/heads/main@{#1160321}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_device_observer.cc b/third_party/blink/renderer/modules/mediastream/media_stream_device_observer.cc
|
||||
index c553b70b3b3be78a1d6636037009210bc280e02e..ece0caa8dbeaadf8f2a78bfb5c76e6db6023f1b5 100644
|
||||
--- a/third_party/blink/renderer/modules/mediastream/media_stream_device_observer.cc
|
||||
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_device_observer.cc
|
||||
@@ -37,11 +37,11 @@ MediaStreamDeviceObserver::MediaStreamDeviceObserver(LocalFrame* frame) {
|
||||
if (frame) {
|
||||
frame->GetInterfaceRegistry()->AddInterface(WTF::BindRepeating(
|
||||
&MediaStreamDeviceObserver::BindMediaStreamDeviceObserverReceiver,
|
||||
- WTF::Unretained(this)));
|
||||
+ weak_factory_.GetWeakPtr()));
|
||||
}
|
||||
}
|
||||
|
||||
-MediaStreamDeviceObserver::~MediaStreamDeviceObserver() {}
|
||||
+MediaStreamDeviceObserver::~MediaStreamDeviceObserver() = default;
|
||||
|
||||
MediaStreamDevices MediaStreamDeviceObserver::GetNonScreenCaptureDevices() {
|
||||
MediaStreamDevices video_devices;
|
||||
@@ -70,13 +70,21 @@ void MediaStreamDeviceObserver::OnDeviceStopped(
|
||||
}
|
||||
|
||||
for (Stream& stream : it->value) {
|
||||
- if (IsAudioInputMediaType(device.type))
|
||||
+ if (IsAudioInputMediaType(device.type)) {
|
||||
RemoveStreamDeviceFromArray(device, &stream.audio_devices);
|
||||
- else
|
||||
+ } else {
|
||||
RemoveStreamDeviceFromArray(device, &stream.video_devices);
|
||||
-
|
||||
- if (stream.on_device_stopped_cb)
|
||||
+ }
|
||||
+ if (stream.on_device_stopped_cb) {
|
||||
+ // Running `stream.on_device_stopped_cb` can destroy `this`. Use a weak
|
||||
+ // pointer to detect that condition, and stop processing if it happens.
|
||||
+ base::WeakPtr<MediaStreamDeviceObserver> weak_this =
|
||||
+ weak_factory_.GetWeakPtr();
|
||||
stream.on_device_stopped_cb.Run(device);
|
||||
+ if (!weak_this) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
// |it| could have already been invalidated in the function call above. So we
|
||||
@@ -85,8 +93,9 @@ void MediaStreamDeviceObserver::OnDeviceStopped(
|
||||
// iterator from |label_stream_map_| (https://crbug.com/616884). Future work
|
||||
// needs to be done to resolve this re-entrancy issue.
|
||||
it = label_stream_map_.find(label);
|
||||
- if (it == label_stream_map_.end())
|
||||
+ if (it == label_stream_map_.end()) {
|
||||
return;
|
||||
+ }
|
||||
|
||||
Vector<Stream>& streams = it->value;
|
||||
auto* stream_it = streams.begin();
|
||||
@@ -122,8 +131,16 @@ void MediaStreamDeviceObserver::OnDeviceChanged(
|
||||
DCHECK_EQ(1u, it->value.size());
|
||||
|
||||
Stream* stream = &it->value[0];
|
||||
- if (stream->on_device_changed_cb)
|
||||
+ if (stream->on_device_changed_cb) {
|
||||
+ // Running `stream->on_device_changed_cb` can destroy `this`. Use a weak
|
||||
+ // pointer to detect that condition, and stop processing if it happens.
|
||||
+ base::WeakPtr<MediaStreamDeviceObserver> weak_this =
|
||||
+ weak_factory_.GetWeakPtr();
|
||||
stream->on_device_changed_cb.Run(old_device, new_device);
|
||||
+ if (!weak_this) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
// Update device list only for device changing. Removing device will be
|
||||
// handled in its own callback.
|
||||
@@ -278,9 +295,9 @@ void MediaStreamDeviceObserver::RemoveStreamDevice(
|
||||
streams_to_remove.push_back(entry.key);
|
||||
}
|
||||
}
|
||||
- DCHECK(device_found);
|
||||
- for (const String& label : streams_to_remove)
|
||||
+ for (const String& label : streams_to_remove) {
|
||||
label_stream_map_.erase(label);
|
||||
+ }
|
||||
}
|
||||
|
||||
base::UnguessableToken MediaStreamDeviceObserver::GetAudioSessionId(
|
||||
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_device_observer.h b/third_party/blink/renderer/modules/mediastream/media_stream_device_observer.h
|
||||
index 55aba2c4e5bd046a008590436ed8eefa4f099d5c..c5a8b5b1e31011f5d2f9f2064cabb10a74c25bf7 100644
|
||||
--- a/third_party/blink/renderer/modules/mediastream/media_stream_device_observer.h
|
||||
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_device_observer.h
|
||||
@@ -116,6 +116,7 @@ class MODULES_EXPORT MediaStreamDeviceObserver
|
||||
|
||||
using LabelStreamMap = HashMap<String, Vector<Stream>>;
|
||||
LabelStreamMap label_stream_map_;
|
||||
+ base::WeakPtrFactory<MediaStreamDeviceObserver> weak_factory_{this};
|
||||
};
|
||||
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/platform/exported/mediastream/web_platform_media_stream_source.cc b/third_party/blink/renderer/platform/exported/mediastream/web_platform_media_stream_source.cc
|
||||
index be69e8c9741faf0728022ff1cc89ccf8d89a0629..b9f5e9c86537dace6f42e4c92ac255990eb910f7 100644
|
||||
--- a/third_party/blink/renderer/platform/exported/mediastream/web_platform_media_stream_source.cc
|
||||
+++ b/third_party/blink/renderer/platform/exported/mediastream/web_platform_media_stream_source.cc
|
||||
@@ -31,10 +31,12 @@ void WebPlatformMediaStreamSource::StopSource() {
|
||||
|
||||
void WebPlatformMediaStreamSource::FinalizeStopSource() {
|
||||
DCHECK(task_runner_->BelongsToCurrentThread());
|
||||
- if (!stop_callback_.is_null())
|
||||
+ if (!stop_callback_.is_null()) {
|
||||
std::move(stop_callback_).Run(Owner());
|
||||
- if (Owner())
|
||||
+ }
|
||||
+ if (Owner()) {
|
||||
Owner().SetReadyState(WebMediaStreamSource::kReadyStateEnded);
|
||||
+ }
|
||||
}
|
||||
|
||||
void WebPlatformMediaStreamSource::SetSourceMuted(bool is_muted) {
|
||||
@@ -42,8 +44,9 @@ void WebPlatformMediaStreamSource::SetSourceMuted(bool is_muted) {
|
||||
// Although this change is valid only if the ready state isn't already Ended,
|
||||
// there's code further along (like in MediaStreamTrack) which filters
|
||||
// that out already.
|
||||
- if (!Owner())
|
||||
+ if (!Owner()) {
|
||||
return;
|
||||
+ }
|
||||
Owner().SetReadyState(is_muted ? WebMediaStreamSource::kReadyStateMuted
|
||||
: WebMediaStreamSource::kReadyStateLive);
|
||||
}
|
||||
@@ -72,7 +75,6 @@ void WebPlatformMediaStreamSource::SetStopCallback(
|
||||
|
||||
void WebPlatformMediaStreamSource::ResetSourceStoppedCallback() {
|
||||
DCHECK(task_runner_->BelongsToCurrentThread());
|
||||
- DCHECK(!stop_callback_.is_null());
|
||||
stop_callback_.Reset();
|
||||
}
|
||||
|
||||
404
patches/chromium/cherry-pick-933b9fad3a53.patch
Normal file
404
patches/chromium/cherry-pick-933b9fad3a53.patch
Normal file
@@ -0,0 +1,404 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Fri, 9 Jun 2023 07:49:02 +0000
|
||||
Subject: Reland "ipcz: Refactor FragmentDescriptor decode"
|
||||
|
||||
This is a reland of commit 17dd18d1f2194089b8433e0ca334c81343b591e2
|
||||
|
||||
Original change's description:
|
||||
> ipcz: Refactor FragmentDescriptor decode
|
||||
>
|
||||
> Funnels untrusted FragmentDescriptor mapping through a new
|
||||
> Fragment::MappedFromDescriptor helper. See the linked bug
|
||||
> for more details.
|
||||
>
|
||||
> Fixed: 1450899
|
||||
> Change-Id: I4c7751b9f4299da4a13c0becc1b889160a0c6e66
|
||||
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4599218
|
||||
> Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||
> Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
> Cr-Commit-Position: refs/heads/main@{#1155133}
|
||||
|
||||
Change-Id: I86ee9118a30dea59d837c377a1f751b20a85a3c3
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4602794
|
||||
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Cr-Commit-Position: refs/heads/main@{#1155397}
|
||||
|
||||
diff --git a/third_party/ipcz/src/BUILD.gn b/third_party/ipcz/src/BUILD.gn
|
||||
index 8b98d75aaa8f6d4df22c872cb9261381647256eb..7dabb9e9d4f3b0c00ce0acbcb2b7ff0e6085fc58 100644
|
||||
--- a/third_party/ipcz/src/BUILD.gn
|
||||
+++ b/third_party/ipcz/src/BUILD.gn
|
||||
@@ -210,6 +210,7 @@ ipcz_source_set("impl") {
|
||||
"ipcz/api_object.h",
|
||||
"ipcz/block_allocator.h",
|
||||
"ipcz/box.h",
|
||||
+ "ipcz/buffer_id.h",
|
||||
"ipcz/buffer_pool.h",
|
||||
"ipcz/driver_memory.h",
|
||||
"ipcz/driver_memory_mapping.h",
|
||||
@@ -253,7 +254,6 @@ ipcz_source_set("impl") {
|
||||
"ipcz/block_allocator_pool.cc",
|
||||
"ipcz/block_allocator_pool.h",
|
||||
"ipcz/box.cc",
|
||||
- "ipcz/buffer_id.h",
|
||||
"ipcz/buffer_pool.cc",
|
||||
"ipcz/driver_memory.cc",
|
||||
"ipcz/driver_memory_mapping.cc",
|
||||
@@ -376,6 +376,7 @@ ipcz_source_set("ipcz_tests_sources") {
|
||||
"ipcz/driver_memory_test.cc",
|
||||
"ipcz/driver_object_test.cc",
|
||||
"ipcz/driver_transport_test.cc",
|
||||
+ "ipcz/fragment_test.cc",
|
||||
"ipcz/message_test.cc",
|
||||
"ipcz/node_connector_test.cc",
|
||||
"ipcz/node_link_memory_test.cc",
|
||||
diff --git a/third_party/ipcz/src/ipcz/block_allocator_pool.cc b/third_party/ipcz/src/ipcz/block_allocator_pool.cc
|
||||
index bd464f897d1fcbde03941ee334d0e1706bf59868..1b9d50b2c77c046d815a94d7760328c8b379ecab 100644
|
||||
--- a/third_party/ipcz/src/ipcz/block_allocator_pool.cc
|
||||
+++ b/third_party/ipcz/src/ipcz/block_allocator_pool.cc
|
||||
@@ -86,7 +86,7 @@ Fragment BlockAllocatorPool::Allocate() {
|
||||
FragmentDescriptor descriptor(
|
||||
entry->buffer_id, checked_cast<uint32_t>(offset),
|
||||
checked_cast<uint32_t>(allocator.block_size()));
|
||||
- return Fragment(descriptor, block);
|
||||
+ return Fragment::FromDescriptorUnsafe(descriptor, block);
|
||||
}
|
||||
|
||||
// Allocation from the active allocator failed. Try another if available.
|
||||
diff --git a/third_party/ipcz/src/ipcz/buffer_pool.cc b/third_party/ipcz/src/ipcz/buffer_pool.cc
|
||||
index 6881346d8f8532f070e5121da16f064ae4a9bdaf..27b23049848967f29f81b10ba4f8fa4ead14d2e2 100644
|
||||
--- a/third_party/ipcz/src/ipcz/buffer_pool.cc
|
||||
+++ b/third_party/ipcz/src/ipcz/buffer_pool.cc
|
||||
@@ -26,15 +26,11 @@ Fragment BufferPool::GetFragment(const FragmentDescriptor& descriptor) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
auto it = mappings_.find(descriptor.buffer_id());
|
||||
if (it == mappings_.end()) {
|
||||
- return Fragment(descriptor, nullptr);
|
||||
+ return Fragment::PendingFromDescriptor(descriptor);
|
||||
}
|
||||
|
||||
auto& [id, mapping] = *it;
|
||||
- if (descriptor.end() > mapping.bytes().size()) {
|
||||
- return {};
|
||||
- }
|
||||
-
|
||||
- return Fragment(descriptor, mapping.address_at(descriptor.offset()));
|
||||
+ return Fragment::MappedFromDescriptor(descriptor, mapping);
|
||||
}
|
||||
|
||||
bool BufferPool::AddBlockBuffer(
|
||||
diff --git a/third_party/ipcz/src/ipcz/buffer_pool_test.cc b/third_party/ipcz/src/ipcz/buffer_pool_test.cc
|
||||
index a009ffe1c20ade013a19b51eceee4faf334eb591..bff66c452a3e2c38b0f208cca1fa1a082f1ee871 100644
|
||||
--- a/third_party/ipcz/src/ipcz/buffer_pool_test.cc
|
||||
+++ b/third_party/ipcz/src/ipcz/buffer_pool_test.cc
|
||||
@@ -194,9 +194,11 @@ TEST_F(BufferPoolTest, BasicBlockAllocation) {
|
||||
pool.GetTotalBlockCapacity(kBlockSize));
|
||||
|
||||
// We can't free something that isn't a valid allocation.
|
||||
- EXPECT_FALSE(pool.FreeBlock(Fragment{{}, nullptr}));
|
||||
- EXPECT_FALSE(pool.FreeBlock(Fragment{{BufferId{1000}, 0, 1}, nullptr}));
|
||||
- EXPECT_FALSE(pool.FreeBlock(Fragment{{BufferId{0}, 0, 1}, bytes0.data()}));
|
||||
+ EXPECT_FALSE(pool.FreeBlock(Fragment::FromDescriptorUnsafe({}, nullptr)));
|
||||
+ EXPECT_FALSE(pool.FreeBlock(
|
||||
+ Fragment::FromDescriptorUnsafe({BufferId{1000}, 0, 1}, nullptr)));
|
||||
+ EXPECT_FALSE(pool.FreeBlock(
|
||||
+ Fragment::FromDescriptorUnsafe({BufferId{0}, 0, 1}, bytes0.data())));
|
||||
|
||||
// Allocate all available capacity.
|
||||
std::vector<Fragment> fragments;
|
||||
diff --git a/third_party/ipcz/src/ipcz/fragment.cc b/third_party/ipcz/src/ipcz/fragment.cc
|
||||
index 651d1c2fca5fe4fb69cdf61c6062bd8804ebf704..2ef4ed8dcfa0a56a73975a0b7dcc3f86bf5a83a0 100644
|
||||
--- a/third_party/ipcz/src/ipcz/fragment.cc
|
||||
+++ b/third_party/ipcz/src/ipcz/fragment.cc
|
||||
@@ -6,10 +6,38 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
+#include "ipcz/driver_memory_mapping.h"
|
||||
+#include "ipcz/fragment_descriptor.h"
|
||||
#include "third_party/abseil-cpp/absl/base/macros.h"
|
||||
+#include "util/safe_math.h"
|
||||
|
||||
namespace ipcz {
|
||||
|
||||
+// static
|
||||
+Fragment Fragment::MappedFromDescriptor(const FragmentDescriptor& descriptor,
|
||||
+ DriverMemoryMapping& mapping) {
|
||||
+ if (descriptor.is_null()) {
|
||||
+ return {};
|
||||
+ }
|
||||
+
|
||||
+ const uint32_t end = SaturatedAdd(descriptor.offset(), descriptor.size());
|
||||
+ if (end > mapping.bytes().size()) {
|
||||
+ return {};
|
||||
+ }
|
||||
+ return Fragment{descriptor, mapping.address_at(descriptor.offset())};
|
||||
+}
|
||||
+
|
||||
+// static
|
||||
+Fragment Fragment::PendingFromDescriptor(const FragmentDescriptor& descriptor) {
|
||||
+ return Fragment{descriptor, nullptr};
|
||||
+}
|
||||
+
|
||||
+// static
|
||||
+Fragment Fragment::FromDescriptorUnsafe(const FragmentDescriptor& descriptor,
|
||||
+ void* base_address) {
|
||||
+ return Fragment{descriptor, base_address};
|
||||
+}
|
||||
+
|
||||
Fragment::Fragment(const FragmentDescriptor& descriptor, void* address)
|
||||
: descriptor_(descriptor), address_(address) {
|
||||
// If `address` is non-null, the descriptor must also be. Note that the
|
||||
diff --git a/third_party/ipcz/src/ipcz/fragment.h b/third_party/ipcz/src/ipcz/fragment.h
|
||||
index c0151fdcf4b418680172a29d1c0d28b58a5807cd..de65f087b0bc27fd59ab88e23130d5ce0d345a8a 100644
|
||||
--- a/third_party/ipcz/src/ipcz/fragment.h
|
||||
+++ b/third_party/ipcz/src/ipcz/fragment.h
|
||||
@@ -14,21 +14,32 @@
|
||||
|
||||
namespace ipcz {
|
||||
|
||||
+class DriverMemoryMapping;
|
||||
+
|
||||
// Represents a span of memory located within the shared memory regions owned by
|
||||
// a NodeLinkMemory, via BufferPool. This is essentially a FragmentDescriptor
|
||||
// plus the actual mapped address of the given buffer and offset.
|
||||
struct Fragment {
|
||||
constexpr Fragment() = default;
|
||||
|
||||
- // Constructs a new Fragment over `descriptor`, mapped to `address`. If
|
||||
- // `address` is null, the Fragment is considered "pending" -- it has a
|
||||
- // potentially valid descriptor, but could not be resolved to a mapped address
|
||||
- // yet (e.g. because the relevant BufferPool doesn't have the identified
|
||||
- // buffer mapped yet.)
|
||||
- Fragment(const FragmentDescriptor& descriptor, void* address);
|
||||
Fragment(const Fragment&);
|
||||
Fragment& operator=(const Fragment&);
|
||||
|
||||
+ // Returns a new concrete Fragment corresponding to `descriptor` within the
|
||||
+ // context of `mapping`. This validates that the fragment's bounds fall within
|
||||
+ // the bounds of `mapping`. If `descriptor` was null or validation fails, this
|
||||
+ // returns a null Fragment.
|
||||
+ static Fragment MappedFromDescriptor(const FragmentDescriptor& descriptor,
|
||||
+ DriverMemoryMapping& mapping);
|
||||
+
|
||||
+ // Returns a pending Fragment corresponding to `descriptor`.
|
||||
+ static Fragment PendingFromDescriptor(const FragmentDescriptor& descriptor);
|
||||
+
|
||||
+ // Returns a Fragment corresponding to `descriptor`, with the starting address
|
||||
+ // already mapped to `address`.
|
||||
+ static Fragment FromDescriptorUnsafe(const FragmentDescriptor& descriptor,
|
||||
+ void* address);
|
||||
+
|
||||
// A null fragment is a fragment with a null descriptor, meaning it does not
|
||||
// reference a valid buffer ID.
|
||||
bool is_null() const { return descriptor_.is_null(); }
|
||||
@@ -66,6 +77,13 @@ struct Fragment {
|
||||
}
|
||||
|
||||
private:
|
||||
+ // Constructs a new Fragment over `descriptor`, mapped to `address`. If
|
||||
+ // `address` is null, the Fragment is considered "pending" -- it has a
|
||||
+ // potentially valid descriptor, but could not be resolved to a mapped address
|
||||
+ // yet (e.g. because the relevant BufferPool doesn't have the identified
|
||||
+ // buffer mapped yet.)
|
||||
+ Fragment(const FragmentDescriptor& descriptor, void* address);
|
||||
+
|
||||
FragmentDescriptor descriptor_;
|
||||
|
||||
// The actual mapped address corresponding to `descriptor_`.
|
||||
diff --git a/third_party/ipcz/src/ipcz/fragment_descriptor.h b/third_party/ipcz/src/ipcz/fragment_descriptor.h
|
||||
index b247215fd5e5f7c69e521416614465b0321f5d83..aeaa7da9c82761854948d009e7f245c9c9d042c7 100644
|
||||
--- a/third_party/ipcz/src/ipcz/fragment_descriptor.h
|
||||
+++ b/third_party/ipcz/src/ipcz/fragment_descriptor.h
|
||||
@@ -39,7 +39,6 @@ struct IPCZ_ALIGN(8) FragmentDescriptor {
|
||||
BufferId buffer_id() const { return buffer_id_; }
|
||||
uint32_t offset() const { return offset_; }
|
||||
uint32_t size() const { return size_; }
|
||||
- uint32_t end() const { return offset_ + size_; }
|
||||
|
||||
private:
|
||||
// Identifies the shared memory buffer in which the memory resides. This ID is
|
||||
diff --git a/third_party/ipcz/src/ipcz/fragment_test.cc b/third_party/ipcz/src/ipcz/fragment_test.cc
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e6b6baa6cb2f1fbdfb89d87d644f63681c797c01
|
||||
--- /dev/null
|
||||
+++ b/third_party/ipcz/src/ipcz/fragment_test.cc
|
||||
@@ -0,0 +1,102 @@
|
||||
+// Copyright 2023 The Chromium Authors
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+#include "ipcz/fragment.h"
|
||||
+
|
||||
+#include <algorithm>
|
||||
+#include <cstring>
|
||||
+#include <limits>
|
||||
+#include <string>
|
||||
+#include <utility>
|
||||
+
|
||||
+#include "ipcz/buffer_id.h"
|
||||
+#include "ipcz/driver_memory.h"
|
||||
+#include "ipcz/driver_memory_mapping.h"
|
||||
+#include "reference_drivers/sync_reference_driver.h"
|
||||
+#include "testing/gtest/include/gtest/gtest.h"
|
||||
+
|
||||
+namespace ipcz {
|
||||
+namespace {
|
||||
+
|
||||
+const IpczDriver& kTestDriver = reference_drivers::kSyncReferenceDriver;
|
||||
+
|
||||
+using FragmentTest = testing::Test;
|
||||
+
|
||||
+TEST_F(FragmentTest, FromDescriptorUnsafe) {
|
||||
+ char kBuffer[] = "Hello, world!";
|
||||
+
|
||||
+ Fragment f = Fragment::FromDescriptorUnsafe({BufferId{0}, 1, 4}, kBuffer + 1);
|
||||
+ EXPECT_FALSE(f.is_null());
|
||||
+ EXPECT_FALSE(f.is_pending());
|
||||
+ EXPECT_EQ(1u, f.offset());
|
||||
+ EXPECT_EQ(4u, f.size());
|
||||
+ EXPECT_EQ("ello", std::string(f.bytes().begin(), f.bytes().end()));
|
||||
+
|
||||
+ f = Fragment::FromDescriptorUnsafe({BufferId{0}, 7, 6}, kBuffer + 7);
|
||||
+ EXPECT_FALSE(f.is_null());
|
||||
+ EXPECT_FALSE(f.is_pending());
|
||||
+ EXPECT_EQ(7u, f.offset());
|
||||
+ EXPECT_EQ(6u, f.size());
|
||||
+ EXPECT_EQ("world!", std::string(f.bytes().begin(), f.bytes().end()));
|
||||
+}
|
||||
+
|
||||
+TEST_F(FragmentTest, PendingFromDescriptor) {
|
||||
+ Fragment f = Fragment::PendingFromDescriptor({BufferId{0}, 5, 42});
|
||||
+ EXPECT_TRUE(f.is_pending());
|
||||
+ EXPECT_FALSE(f.is_null());
|
||||
+ EXPECT_EQ(5u, f.offset());
|
||||
+ EXPECT_EQ(42u, f.size());
|
||||
+
|
||||
+ f = Fragment::PendingFromDescriptor({kInvalidBufferId, 0, 0});
|
||||
+ EXPECT_TRUE(f.is_null());
|
||||
+ EXPECT_FALSE(f.is_pending());
|
||||
+}
|
||||
+
|
||||
+TEST_F(FragmentTest, NullMappedFromDescriptor) {
|
||||
+ constexpr size_t kDataSize = 32;
|
||||
+ DriverMemory memory(kTestDriver, kDataSize);
|
||||
+ auto mapping = memory.Map();
|
||||
+
|
||||
+ Fragment f =
|
||||
+ Fragment::MappedFromDescriptor({kInvalidBufferId, 0, 0}, mapping);
|
||||
+ EXPECT_TRUE(f.is_null());
|
||||
+}
|
||||
+
|
||||
+TEST_F(FragmentTest, InvalidMappedFromDescriptor) {
|
||||
+ constexpr size_t kDataSize = 32;
|
||||
+ DriverMemory memory(kTestDriver, kDataSize);
|
||||
+ auto mapping = memory.Map();
|
||||
+
|
||||
+ Fragment f;
|
||||
+
|
||||
+ // Offset out of bounds
|
||||
+ f = Fragment::MappedFromDescriptor({BufferId{0}, kDataSize, 1}, mapping);
|
||||
+ EXPECT_TRUE(f.is_null());
|
||||
+
|
||||
+ // Tail out of bounds
|
||||
+ f = Fragment::MappedFromDescriptor({BufferId{0}, 0, kDataSize + 5}, mapping);
|
||||
+ EXPECT_TRUE(f.is_null());
|
||||
+
|
||||
+ // Tail overflow
|
||||
+ f = Fragment::MappedFromDescriptor(
|
||||
+ {BufferId{0}, std::numeric_limits<uint32_t>::max(), 2}, mapping);
|
||||
+ EXPECT_TRUE(f.is_null());
|
||||
+}
|
||||
+
|
||||
+TEST_F(FragmentTest, ValidMappedFromDescriptor) {
|
||||
+ const char kData[] = "0123456789abcdef";
|
||||
+ DriverMemory memory(kTestDriver, std::size(kData));
|
||||
+ auto mapping = memory.Map();
|
||||
+ memcpy(mapping.bytes().data(), kData, std::size(kData));
|
||||
+
|
||||
+ Fragment f = Fragment::MappedFromDescriptor({BufferId{0}, 2, 11}, mapping);
|
||||
+ EXPECT_FALSE(f.is_null());
|
||||
+ EXPECT_FALSE(f.is_pending());
|
||||
+ EXPECT_EQ(2u, f.offset());
|
||||
+ EXPECT_EQ(11u, f.size());
|
||||
+ EXPECT_EQ("23456789abc", std::string(f.bytes().begin(), f.bytes().end()));
|
||||
+}
|
||||
+
|
||||
+} // namespace
|
||||
+} // namespace ipcz
|
||||
diff --git a/third_party/ipcz/src/ipcz/node_link_memory.cc b/third_party/ipcz/src/ipcz/node_link_memory.cc
|
||||
index 0cfadfa02aa4b7058e04c3b0255412a0d11aed87..9f920faf31748a6c4213045e31331af2a865bb4f 100644
|
||||
--- a/third_party/ipcz/src/ipcz/node_link_memory.cc
|
||||
+++ b/third_party/ipcz/src/ipcz/node_link_memory.cc
|
||||
@@ -278,8 +278,9 @@ FragmentRef<RouterLinkState> NodeLinkMemory::GetInitialRouterLinkState(
|
||||
FragmentDescriptor descriptor(kPrimaryBufferId,
|
||||
ToOffset(state, primary_buffer_memory_.data()),
|
||||
sizeof(RouterLinkState));
|
||||
- return FragmentRef<RouterLinkState>(RefCountedFragment::kUnmanagedRef,
|
||||
- Fragment(descriptor, state));
|
||||
+ return FragmentRef<RouterLinkState>(
|
||||
+ RefCountedFragment::kUnmanagedRef,
|
||||
+ Fragment::FromDescriptorUnsafe(descriptor, state));
|
||||
}
|
||||
|
||||
Fragment NodeLinkMemory::GetFragment(const FragmentDescriptor& descriptor) {
|
||||
diff --git a/third_party/ipcz/src/ipcz/ref_counted_fragment_test.cc b/third_party/ipcz/src/ipcz/ref_counted_fragment_test.cc
|
||||
index d5a2243a693597e43f87f116f80599fde383cb59..220c3556a261c5caab7194114af4cf375d9af683 100644
|
||||
--- a/third_party/ipcz/src/ipcz/ref_counted_fragment_test.cc
|
||||
+++ b/third_party/ipcz/src/ipcz/ref_counted_fragment_test.cc
|
||||
@@ -64,7 +64,8 @@ TEST_F(RefCountedFragmentTest, SimpleRef) {
|
||||
|
||||
FragmentRef<TestObject> ref(
|
||||
RefCountedFragment::kUnmanagedRef,
|
||||
- Fragment(FragmentDescriptor(BufferId(0), 0, sizeof(object)), &object));
|
||||
+ Fragment::FromDescriptorUnsafe(
|
||||
+ FragmentDescriptor(BufferId(0), 0, sizeof(object)), &object));
|
||||
EXPECT_EQ(1, object.ref_count_for_testing());
|
||||
ref.reset();
|
||||
EXPECT_EQ(0, object.ref_count_for_testing());
|
||||
@@ -75,7 +76,8 @@ TEST_F(RefCountedFragmentTest, Copy) {
|
||||
|
||||
FragmentRef<TestObject> ref1(
|
||||
RefCountedFragment::kUnmanagedRef,
|
||||
- Fragment(FragmentDescriptor(BufferId(0), 0, sizeof(object1)), &object1));
|
||||
+ Fragment::FromDescriptorUnsafe(
|
||||
+ FragmentDescriptor(BufferId(0), 0, sizeof(object1)), &object1));
|
||||
EXPECT_EQ(1, object1.ref_count_for_testing());
|
||||
|
||||
FragmentRef<TestObject> other1 = ref1;
|
||||
@@ -88,7 +90,8 @@ TEST_F(RefCountedFragmentTest, Copy) {
|
||||
TestObject object2;
|
||||
auto ref2 = FragmentRef<TestObject>(
|
||||
RefCountedFragment::kUnmanagedRef,
|
||||
- Fragment(FragmentDescriptor(BufferId(0), 0, sizeof(object2)), &object2));
|
||||
+ Fragment::FromDescriptorUnsafe(
|
||||
+ FragmentDescriptor(BufferId(0), 0, sizeof(object2)), &object2));
|
||||
EXPECT_EQ(1, object1.ref_count_for_testing());
|
||||
EXPECT_EQ(1, object2.ref_count_for_testing());
|
||||
ref2 = ref1;
|
||||
@@ -115,7 +118,8 @@ TEST_F(RefCountedFragmentTest, Move) {
|
||||
|
||||
FragmentRef<TestObject> ref1(
|
||||
RefCountedFragment::kUnmanagedRef,
|
||||
- Fragment(FragmentDescriptor(BufferId(0), 0, sizeof(object1)), &object1));
|
||||
+ Fragment::FromDescriptorUnsafe(
|
||||
+ FragmentDescriptor(BufferId(0), 0, sizeof(object1)), &object1));
|
||||
EXPECT_EQ(1, ref1.ref_count_for_testing());
|
||||
|
||||
FragmentRef<TestObject> other1 = std::move(ref1);
|
||||
@@ -133,10 +137,12 @@ TEST_F(RefCountedFragmentTest, Move) {
|
||||
TestObject object3;
|
||||
FragmentRef<TestObject> ref2(
|
||||
RefCountedFragment::kUnmanagedRef,
|
||||
- Fragment(FragmentDescriptor(BufferId(0), 0, sizeof(object2)), &object2));
|
||||
+ Fragment::FromDescriptorUnsafe(
|
||||
+ FragmentDescriptor(BufferId(0), 0, sizeof(object2)), &object2));
|
||||
FragmentRef<TestObject> ref3(
|
||||
RefCountedFragment::kUnmanagedRef,
|
||||
- Fragment(FragmentDescriptor(BufferId(0), 0, sizeof(object3)), &object3));
|
||||
+ Fragment::FromDescriptorUnsafe(
|
||||
+ FragmentDescriptor(BufferId(0), 0, sizeof(object3)), &object3));
|
||||
|
||||
EXPECT_FALSE(ref2.is_null());
|
||||
EXPECT_TRUE(ref2.is_addressable());
|
||||
119
patches/chromium/cherry-pick-b03973561862.patch
Normal file
119
patches/chromium/cherry-pick-b03973561862.patch
Normal file
@@ -0,0 +1,119 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tommi <tommi@chromium.org>
|
||||
Date: Wed, 5 Jul 2023 10:55:53 +0000
|
||||
Subject: Make RTCDataChannel's channel and observer pointers const.
|
||||
|
||||
This allows channel properties to be queried while the RTCDataChannel
|
||||
instance exists and avoids potential null deref after entering the
|
||||
kClosed state.
|
||||
|
||||
(cherry picked from commit 08d5ad011f53a1995bfccef6728bfa62541f7608)
|
||||
|
||||
Bug: 1456567, 1457421
|
||||
Change-Id: I4747f9c00804b35711667d7320ec6188f20910c4
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4663082
|
||||
Commit-Queue: Tomas Gunnarsson <tommi@chromium.org>
|
||||
Reviewed-by: Elad Alon <eladalon@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1165406}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4665530
|
||||
Cr-Commit-Position: refs/branch-heads/5845@{#300}
|
||||
Cr-Branched-From: 5a5dff63a4a4c63b9b18589819bebb2566c85443-refs/heads/main@{#1160321}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
|
||||
index 78d28d60822f4ce206d869846235352224378076..91c20cbcc5042373964d57545177ff06074db564 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
|
||||
@@ -228,11 +228,12 @@ RTCDataChannel::Observer::Observer(
|
||||
scoped_refptr<webrtc::DataChannelInterface> channel)
|
||||
: main_thread_(main_thread),
|
||||
blink_channel_(blink_channel),
|
||||
- webrtc_channel_(channel) {}
|
||||
+ webrtc_channel_(std::move(channel)) {
|
||||
+ CHECK(webrtc_channel_.get());
|
||||
+}
|
||||
|
||||
RTCDataChannel::Observer::~Observer() {
|
||||
DCHECK(!blink_channel_) << "Reference to blink channel hasn't been released.";
|
||||
- DCHECK(!webrtc_channel_.get()) << "Unregister hasn't been called.";
|
||||
}
|
||||
|
||||
const scoped_refptr<webrtc::DataChannelInterface>&
|
||||
@@ -242,13 +243,8 @@ RTCDataChannel::Observer::channel() const {
|
||||
|
||||
void RTCDataChannel::Observer::Unregister() {
|
||||
DCHECK(main_thread_->BelongsToCurrentThread());
|
||||
+ webrtc_channel_->UnregisterObserver();
|
||||
blink_channel_ = nullptr;
|
||||
- if (webrtc_channel_.get()) {
|
||||
- webrtc_channel_->UnregisterObserver();
|
||||
- // Now that we're guaranteed to not get further OnStateChange callbacks,
|
||||
- // it's safe to release our reference to the channel.
|
||||
- webrtc_channel_ = nullptr;
|
||||
- }
|
||||
}
|
||||
|
||||
void RTCDataChannel::Observer::OnStateChange() {
|
||||
@@ -302,7 +298,7 @@ void RTCDataChannel::Observer::OnMessageImpl(
|
||||
|
||||
RTCDataChannel::RTCDataChannel(
|
||||
ExecutionContext* context,
|
||||
- scoped_refptr<webrtc::DataChannelInterface> channel,
|
||||
+ scoped_refptr<webrtc::DataChannelInterface> data_channel,
|
||||
RTCPeerConnectionHandler* peer_connection_handler)
|
||||
: ExecutionContextLifecycleObserver(context),
|
||||
state_(webrtc::DataChannelInterface::kConnecting),
|
||||
@@ -317,7 +313,7 @@ RTCDataChannel::RTCDataChannel(
|
||||
observer_(base::MakeRefCounted<Observer>(
|
||||
context->GetTaskRunner(TaskType::kNetworking),
|
||||
this,
|
||||
- channel)),
|
||||
+ std::move(data_channel))),
|
||||
signaling_thread_(peer_connection_handler->signaling_thread()) {
|
||||
DCHECK(peer_connection_handler);
|
||||
|
||||
@@ -340,7 +336,7 @@ RTCDataChannel::RTCDataChannel(
|
||||
observer_, state_),
|
||||
"RegisterObserverAndGetStateUpdate");
|
||||
|
||||
- IncrementCounters(*channel.get());
|
||||
+ IncrementCounters(*(observer_->channel()).get());
|
||||
}
|
||||
|
||||
RTCDataChannel::~RTCDataChannel() = default;
|
||||
@@ -689,9 +685,8 @@ void RTCDataChannel::Dispose() {
|
||||
if (stopped_)
|
||||
return;
|
||||
|
||||
- // Clears the weak persistent reference to this on-heap object.
|
||||
+ // Clear the weak persistent reference to this on-heap object.
|
||||
observer_->Unregister();
|
||||
- observer_ = nullptr;
|
||||
}
|
||||
|
||||
void RTCDataChannel::ScheduleDispatchEvent(Event* event) {
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.h b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.h
|
||||
index 21bb39382ac0c6acbf984ffbda5f6a4e6c863432..6959b8b1e3a0b586be68cb4a8d0389b7926b98fe 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.h
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.h
|
||||
@@ -152,7 +152,7 @@ class MODULES_EXPORT RTCDataChannel final
|
||||
|
||||
const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
|
||||
WeakPersistent<RTCDataChannel> blink_channel_;
|
||||
- scoped_refptr<webrtc::DataChannelInterface> webrtc_channel_;
|
||||
+ const scoped_refptr<webrtc::DataChannelInterface> webrtc_channel_;
|
||||
};
|
||||
|
||||
void OnStateChange(webrtc::DataChannelInterface::DataState state);
|
||||
@@ -195,7 +195,11 @@ class MODULES_EXPORT RTCDataChannel final
|
||||
unsigned buffered_amount_;
|
||||
bool stopped_;
|
||||
bool closed_from_owner_;
|
||||
- scoped_refptr<Observer> observer_;
|
||||
+ // Keep the `observer_` reference const to make it clear that we don't want
|
||||
+ // to free the underlying channel (or callback observer) until the
|
||||
+ // `RTCDataChannel` instance goes away. This allows properties to be queried
|
||||
+ // after the state reaches `kClosed`.
|
||||
+ const scoped_refptr<Observer> observer_;
|
||||
scoped_refptr<base::SingleThreadTaskRunner> signaling_thread_;
|
||||
THREAD_CHECKER(thread_checker_);
|
||||
};
|
||||
40
patches/chromium/cherry-pick-b11e7d07a6f4.patch
Normal file
40
patches/chromium/cherry-pick-b11e7d07a6f4.patch
Normal file
@@ -0,0 +1,40 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lei Zhang <thestig@chromium.org>
|
||||
Date: Wed, 13 Sep 2023 23:32:40 +0000
|
||||
Subject: M117: Check for object destruction in PdfViewWebPlugin::UpdateFocus()
|
||||
|
||||
PdfViewWebPlugin::UpdateFocus() can potentially triggers its own
|
||||
destruction. Add a check for this and bail out.
|
||||
|
||||
(cherry picked from commit cacf485a202b342526374d444375b80a044add76)
|
||||
|
||||
Bug: 1480184
|
||||
Change-Id: I5e7760ed541a2bffb9dd1ebeb522f10650049033
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4852346
|
||||
Reviewed-by: Tom Sepez <tsepez@chromium.org>
|
||||
Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com>
|
||||
Commit-Queue: Lei Zhang <thestig@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1194210}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4863395
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5938@{#1286}
|
||||
Cr-Branched-From: 2b50cb4bcc2318034581a816714d9535dc38966d-refs/heads/main@{#1181205}
|
||||
|
||||
diff --git a/pdf/pdf_view_web_plugin.cc b/pdf/pdf_view_web_plugin.cc
|
||||
index cdedca1425dd5be31b2d0b5220d0e050d0b0fb59..b14777df757c8c9b3e5474e7f0f73fe316bfee58 100644
|
||||
--- a/pdf/pdf_view_web_plugin.cc
|
||||
+++ b/pdf/pdf_view_web_plugin.cc
|
||||
@@ -519,7 +519,13 @@ void PdfViewWebPlugin::UpdateFocus(bool focused,
|
||||
if (has_focus_ != focused) {
|
||||
engine_->UpdateFocus(focused);
|
||||
client_->UpdateTextInputState();
|
||||
+
|
||||
+ // Make sure `this` is still alive after the UpdateSelectionBounds() call.
|
||||
+ auto weak_this = weak_factory_.GetWeakPtr();
|
||||
client_->UpdateSelectionBounds();
|
||||
+ if (!weak_this) {
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
has_focus_ = focused;
|
||||
|
||||
187
patches/chromium/cherry-pick-c60a1ab717c7.patch
Normal file
187
patches/chromium/cherry-pick-c60a1ab717c7.patch
Normal file
@@ -0,0 +1,187 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Taylor Bergquist <tbergquist@chromium.org>
|
||||
Date: Tue, 11 Jul 2023 01:32:22 +0000
|
||||
Subject: Fix UAF when exiting a nested run loop in
|
||||
TabDragContextImpl::OnGestureEvent.
|
||||
|
||||
OnGestureEvent may call ContinueDrag, which may run a nested run loop. After the nested run loop returns, multiple seconds of time may have passed, and the world may be in a very different state; in particular, the window that contains this TabDragContext may have closed.
|
||||
|
||||
This CL checks if this has happened, and returns early in that case.
|
||||
|
||||
(cherry picked from commit 63d6b8ba8126b16215d33670df8c67dcbc6c9bef)
|
||||
|
||||
Bug: 1453465
|
||||
Change-Id: I6095c0afeb5aa5f422717f1bbd93b96175e52afa
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4657527
|
||||
Reviewed-by: Darryl James <dljames@chromium.org>
|
||||
Commit-Queue: Taylor Bergquist <tbergquist@chromium.org>
|
||||
Code-Coverage: Findit <findit-for-me@appspot.gserviceaccount.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1164449}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4676126
|
||||
Reviewed-by: Shibalik Mohapatra <shibalik@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5845@{#410}
|
||||
Cr-Branched-From: 5a5dff63a4a4c63b9b18589819bebb2566c85443-refs/heads/main@{#1160321}
|
||||
|
||||
diff --git a/chrome/browser/ui/views/tabs/fake_tab_slot_controller.cc b/chrome/browser/ui/views/tabs/fake_tab_slot_controller.cc
|
||||
index 94d27ec3ab22f7afb5e265fdcee662e48f36c00e..81348ceb4a415f789dd384988a54662ec3c3d0e0 100644
|
||||
--- a/chrome/browser/ui/views/tabs/fake_tab_slot_controller.cc
|
||||
+++ b/chrome/browser/ui/views/tabs/fake_tab_slot_controller.cc
|
||||
@@ -45,6 +45,12 @@ bool FakeTabSlotController::IsFocusInTabs() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
+TabSlotController::Liveness FakeTabSlotController::ContinueDrag(
|
||||
+ views::View* view,
|
||||
+ const ui::LocatedEvent& event) {
|
||||
+ return Liveness::kAlive;
|
||||
+}
|
||||
+
|
||||
bool FakeTabSlotController::EndDrag(EndDragReason reason) {
|
||||
return false;
|
||||
}
|
||||
diff --git a/chrome/browser/ui/views/tabs/fake_tab_slot_controller.h b/chrome/browser/ui/views/tabs/fake_tab_slot_controller.h
|
||||
index ebbae9b19a8f9534e3a86d2bf28875418a7be80d..4795c222651af3a7146a8bf12e824a1480cdbfae 100644
|
||||
--- a/chrome/browser/ui/views/tabs/fake_tab_slot_controller.h
|
||||
+++ b/chrome/browser/ui/views/tabs/fake_tab_slot_controller.h
|
||||
@@ -60,8 +60,8 @@ class FakeTabSlotController : public TabSlotController {
|
||||
TabSlotView* source,
|
||||
const ui::LocatedEvent& event,
|
||||
const ui::ListSelectionModel& original_selection) override {}
|
||||
- void ContinueDrag(views::View* view, const ui::LocatedEvent& event) override {
|
||||
- }
|
||||
+ Liveness ContinueDrag(views::View* view,
|
||||
+ const ui::LocatedEvent& event) override;
|
||||
bool EndDrag(EndDragReason reason) override;
|
||||
Tab* GetTabAt(const gfx::Point& point) override;
|
||||
const Tab* GetAdjacentTab(const Tab* tab, int offset) override;
|
||||
diff --git a/chrome/browser/ui/views/tabs/tab_slot_controller.h b/chrome/browser/ui/views/tabs/tab_slot_controller.h
|
||||
index 6a43f963a22917b9e9b861d3619d9804851dfb5b..d412ad6d5d9a95aa5d635fae5232eddfa87132ae 100644
|
||||
--- a/chrome/browser/ui/views/tabs/tab_slot_controller.h
|
||||
+++ b/chrome/browser/ui/views/tabs/tab_slot_controller.h
|
||||
@@ -49,6 +49,8 @@ class TabSlotController {
|
||||
kEvent
|
||||
};
|
||||
|
||||
+ enum class Liveness { kAlive, kDeleted };
|
||||
+
|
||||
virtual const ui::ListSelectionModel& GetSelectionModel() const = 0;
|
||||
|
||||
// Returns the tab at |index|.
|
||||
@@ -126,9 +128,10 @@ class TabSlotController {
|
||||
const ui::LocatedEvent& event,
|
||||
const ui::ListSelectionModel& original_selection) = 0;
|
||||
|
||||
- // Continues dragging a Tab.
|
||||
- virtual void ContinueDrag(views::View* view,
|
||||
- const ui::LocatedEvent& event) = 0;
|
||||
+ // Continues dragging a Tab. May enter a nested event loop - returns
|
||||
+ // Liveness::kDeleted if `this` was destroyed during this nested event loop,
|
||||
+ // and Liveness::kAlive if `this` is still alive.
|
||||
+ virtual Liveness ContinueDrag(views::View* view, const ui::LocatedEvent& event) = 0;
|
||||
|
||||
// Ends dragging a Tab. Returns whether the tab has been destroyed.
|
||||
virtual bool EndDrag(EndDragReason reason) = 0;
|
||||
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
|
||||
index f2f18c7f21bc249b95dece091716fcb6872b0c12..22a4b6b761058f44cbea029bbc52dd4071e111e9 100644
|
||||
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
|
||||
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
|
||||
@@ -174,7 +174,7 @@ class TabStrip::TabDragContextImpl : public TabDragContext,
|
||||
}
|
||||
|
||||
bool OnMouseDragged(const ui::MouseEvent& event) override {
|
||||
- ContinueDrag(this, event);
|
||||
+ (void)ContinueDrag(this, event);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -185,6 +185,7 @@ class TabStrip::TabDragContextImpl : public TabDragContext,
|
||||
void OnMouseCaptureLost() override { EndDrag(END_DRAG_CAPTURE_LOST); }
|
||||
|
||||
void OnGestureEvent(ui::GestureEvent* event) override {
|
||||
+ Liveness tabstrip_alive = Liveness::kAlive;
|
||||
switch (event->type()) {
|
||||
case ui::ET_GESTURE_SCROLL_END:
|
||||
case ui::ET_SCROLL_FLING_START:
|
||||
@@ -198,7 +199,8 @@ class TabStrip::TabDragContextImpl : public TabDragContext,
|
||||
}
|
||||
|
||||
case ui::ET_GESTURE_SCROLL_UPDATE:
|
||||
- ContinueDrag(this, *event);
|
||||
+ // N.B. !! ContinueDrag may enter a nested run loop !!
|
||||
+ tabstrip_alive = ContinueDrag(this, *event);
|
||||
break;
|
||||
|
||||
case ui::ET_GESTURE_TAP_DOWN:
|
||||
@@ -210,6 +212,12 @@ class TabStrip::TabDragContextImpl : public TabDragContext,
|
||||
}
|
||||
event->SetHandled();
|
||||
|
||||
+ // If tabstrip was destroyed (during ContinueDrag above), return early to
|
||||
+ // avoid UAF below.
|
||||
+ if (tabstrip_alive == Liveness::kDeleted) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
// TabDragContext gets event capture as soon as a drag session begins, which
|
||||
// precludes TabStrip from ever getting events like tap or long tap. Forward
|
||||
// this on to TabStrip so it can respond to those events.
|
||||
@@ -295,20 +303,20 @@ class TabStrip::TabDragContextImpl : public TabDragContext,
|
||||
std::move(drag_controller_set_callback_).Run(drag_controller_.get());
|
||||
}
|
||||
|
||||
- void ContinueDrag(views::View* view, const ui::LocatedEvent& event) {
|
||||
- if (drag_controller_.get() &&
|
||||
- drag_controller_->event_source() == EventSourceFromEvent(event)) {
|
||||
- gfx::Point screen_location(event.location());
|
||||
- views::View::ConvertPointToScreen(view, &screen_location);
|
||||
+ Liveness ContinueDrag(views::View* view, const ui::LocatedEvent& event) {
|
||||
+ if (!drag_controller_.get() ||
|
||||
+ drag_controller_->event_source() != EventSourceFromEvent(event)) {
|
||||
+ return Liveness::kAlive;
|
||||
+ }
|
||||
|
||||
- // Note: |tab_strip_| can be destroyed during drag, also destroying
|
||||
- // |this|.
|
||||
- base::WeakPtr<TabDragContext> weak_ptr(weak_factory_.GetWeakPtr());
|
||||
- drag_controller_->Drag(screen_location);
|
||||
+ gfx::Point screen_location(event.location());
|
||||
+ views::View::ConvertPointToScreen(view, &screen_location);
|
||||
|
||||
- if (!weak_ptr)
|
||||
- return;
|
||||
- }
|
||||
+ // Note: `tab_strip_` can be destroyed during drag, also destroying `this`.
|
||||
+ base::WeakPtr<TabDragContext> weak_ptr(weak_factory_.GetWeakPtr());
|
||||
+ drag_controller_->Drag(screen_location);
|
||||
+
|
||||
+ return weak_ptr ? Liveness::kAlive : Liveness::kDeleted;
|
||||
}
|
||||
|
||||
bool EndDrag(EndDragReason reason) {
|
||||
@@ -1573,8 +1581,10 @@ void TabStrip::MaybeStartDrag(
|
||||
drag_context_->MaybeStartDrag(source, event, original_selection);
|
||||
}
|
||||
|
||||
-void TabStrip::ContinueDrag(views::View* view, const ui::LocatedEvent& event) {
|
||||
- drag_context_->ContinueDrag(view, event);
|
||||
+TabSlotController::Liveness TabStrip::ContinueDrag(
|
||||
+ views::View* view,
|
||||
+ const ui::LocatedEvent& event) {
|
||||
+ return drag_context_->ContinueDrag(view, event);
|
||||
}
|
||||
|
||||
bool TabStrip::EndDrag(EndDragReason reason) {
|
||||
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h
|
||||
index fce93e7d993434ce1e99c7cbca71c1391798c1a4..de6f20bb978c32d635b4f8b75841c148996df2c6 100644
|
||||
--- a/chrome/browser/ui/views/tabs/tab_strip.h
|
||||
+++ b/chrome/browser/ui/views/tabs/tab_strip.h
|
||||
@@ -278,7 +278,8 @@ class TabStrip : public views::View,
|
||||
TabSlotView* source,
|
||||
const ui::LocatedEvent& event,
|
||||
const ui::ListSelectionModel& original_selection) override;
|
||||
- void ContinueDrag(views::View* view, const ui::LocatedEvent& event) override;
|
||||
+ Liveness ContinueDrag(views::View* view,
|
||||
+ const ui::LocatedEvent& event) override;
|
||||
bool EndDrag(EndDragReason reason) override;
|
||||
Tab* GetTabAt(const gfx::Point& point) override;
|
||||
const Tab* GetAdjacentTab(const Tab* tab, int offset) override;
|
||||
@@ -0,0 +1,84 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Rune Lillesveen <futhark@chromium.org>
|
||||
Date: Tue, 15 Aug 2023 15:04:39 +0000
|
||||
Subject: Don't keep pointer to popped stack memory for :has()
|
||||
|
||||
The sibling_features pass into UpdateFeaturesFromCombinator may be
|
||||
initialized to last_compound_in_adjacent_chain_features if null. The
|
||||
outer while loop in
|
||||
AddFeaturesToInvalidationSetsForLogicalCombinationInHas() could then
|
||||
reference to the last_compound_in_adjacent_chain_features which is
|
||||
popped from the stack on every outer iteration. That caused an ASAN
|
||||
failure for reading stack memory that had been popped.
|
||||
|
||||
Instead make sure each inner iteration restarts with the same
|
||||
sibling_features pointer, which seems to have been the intent here.
|
||||
|
||||
(cherry picked from commit 5e213507a2f0d6e3c96904a710407b01493670bd)
|
||||
|
||||
Bug: 1470477
|
||||
Change-Id: I260c93016f8ab0d165e4b29ca1aea810bede5b97
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4759326
|
||||
Commit-Queue: Rune Lillesveen <futhark@chromium.org>
|
||||
Reviewed-by: Anders Hartvoll Ruud <andruud@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1181365}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4777251
|
||||
Cr-Commit-Position: refs/branch-heads/5845@{#1482}
|
||||
Cr-Branched-From: 5a5dff63a4a4c63b9b18589819bebb2566c85443-refs/heads/main@{#1160321}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/css/rule_feature_set.cc b/third_party/blink/renderer/core/css/rule_feature_set.cc
|
||||
index ec7356285d7fa45b7d9c1701be484a121c2a0017..9cb6084b7fca4fc6ff2edd8defadf8fabf2899b5 100644
|
||||
--- a/third_party/blink/renderer/core/css/rule_feature_set.cc
|
||||
+++ b/third_party/blink/renderer/core/css/rule_feature_set.cc
|
||||
@@ -1227,6 +1227,7 @@ void RuleFeatureSet::AddFeaturesToInvalidationSetsForLogicalCombinationInHas(
|
||||
descendant_features);
|
||||
|
||||
const CSSSelector* compound_in_logical_combination = complex;
|
||||
+ InvalidationSetFeatures* inner_sibling_features = sibling_features;
|
||||
InvalidationSetFeatures last_compound_in_adjacent_chain_features;
|
||||
while (compound_in_logical_combination) {
|
||||
AddFeaturesToInvalidationSetsForLogicalCombinationInHasContext context(
|
||||
@@ -1238,14 +1239,14 @@ void RuleFeatureSet::AddFeaturesToInvalidationSetsForLogicalCombinationInHas(
|
||||
last_in_compound =
|
||||
SkipAddingAndGetLastInCompoundForLogicalCombinationInHas(
|
||||
compound_in_logical_combination, compound_containing_has,
|
||||
- sibling_features, descendant_features, previous_combinator,
|
||||
- add_features_method);
|
||||
+ inner_sibling_features, descendant_features,
|
||||
+ previous_combinator, add_features_method);
|
||||
} else {
|
||||
last_in_compound =
|
||||
AddFeaturesAndGetLastInCompoundForLogicalCombinationInHas(
|
||||
compound_in_logical_combination, compound_containing_has,
|
||||
- sibling_features, descendant_features, previous_combinator,
|
||||
- add_features_method);
|
||||
+ inner_sibling_features, descendant_features,
|
||||
+ previous_combinator, add_features_method);
|
||||
}
|
||||
|
||||
if (!last_in_compound)
|
||||
@@ -1259,7 +1260,7 @@ void RuleFeatureSet::AddFeaturesToInvalidationSetsForLogicalCombinationInHas(
|
||||
? CSSSelector::kIndirectAdjacent
|
||||
: previous_combinator,
|
||||
context.last_compound_in_adjacent_chain,
|
||||
- last_compound_in_adjacent_chain_features, sibling_features,
|
||||
+ last_compound_in_adjacent_chain_features, inner_sibling_features,
|
||||
descendant_features);
|
||||
}
|
||||
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/has-sibling-chrome-crash.html b/third_party/blink/web_tests/external/wpt/css/selectors/has-sibling-chrome-crash.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0306e3e39272c321fc3539aa582b4e239ffe2fa1
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/has-sibling-chrome-crash.html
|
||||
@@ -0,0 +1,10 @@
|
||||
+<!DOCTYPE html>
|
||||
+<title>CSS Selectors Test: Chrome crash issue 1470477</title>
|
||||
+<link rel="help" href="https://crbug.com/1470477">
|
||||
+<style>
|
||||
+ :has(> :where(label:first-child + [a="a"]:only-of-type,
|
||||
+ [a="a"]:only-of-type + label:last-child)) label:last-child {
|
||||
+ margin-inline: 1em;
|
||||
+ }
|
||||
+</style>
|
||||
+<p>PASS if this tests does not crash</p>
|
||||
@@ -0,0 +1,93 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Adam Rice <ricea@chromium.org>
|
||||
Date: Tue, 8 Aug 2023 08:48:51 +0000
|
||||
Subject: NetworkContext: Don't access url_loader_factories_ during destruction
|
||||
|
||||
Move the contents of `url_loader_factories_` to a temporary variable in
|
||||
the destructor of network::NetworkContext so that re-entrant calls to
|
||||
DestroyURLLoaderFactory() don't happen after it has started being
|
||||
destroyed.
|
||||
|
||||
BUG=1465833
|
||||
|
||||
(cherry picked from commit e579b20308290df03f045c5d0ccb852d96b24ce3)
|
||||
|
||||
Change-Id: I476f0865256bdcba4ec934688597e69991968f84
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4733351
|
||||
Reviewed-by: Kenichi Ishibashi <bashi@chromium.org>
|
||||
Commit-Queue: Adam Rice <ricea@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1177648}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4756334
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Auto-Submit: Adam Rice <ricea@chromium.org>
|
||||
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5845@{#1252}
|
||||
Cr-Branched-From: 5a5dff63a4a4c63b9b18589819bebb2566c85443-refs/heads/main@{#1160321}
|
||||
|
||||
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
|
||||
index 6dc46954b070795de082d8542f8bae56d7b52dd4..2b12040f5ef2b7fd466a9b6d92e75faea8bd1808 100644
|
||||
--- a/services/network/network_context.cc
|
||||
+++ b/services/network/network_context.cc
|
||||
@@ -712,6 +712,8 @@ NetworkContext::NetworkContext(
|
||||
}
|
||||
|
||||
NetworkContext::~NetworkContext() {
|
||||
+ is_destructing_ = true;
|
||||
+
|
||||
// May be nullptr in tests.
|
||||
if (network_service_)
|
||||
network_service_->DeregisterNetworkContext(this);
|
||||
@@ -775,6 +777,12 @@ NetworkContext::~NetworkContext() {
|
||||
}
|
||||
}
|
||||
#endif // BUILDFLAG(IS_DIRECTORY_TRANSFER_REQUIRED)
|
||||
+
|
||||
+ // Clear `url_loader_factories_` before deleting the contents, as it can
|
||||
+ // result in re-entrant calls to DestroyURLLoaderFactory().
|
||||
+ std::set<std::unique_ptr<cors::CorsURLLoaderFactory>,
|
||||
+ base::UniquePtrComparator>
|
||||
+ url_loader_factories = std::move(url_loader_factories_);
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -993,6 +1001,9 @@ void NetworkContext::DisableQuic() {
|
||||
|
||||
void NetworkContext::DestroyURLLoaderFactory(
|
||||
cors::CorsURLLoaderFactory* url_loader_factory) {
|
||||
+ if (is_destructing_) {
|
||||
+ return;
|
||||
+ }
|
||||
auto it = url_loader_factories_.find(url_loader_factory);
|
||||
DCHECK(it != url_loader_factories_.end());
|
||||
url_loader_factories_.erase(it);
|
||||
diff --git a/services/network/network_context.h b/services/network/network_context.h
|
||||
index 402a9de330140e78f14dbfae204f4c637803fcef..9e4db6927a42308b7ac30455f27ad97b92e2b0c3 100644
|
||||
--- a/services/network/network_context.h
|
||||
+++ b/services/network/network_context.h
|
||||
@@ -915,6 +915,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
|
||||
// DCHECKs on APIs used by external callers.
|
||||
bool require_network_isolation_key_ = false;
|
||||
|
||||
+ // True once the destructor has been called. Used to guard against re-entrant
|
||||
+ // calls to DestroyURLLoaderFactory().
|
||||
+ bool is_destructing_ = false;
|
||||
+
|
||||
// Indicating whether
|
||||
// https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name is
|
||||
// supported.
|
||||
@@ -923,13 +927,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
|
||||
|
||||
// CorsURLLoaderFactory assumes that fields owned by the NetworkContext always
|
||||
// live longer than the factory. Therefore we want the factories to be
|
||||
- // destroyed before other fields above. In particular:
|
||||
- // - This must be below |url_request_context_| so that the URLRequestContext
|
||||
- // outlives all the URLLoaderFactories and URLLoaders that depend on it;
|
||||
- // for the same reason, it must also be below |network_context_|.
|
||||
- // - This must be below |loader_count_per_process_| that is touched by
|
||||
- // CorsURLLoaderFactory::DestroyURLLoader (see also
|
||||
- // https://crbug.com/1174943).
|
||||
+ // destroyed before other fields above. This is accomplished by explicitly
|
||||
+ // clearing `url_loader_factories_` in the destructor.
|
||||
std::set<std::unique_ptr<cors::CorsURLLoaderFactory>,
|
||||
base::UniquePtrComparator>
|
||||
url_loader_factories_;
|
||||
@@ -29,5 +29,9 @@
|
||||
|
||||
"src/electron/patches/dawn": "src/third_party/dawn",
|
||||
|
||||
"src/electron/patches/webrtc": "src/third_party/webrtc"
|
||||
"src/electron/patches/webrtc": "src/third_party/webrtc",
|
||||
|
||||
"src/electron/patches/libwebp": "src/third_party/libwebp/src",
|
||||
|
||||
"src/electron/patches/libvpx": "src/third_party/libvpx/source/libvpx"
|
||||
}
|
||||
|
||||
1
patches/libvpx/.patches
Normal file
1
patches/libvpx/.patches
Normal file
@@ -0,0 +1 @@
|
||||
cherry-pick-3fbd1dca6a4d.patch
|
||||
27
patches/libvpx/cherry-pick-3fbd1dca6a4d.patch
Normal file
27
patches/libvpx/cherry-pick-3fbd1dca6a4d.patch
Normal file
@@ -0,0 +1,27 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: James Zern <jzern@google.com>
|
||||
Date: Mon, 25 Sep 2023 18:55:59 -0700
|
||||
Subject: VP8: disallow thread count changes
|
||||
|
||||
Currently allocations are done at encoder creation time. Going from
|
||||
threaded to non-threaded would cause a crash.
|
||||
|
||||
Bug: chromium:1486441
|
||||
Change-Id: Ie301c2a70847dff2f0daae408fbef1e4d42e73d4
|
||||
|
||||
diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c
|
||||
index 94fb6e256e8f4f1077aa6e2aef84e3bc7070da0f..f68339d2b4f4b2ca654a835cc56c537fb5e7d260 100644
|
||||
--- a/vp8/encoder/onyx_if.c
|
||||
+++ b/vp8/encoder/onyx_if.c
|
||||
@@ -1443,6 +1443,11 @@ void vp8_change_config(VP8_COMP *cpi, VP8_CONFIG *oxcf) {
|
||||
last_h = cpi->oxcf.Height;
|
||||
prev_number_of_layers = cpi->oxcf.number_of_layers;
|
||||
|
||||
+ if (cpi->initial_width) {
|
||||
+ // TODO(https://crbug.com/1486441): Allow changing thread counts; the
|
||||
+ // allocation is done once in vp8_create_compressor().
|
||||
+ oxcf->multi_threaded = cpi->oxcf.multi_threaded;
|
||||
+ }
|
||||
cpi->oxcf = *oxcf;
|
||||
|
||||
switch (cpi->oxcf.Mode) {
|
||||
1
patches/libwebp/.patches
Normal file
1
patches/libwebp/.patches
Normal file
@@ -0,0 +1 @@
|
||||
fix_oob_write_in_buildhuffmantable.patch
|
||||
353
patches/libwebp/fix_oob_write_in_buildhuffmantable.patch
Normal file
353
patches/libwebp/fix_oob_write_in_buildhuffmantable.patch
Normal file
@@ -0,0 +1,353 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Vincent Rabaud <vrabaud@google.com>
|
||||
Date: Thu, 7 Sep 2023 21:16:03 +0200
|
||||
Subject: Fix OOB write in BuildHuffmanTable.
|
||||
|
||||
First, BuildHuffmanTable is called to check if the data is valid.
|
||||
If it is and the table is not big enough, more memory is allocated.
|
||||
|
||||
This will make sure that valid (but unoptimized because of unbalanced
|
||||
codes) streams are still decodable.
|
||||
|
||||
Bug: chromium:1479274
|
||||
Change-Id: I31c36dbf3aa78d35ecf38706b50464fd3d375741
|
||||
(cherry picked from commit 902bc9190331343b2017211debcec8d2ab87e17a)
|
||||
(cherry picked from commit 2af26267cdfcb63a88e5c74a85927a12d6ca1d76)
|
||||
|
||||
diff --git a/src/dec/vp8l_dec.c b/src/dec/vp8l_dec.c
|
||||
index 13480551282eca71560641a68c632e13acd3cd79..186b0b2f826a17a4889299a90a068725d06be4f3 100644
|
||||
--- a/src/dec/vp8l_dec.c
|
||||
+++ b/src/dec/vp8l_dec.c
|
||||
@@ -253,11 +253,11 @@ static int ReadHuffmanCodeLengths(
|
||||
int symbol;
|
||||
int max_symbol;
|
||||
int prev_code_len = DEFAULT_CODE_LENGTH;
|
||||
- HuffmanCode table[1 << LENGTHS_TABLE_BITS];
|
||||
+ HuffmanTables tables;
|
||||
|
||||
- if (!VP8LBuildHuffmanTable(table, LENGTHS_TABLE_BITS,
|
||||
- code_length_code_lengths,
|
||||
- NUM_CODE_LENGTH_CODES)) {
|
||||
+ if (!VP8LHuffmanTablesAllocate(1 << LENGTHS_TABLE_BITS, &tables) ||
|
||||
+ !VP8LBuildHuffmanTable(&tables, LENGTHS_TABLE_BITS,
|
||||
+ code_length_code_lengths, NUM_CODE_LENGTH_CODES)) {
|
||||
goto End;
|
||||
}
|
||||
|
||||
@@ -277,7 +277,7 @@ static int ReadHuffmanCodeLengths(
|
||||
int code_len;
|
||||
if (max_symbol-- == 0) break;
|
||||
VP8LFillBitWindow(br);
|
||||
- p = &table[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];
|
||||
+ p = &tables.curr_segment->start[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];
|
||||
VP8LSetBitPos(br, br->bit_pos_ + p->bits);
|
||||
code_len = p->value;
|
||||
if (code_len < kCodeLengthLiterals) {
|
||||
@@ -300,6 +300,7 @@ static int ReadHuffmanCodeLengths(
|
||||
ok = 1;
|
||||
|
||||
End:
|
||||
+ VP8LHuffmanTablesDeallocate(&tables);
|
||||
if (!ok) dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
|
||||
return ok;
|
||||
}
|
||||
@@ -307,7 +308,8 @@ static int ReadHuffmanCodeLengths(
|
||||
// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman
|
||||
// tree.
|
||||
static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
|
||||
- int* const code_lengths, HuffmanCode* const table) {
|
||||
+ int* const code_lengths,
|
||||
+ HuffmanTables* const table) {
|
||||
int ok = 0;
|
||||
int size = 0;
|
||||
VP8LBitReader* const br = &dec->br_;
|
||||
@@ -362,8 +364,7 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
VP8LMetadata* const hdr = &dec->hdr_;
|
||||
uint32_t* huffman_image = NULL;
|
||||
HTreeGroup* htree_groups = NULL;
|
||||
- HuffmanCode* huffman_tables = NULL;
|
||||
- HuffmanCode* huffman_table = NULL;
|
||||
+ HuffmanTables* huffman_tables = &hdr->huffman_tables_;
|
||||
int num_htree_groups = 1;
|
||||
int num_htree_groups_max = 1;
|
||||
int max_alphabet_size = 0;
|
||||
@@ -372,6 +373,10 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
int* mapping = NULL;
|
||||
int ok = 0;
|
||||
|
||||
+ // Check the table has been 0 initialized (through InitMetadata).
|
||||
+ assert(huffman_tables->root.start == NULL);
|
||||
+ assert(huffman_tables->curr_segment == NULL);
|
||||
+
|
||||
if (allow_recursion && VP8LReadBits(br, 1)) {
|
||||
// use meta Huffman codes.
|
||||
const int huffman_precision = VP8LReadBits(br, 3) + 2;
|
||||
@@ -434,16 +439,15 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
|
||||
code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size,
|
||||
sizeof(*code_lengths));
|
||||
- huffman_tables = (HuffmanCode*)WebPSafeMalloc(num_htree_groups * table_size,
|
||||
- sizeof(*huffman_tables));
|
||||
htree_groups = VP8LHtreeGroupsNew(num_htree_groups);
|
||||
|
||||
- if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) {
|
||||
+ if (htree_groups == NULL || code_lengths == NULL ||
|
||||
+ !VP8LHuffmanTablesAllocate(num_htree_groups * table_size,
|
||||
+ huffman_tables)) {
|
||||
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
- huffman_table = huffman_tables;
|
||||
for (i = 0; i < num_htree_groups_max; ++i) {
|
||||
// If the index "i" is unused in the Huffman image, just make sure the
|
||||
// coefficients are valid but do not store them.
|
||||
@@ -468,19 +472,20 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
int max_bits = 0;
|
||||
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
|
||||
int alphabet_size = kAlphabetSize[j];
|
||||
- htrees[j] = huffman_table;
|
||||
if (j == 0 && color_cache_bits > 0) {
|
||||
alphabet_size += (1 << color_cache_bits);
|
||||
}
|
||||
- size = ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_table);
|
||||
+ size =
|
||||
+ ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables);
|
||||
+ htrees[j] = huffman_tables->curr_segment->curr_table;
|
||||
if (size == 0) {
|
||||
goto Error;
|
||||
}
|
||||
if (is_trivial_literal && kLiteralMap[j] == 1) {
|
||||
- is_trivial_literal = (huffman_table->bits == 0);
|
||||
+ is_trivial_literal = (htrees[j]->bits == 0);
|
||||
}
|
||||
- total_size += huffman_table->bits;
|
||||
- huffman_table += size;
|
||||
+ total_size += htrees[j]->bits;
|
||||
+ huffman_tables->curr_segment->curr_table += size;
|
||||
if (j <= ALPHA) {
|
||||
int local_max_bits = code_lengths[0];
|
||||
int k;
|
||||
@@ -515,14 +520,13 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
hdr->huffman_image_ = huffman_image;
|
||||
hdr->num_htree_groups_ = num_htree_groups;
|
||||
hdr->htree_groups_ = htree_groups;
|
||||
- hdr->huffman_tables_ = huffman_tables;
|
||||
|
||||
Error:
|
||||
WebPSafeFree(code_lengths);
|
||||
WebPSafeFree(mapping);
|
||||
if (!ok) {
|
||||
WebPSafeFree(huffman_image);
|
||||
- WebPSafeFree(huffman_tables);
|
||||
+ VP8LHuffmanTablesDeallocate(huffman_tables);
|
||||
VP8LHtreeGroupsFree(htree_groups);
|
||||
}
|
||||
return ok;
|
||||
@@ -1358,7 +1362,7 @@ static void ClearMetadata(VP8LMetadata* const hdr) {
|
||||
assert(hdr != NULL);
|
||||
|
||||
WebPSafeFree(hdr->huffman_image_);
|
||||
- WebPSafeFree(hdr->huffman_tables_);
|
||||
+ VP8LHuffmanTablesDeallocate(&hdr->huffman_tables_);
|
||||
VP8LHtreeGroupsFree(hdr->htree_groups_);
|
||||
VP8LColorCacheClear(&hdr->color_cache_);
|
||||
VP8LColorCacheClear(&hdr->saved_color_cache_);
|
||||
@@ -1673,7 +1677,7 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
|
||||
|
||||
if (dec == NULL) return 0;
|
||||
|
||||
- assert(dec->hdr_.huffman_tables_ != NULL);
|
||||
+ assert(dec->hdr_.huffman_tables_.root.start != NULL);
|
||||
assert(dec->hdr_.htree_groups_ != NULL);
|
||||
assert(dec->hdr_.num_htree_groups_ > 0);
|
||||
|
||||
diff --git a/src/dec/vp8li_dec.h b/src/dec/vp8li_dec.h
|
||||
index 72b2e861208447f45e5ee12eac57b9c36ff2cd31..32540a4b88a05cc74b88f11da3f143e83be81c9c 100644
|
||||
--- a/src/dec/vp8li_dec.h
|
||||
+++ b/src/dec/vp8li_dec.h
|
||||
@@ -51,7 +51,7 @@ typedef struct {
|
||||
uint32_t* huffman_image_;
|
||||
int num_htree_groups_;
|
||||
HTreeGroup* htree_groups_;
|
||||
- HuffmanCode* huffman_tables_;
|
||||
+ HuffmanTables huffman_tables_;
|
||||
} VP8LMetadata;
|
||||
|
||||
typedef struct VP8LDecoder VP8LDecoder;
|
||||
diff --git a/src/utils/huffman_utils.c b/src/utils/huffman_utils.c
|
||||
index 0cba0fbb7d4f3a945cf9f9909a3e4c1b96ec92da..9efd6283ac30210fb7450250f855cbd1d75f55ec 100644
|
||||
--- a/src/utils/huffman_utils.c
|
||||
+++ b/src/utils/huffman_utils.c
|
||||
@@ -177,21 +177,24 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
||||
if (num_open < 0) {
|
||||
return 0;
|
||||
}
|
||||
- if (root_table == NULL) continue;
|
||||
for (; count[len] > 0; --count[len]) {
|
||||
HuffmanCode code;
|
||||
if ((key & mask) != low) {
|
||||
- table += table_size;
|
||||
+ if (root_table != NULL) table += table_size;
|
||||
table_bits = NextTableBitSize(count, len, root_bits);
|
||||
table_size = 1 << table_bits;
|
||||
total_size += table_size;
|
||||
low = key & mask;
|
||||
- root_table[low].bits = (uint8_t)(table_bits + root_bits);
|
||||
- root_table[low].value = (uint16_t)((table - root_table) - low);
|
||||
+ if (root_table != NULL) {
|
||||
+ root_table[low].bits = (uint8_t)(table_bits + root_bits);
|
||||
+ root_table[low].value = (uint16_t)((table - root_table) - low);
|
||||
+ }
|
||||
+ }
|
||||
+ if (root_table != NULL) {
|
||||
+ code.bits = (uint8_t)(len - root_bits);
|
||||
+ code.value = (uint16_t)sorted[symbol++];
|
||||
+ ReplicateValue(&table[key >> root_bits], step, table_size, code);
|
||||
}
|
||||
- code.bits = (uint8_t)(len - root_bits);
|
||||
- code.value = (uint16_t)sorted[symbol++];
|
||||
- ReplicateValue(&table[key >> root_bits], step, table_size, code);
|
||||
key = GetNextKey(key, len);
|
||||
}
|
||||
}
|
||||
@@ -211,25 +214,83 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
||||
((1 << MAX_CACHE_BITS) + NUM_LITERAL_CODES + NUM_LENGTH_CODES)
|
||||
// Cut-off value for switching between heap and stack allocation.
|
||||
#define SORTED_SIZE_CUTOFF 512
|
||||
-int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
||||
+int VP8LBuildHuffmanTable(HuffmanTables* const root_table, int root_bits,
|
||||
const int code_lengths[], int code_lengths_size) {
|
||||
- int total_size;
|
||||
+ const int total_size =
|
||||
+ BuildHuffmanTable(NULL, root_bits, code_lengths, code_lengths_size, NULL);
|
||||
assert(code_lengths_size <= MAX_CODE_LENGTHS_SIZE);
|
||||
- if (root_table == NULL) {
|
||||
- total_size = BuildHuffmanTable(NULL, root_bits,
|
||||
- code_lengths, code_lengths_size, NULL);
|
||||
- } else if (code_lengths_size <= SORTED_SIZE_CUTOFF) {
|
||||
+ if (total_size == 0 || root_table == NULL) return total_size;
|
||||
+
|
||||
+ if (root_table->curr_segment->curr_table + total_size >=
|
||||
+ root_table->curr_segment->start + root_table->curr_segment->size) {
|
||||
+ // If 'root_table' does not have enough memory, allocate a new segment.
|
||||
+ // The available part of root_table->curr_segment is left unused because we
|
||||
+ // need a contiguous buffer.
|
||||
+ const int segment_size = root_table->curr_segment->size;
|
||||
+ struct HuffmanTablesSegment* next =
|
||||
+ (HuffmanTablesSegment*)WebPSafeMalloc(1, sizeof(*next));
|
||||
+ if (next == NULL) return 0;
|
||||
+ // Fill the new segment.
|
||||
+ // We need at least 'total_size' but if that value is small, it is better to
|
||||
+ // allocate a big chunk to prevent more allocations later. 'segment_size' is
|
||||
+ // therefore chosen (any other arbitrary value could be chosen).
|
||||
+ next->size = total_size > segment_size ? total_size : segment_size;
|
||||
+ next->start =
|
||||
+ (HuffmanCode*)WebPSafeMalloc(next->size, sizeof(*next->start));
|
||||
+ if (next->start == NULL) {
|
||||
+ WebPSafeFree(next);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ next->curr_table = next->start;
|
||||
+ next->next = NULL;
|
||||
+ // Point to the new segment.
|
||||
+ root_table->curr_segment->next = next;
|
||||
+ root_table->curr_segment = next;
|
||||
+ }
|
||||
+ if (code_lengths_size <= SORTED_SIZE_CUTOFF) {
|
||||
// use local stack-allocated array.
|
||||
uint16_t sorted[SORTED_SIZE_CUTOFF];
|
||||
- total_size = BuildHuffmanTable(root_table, root_bits,
|
||||
- code_lengths, code_lengths_size, sorted);
|
||||
- } else { // rare case. Use heap allocation.
|
||||
+ BuildHuffmanTable(root_table->curr_segment->curr_table, root_bits,
|
||||
+ code_lengths, code_lengths_size, sorted);
|
||||
+ } else { // rare case. Use heap allocation.
|
||||
uint16_t* const sorted =
|
||||
(uint16_t*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted));
|
||||
if (sorted == NULL) return 0;
|
||||
- total_size = BuildHuffmanTable(root_table, root_bits,
|
||||
- code_lengths, code_lengths_size, sorted);
|
||||
+ BuildHuffmanTable(root_table->curr_segment->curr_table, root_bits,
|
||||
+ code_lengths, code_lengths_size, sorted);
|
||||
WebPSafeFree(sorted);
|
||||
}
|
||||
return total_size;
|
||||
}
|
||||
+
|
||||
+int VP8LHuffmanTablesAllocate(int size, HuffmanTables* huffman_tables) {
|
||||
+ // Have 'segment' point to the first segment for now, 'root'.
|
||||
+ HuffmanTablesSegment* const root = &huffman_tables->root;
|
||||
+ huffman_tables->curr_segment = root;
|
||||
+ // Allocate root.
|
||||
+ root->start = (HuffmanCode*)WebPSafeMalloc(size, sizeof(*root->start));
|
||||
+ if (root->start == NULL) return 0;
|
||||
+ root->curr_table = root->start;
|
||||
+ root->next = NULL;
|
||||
+ root->size = size;
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+void VP8LHuffmanTablesDeallocate(HuffmanTables* const huffman_tables) {
|
||||
+ HuffmanTablesSegment *current, *next;
|
||||
+ if (huffman_tables == NULL) return;
|
||||
+ // Free the root node.
|
||||
+ current = &huffman_tables->root;
|
||||
+ next = current->next;
|
||||
+ WebPSafeFree(current->start);
|
||||
+ current->start = NULL;
|
||||
+ current->next = NULL;
|
||||
+ current = next;
|
||||
+ // Free the following nodes.
|
||||
+ while (current != NULL) {
|
||||
+ next = current->next;
|
||||
+ WebPSafeFree(current->start);
|
||||
+ WebPSafeFree(current);
|
||||
+ current = next;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/utils/huffman_utils.h b/src/utils/huffman_utils.h
|
||||
index 13b7ad1ac40c5316f5506d9b4cbf5039c9fd5600..98415c532895374ea28fc1dc5c9a15c751ea9ba0 100644
|
||||
--- a/src/utils/huffman_utils.h
|
||||
+++ b/src/utils/huffman_utils.h
|
||||
@@ -43,6 +43,29 @@ typedef struct {
|
||||
// or non-literal symbol otherwise
|
||||
} HuffmanCode32;
|
||||
|
||||
+// Contiguous memory segment of HuffmanCodes.
|
||||
+typedef struct HuffmanTablesSegment {
|
||||
+ HuffmanCode* start;
|
||||
+ // Pointer to where we are writing into the segment. Starts at 'start' and
|
||||
+ // cannot go beyond 'start' + 'size'.
|
||||
+ HuffmanCode* curr_table;
|
||||
+ // Pointer to the next segment in the chain.
|
||||
+ struct HuffmanTablesSegment* next;
|
||||
+ int size;
|
||||
+} HuffmanTablesSegment;
|
||||
+
|
||||
+// Chained memory segments of HuffmanCodes.
|
||||
+typedef struct HuffmanTables {
|
||||
+ HuffmanTablesSegment root;
|
||||
+ // Currently processed segment. At first, this is 'root'.
|
||||
+ HuffmanTablesSegment* curr_segment;
|
||||
+} HuffmanTables;
|
||||
+
|
||||
+// Allocates a HuffmanTables with 'size' contiguous HuffmanCodes. Returns 0 on
|
||||
+// memory allocation error, 1 otherwise.
|
||||
+int VP8LHuffmanTablesAllocate(int size, HuffmanTables* huffman_tables);
|
||||
+void VP8LHuffmanTablesDeallocate(HuffmanTables* const huffman_tables);
|
||||
+
|
||||
#define HUFFMAN_PACKED_BITS 6
|
||||
#define HUFFMAN_PACKED_TABLE_SIZE (1u << HUFFMAN_PACKED_BITS)
|
||||
|
||||
@@ -78,9 +101,7 @@ void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups);
|
||||
// the huffman table.
|
||||
// Returns built table size or 0 in case of error (invalid tree or
|
||||
// memory error).
|
||||
-// If root_table is NULL, it returns 0 if a lookup cannot be built, something
|
||||
-// > 0 otherwise (but not the table size).
|
||||
-int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
||||
+int VP8LBuildHuffmanTable(HuffmanTables* const root_table, int root_bits,
|
||||
const int code_lengths[], int code_lengths_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -55,3 +55,4 @@ chore_enable_c_17_for_native_modules.patch
|
||||
enable_crashpad_linux_node_processes.patch
|
||||
cherry-pick-09ae62b.patch
|
||||
allow_embedder_to_control_codegenerationfromstringscallback.patch
|
||||
fix_do_not_resolve_electron_entrypoints.patch
|
||||
|
||||
47
patches/node/fix_do_not_resolve_electron_entrypoints.patch
Normal file
47
patches/node/fix_do_not_resolve_electron_entrypoints.patch
Normal file
@@ -0,0 +1,47 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <marshallofsound@electronjs.org>
|
||||
Date: Wed, 26 Jul 2023 17:03:15 -0700
|
||||
Subject: fix: do not resolve electron entrypoints
|
||||
|
||||
This wastes fs cycles and can result in strange behavior if this path actually exists on disk
|
||||
|
||||
diff --git a/lib/internal/modules/run_main.js b/lib/internal/modules/run_main.js
|
||||
index 5a50d5d6afab6e6648f72a1c0efa1df4cd80bcd9..ebc9999358ccf16689dc02322eb1aeb86355f39b 100644
|
||||
--- a/lib/internal/modules/run_main.js
|
||||
+++ b/lib/internal/modules/run_main.js
|
||||
@@ -3,6 +3,7 @@
|
||||
const {
|
||||
ObjectCreate,
|
||||
StringPrototypeEndsWith,
|
||||
+ StringPrototypeStartsWith,
|
||||
} = primordials;
|
||||
const CJSLoader = require('internal/modules/cjs/loader');
|
||||
const { Module, toRealPath, readPackageScope } = CJSLoader;
|
||||
@@ -13,6 +14,13 @@ const {
|
||||
} = require('internal/modules/esm/handle_process_exit');
|
||||
|
||||
function resolveMainPath(main) {
|
||||
+ // For built-in modules used as the main entry point we _never_
|
||||
+ // want to waste cycles resolving them to file paths on disk
|
||||
+ // that actually might exist
|
||||
+ if (typeof main === 'string' && StringPrototypeStartsWith(main, 'electron/js2c')) {
|
||||
+ return main;
|
||||
+ }
|
||||
+
|
||||
// Note extension resolution for the main entry point can be deprecated in a
|
||||
// future major.
|
||||
// Module._findPath is monkey-patchable here.
|
||||
@@ -28,6 +36,13 @@ function resolveMainPath(main) {
|
||||
}
|
||||
|
||||
function shouldUseESMLoader(mainPath) {
|
||||
+ // For built-in modules used as the main entry point we _never_
|
||||
+ // want to waste cycles resolving them to file paths on disk
|
||||
+ // that actually might exist
|
||||
+ if (typeof mainPath === 'string' && StringPrototypeStartsWith(mainPath, 'electron/js2c')) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* @type {string[]} userLoaders A list of custom loaders registered by the user
|
||||
* (or an empty list when none have been registered).
|
||||
@@ -1,2 +1,3 @@
|
||||
enforce_program_stack_limits_on_function_parameters.patch
|
||||
enforce_size_limits_on_struct_and_array_declarations.patch
|
||||
enforce_an_upper_limit_of_715_million_path_verbs_in_skpath.patch
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: John Stiles <johnstiles@google.com>
|
||||
Date: Thu, 3 Aug 2023 13:33:52 -0400
|
||||
Subject: Enforce an upper limit of 715 million path verbs in SkPath.
|
||||
|
||||
Bug: chromium:1464215
|
||||
Change-Id: Iedb7d73fc80de5ffb881b664dd77314cc2c6b108
|
||||
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/735316
|
||||
Reviewed-by: Brian Osman <brianosman@google.com>
|
||||
Commit-Queue: John Stiles <johnstiles@google.com>
|
||||
|
||||
diff --git a/relnotes/path_715M.md b/relnotes/path_715M.md
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..7be9a40f1fc5b4f6432c490725b05d536d497fb1
|
||||
--- /dev/null
|
||||
+++ b/relnotes/path_715M.md
|
||||
@@ -0,0 +1 @@
|
||||
+SkPath now enforces an upper limit of 715 million path verbs.
|
||||
diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp
|
||||
index 7caac5ca6f05d89a2986c3eea432eedcd201203f..1a9279784b5b7bab3e0ca6dad9d1fd49a9038965 100644
|
||||
--- a/src/core/SkPath.cpp
|
||||
+++ b/src/core/SkPath.cpp
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "src/pathops/SkPathOpsPoint.h"
|
||||
|
||||
#include <cmath>
|
||||
+#include <limits.h>
|
||||
#include <utility>
|
||||
|
||||
struct SkPath_Storage_Equivalent {
|
||||
@@ -3401,43 +3402,52 @@ bool SkPath::IsCubicDegenerate(const SkPoint& p1, const SkPoint& p2,
|
||||
|
||||
SkPathVerbAnalysis sk_path_analyze_verbs(const uint8_t vbs[], int verbCount) {
|
||||
SkPathVerbAnalysis info = {false, 0, 0, 0};
|
||||
-
|
||||
bool needMove = true;
|
||||
bool invalid = false;
|
||||
- for (int i = 0; i < verbCount; ++i) {
|
||||
- switch ((SkPathVerb)vbs[i]) {
|
||||
- case SkPathVerb::kMove:
|
||||
- needMove = false;
|
||||
- info.points += 1;
|
||||
- break;
|
||||
- case SkPathVerb::kLine:
|
||||
- invalid |= needMove;
|
||||
- info.segmentMask |= kLine_SkPathSegmentMask;
|
||||
- info.points += 1;
|
||||
- break;
|
||||
- case SkPathVerb::kQuad:
|
||||
- invalid |= needMove;
|
||||
- info.segmentMask |= kQuad_SkPathSegmentMask;
|
||||
- info.points += 2;
|
||||
- break;
|
||||
- case SkPathVerb::kConic:
|
||||
- invalid |= needMove;
|
||||
- info.segmentMask |= kConic_SkPathSegmentMask;
|
||||
- info.points += 2;
|
||||
- info.weights += 1;
|
||||
- break;
|
||||
- case SkPathVerb::kCubic:
|
||||
- invalid |= needMove;
|
||||
- info.segmentMask |= kCubic_SkPathSegmentMask;
|
||||
- info.points += 3;
|
||||
- break;
|
||||
- case SkPathVerb::kClose:
|
||||
- invalid |= needMove;
|
||||
- needMove = true;
|
||||
- break;
|
||||
- default:
|
||||
- invalid = true;
|
||||
- break;
|
||||
+
|
||||
+ if (verbCount >= (INT_MAX / 3)) {
|
||||
+ // A path with an extremely high number of quad, conic or cubic verbs could cause
|
||||
+ // `info.points` to overflow. To prevent against this, we reject extremely large paths. This
|
||||
+ // check is conservative and assumes the worst case (in particular, it assumes that every
|
||||
+ // verb consumes 3 points, which would only happen for a path composed entirely of cubics).
|
||||
+ // This limits us to 700 million verbs, which is large enough for any reasonable use case.
|
||||
+ invalid = true;
|
||||
+ } else {
|
||||
+ for (int i = 0; i < verbCount; ++i) {
|
||||
+ switch ((SkPathVerb)vbs[i]) {
|
||||
+ case SkPathVerb::kMove:
|
||||
+ needMove = false;
|
||||
+ info.points += 1;
|
||||
+ break;
|
||||
+ case SkPathVerb::kLine:
|
||||
+ invalid |= needMove;
|
||||
+ info.segmentMask |= kLine_SkPathSegmentMask;
|
||||
+ info.points += 1;
|
||||
+ break;
|
||||
+ case SkPathVerb::kQuad:
|
||||
+ invalid |= needMove;
|
||||
+ info.segmentMask |= kQuad_SkPathSegmentMask;
|
||||
+ info.points += 2;
|
||||
+ break;
|
||||
+ case SkPathVerb::kConic:
|
||||
+ invalid |= needMove;
|
||||
+ info.segmentMask |= kConic_SkPathSegmentMask;
|
||||
+ info.points += 2;
|
||||
+ info.weights += 1;
|
||||
+ break;
|
||||
+ case SkPathVerb::kCubic:
|
||||
+ invalid |= needMove;
|
||||
+ info.segmentMask |= kCubic_SkPathSegmentMask;
|
||||
+ info.points += 3;
|
||||
+ break;
|
||||
+ case SkPathVerb::kClose:
|
||||
+ invalid |= needMove;
|
||||
+ needMove = true;
|
||||
+ break;
|
||||
+ default:
|
||||
+ invalid = true;
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
info.valid = !invalid;
|
||||
@@ -25,3 +25,10 @@ cherry-pick-2e76270cf65e.patch
|
||||
utf-8_q_shared-struct_20fix_20using_20shared_20objects_20as.patch
|
||||
merged_runtime_set_instance_prototypes_directly_on_maps.patch
|
||||
merged_compiler_stackcheck_can_have_side_effects.patch
|
||||
promise_allsettled_mark_values_array_as_cow.patch
|
||||
merged_builtins_clear_fixedarray_slot_in_promise_builtins.patch
|
||||
merged_compiler_check_for_read-only_property_on.patch
|
||||
shared-struct_fix_for-in_enumeration.patch
|
||||
merged_squashed_multiple_commits.patch
|
||||
cherry-pick-038530c94a06.patch
|
||||
cherry-pick-b0ad701a609a.patch
|
||||
|
||||
49
patches/v8/cherry-pick-038530c94a06.patch
Normal file
49
patches/v8/cherry-pick-038530c94a06.patch
Normal file
@@ -0,0 +1,49 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Tebbi <tebbi@chromium.org>
|
||||
Date: Wed, 30 Aug 2023 10:59:48 +0200
|
||||
Subject: Merged: [turbofan] Growing a non-JSArray packed elements kind makes
|
||||
it holey
|
||||
|
||||
Bug: chromium:1473247
|
||||
(cherry picked from commit ae7dc61652805bc8e2b060d53b2b6da7cf846b6f)
|
||||
|
||||
Change-Id: I5268513bc91ca0cc18e3e2115244c0b090afa0da
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4831892
|
||||
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
|
||||
Owners-Override: Leszek Swirski <leszeks@chromium.org>
|
||||
Commit-Queue: Darius Mercadier <dmercadier@chromium.org>
|
||||
Reviewed-by: Darius Mercadier <dmercadier@chromium.org>
|
||||
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/11.6@{#34}
|
||||
Cr-Branched-From: e29c028f391389a7a60ee37097e3ca9e396d6fa4-refs/heads/11.6.189@{#3}
|
||||
Cr-Branched-From: 95cbef20e2aa556a1ea75431a48b36c4de6b9934-refs/heads/main@{#88340}
|
||||
|
||||
diff --git a/src/compiler/js-native-context-specialization.cc b/src/compiler/js-native-context-specialization.cc
|
||||
index 31b6d2dd0944a4d541947c773b175f86d24c86f6..72d97098c60e78b53cfa2356eabdc54f3eafc133 100644
|
||||
--- a/src/compiler/js-native-context-specialization.cc
|
||||
+++ b/src/compiler/js-native-context-specialization.cc
|
||||
@@ -3628,15 +3628,21 @@ JSNativeContextSpecialization::BuildElementAccess(
|
||||
// the (potential) backing store growth would normalize and thus
|
||||
// the elements kind of the {receiver} would change to slow mode.
|
||||
//
|
||||
- // For PACKED_*_ELEMENTS the {index} must be within the range
|
||||
+ // For JSArray PACKED_*_ELEMENTS the {index} must be within the range
|
||||
// [0,length+1[ to be valid. In case {index} equals {length},
|
||||
// the {receiver} will be extended, but kept packed.
|
||||
+ //
|
||||
+ // Non-JSArray PACKED_*_ELEMENTS always grow by adding holes because they
|
||||
+ // lack the magical length property, which requires a map transition.
|
||||
+ // So we can assume that this did not happen if we did not see this map.
|
||||
Node* limit =
|
||||
IsHoleyElementsKind(elements_kind)
|
||||
? graph()->NewNode(simplified()->NumberAdd(), elements_length,
|
||||
jsgraph()->Constant(JSObject::kMaxGap))
|
||||
- : graph()->NewNode(simplified()->NumberAdd(), length,
|
||||
- jsgraph()->OneConstant());
|
||||
+ : receiver_is_jsarray
|
||||
+ ? graph()->NewNode(simplified()->NumberAdd(), length,
|
||||
+ jsgraph()->OneConstant())
|
||||
+ : elements_length;
|
||||
index = effect = graph()->NewNode(
|
||||
simplified()->CheckBounds(
|
||||
FeedbackSource(), CheckBoundsFlag::kConvertStringAndMinusZero),
|
||||
56
patches/v8/cherry-pick-b0ad701a609a.patch
Normal file
56
patches/v8/cherry-pick-b0ad701a609a.patch
Normal file
@@ -0,0 +1,56 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shu-yu Guo <syg@chromium.org>
|
||||
Date: Wed, 6 Sep 2023 17:36:38 -0700
|
||||
Subject: Merged: [builtins] Clear FixedArray slot in Promise builtins
|
||||
|
||||
(cherry picked from commit f1884222ad56734e56d80f9707e0e8279af9049e)
|
||||
|
||||
Bug: chromium:1479104
|
||||
Change-Id: Iddc16d8add4dc6bf6f55f537da44770bea6f4bc3
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4862980
|
||||
Auto-Submit: Shu-yu Guo <syg@chromium.org>
|
||||
Reviewed-by: Adam Klein <adamk@chromium.org>
|
||||
Commit-Queue: Adam Klein <adamk@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/11.6@{#36}
|
||||
Cr-Branched-From: e29c028f391389a7a60ee37097e3ca9e396d6fa4-refs/heads/11.6.189@{#3}
|
||||
Cr-Branched-From: 95cbef20e2aa556a1ea75431a48b36c4de6b9934-refs/heads/main@{#88340}
|
||||
|
||||
diff --git a/src/builtins/promise-any.tq b/src/builtins/promise-any.tq
|
||||
index 45bafac0e6b09143b69b21a7292f9ed6b9c46239..d531d57a375ba33bf11ccf698da5918f1e25f38c 100644
|
||||
--- a/src/builtins/promise-any.tq
|
||||
+++ b/src/builtins/promise-any.tq
|
||||
@@ -106,9 +106,10 @@ PromiseAnyRejectElementClosure(
|
||||
const index = identityHash - 1;
|
||||
|
||||
// 6. Let errors be F.[[Errors]].
|
||||
- let errors = *ContextSlot(
|
||||
+ let errorsRef:&FixedArray = ContextSlot(
|
||||
context,
|
||||
PromiseAnyRejectElementContextSlots::kPromiseAnyRejectElementErrorsSlot);
|
||||
+ let errors = *errorsRef;
|
||||
|
||||
// 7. Let promiseCapability be F.[[Capability]].
|
||||
|
||||
@@ -134,10 +135,7 @@ PromiseAnyRejectElementClosure(
|
||||
IntPtrMax(SmiUntag(remainingElementsCount) - 1, index + 1);
|
||||
if (newCapacity > errors.length_intptr) deferred {
|
||||
errors = ExtractFixedArray(errors, 0, errors.length_intptr, newCapacity);
|
||||
- *ContextSlot(
|
||||
- context,
|
||||
- PromiseAnyRejectElementContextSlots::
|
||||
- kPromiseAnyRejectElementErrorsSlot) = errors;
|
||||
+ *errorsRef = errors;
|
||||
}
|
||||
errors.objects[index] = value;
|
||||
|
||||
@@ -155,6 +153,10 @@ PromiseAnyRejectElementClosure(
|
||||
|
||||
// b. Set error.[[AggregateErrors]] to errors.
|
||||
const error = ConstructAggregateError(errors);
|
||||
+
|
||||
+ // After this point, errors escapes to user code. Clear the slot.
|
||||
+ *errorsRef = kEmptyFixedArray;
|
||||
+
|
||||
// c. Return ? Call(promiseCapability.[[Reject]], undefined, « error »).
|
||||
const capability = *ContextSlot(
|
||||
context,
|
||||
@@ -0,0 +1,126 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shu-yu Guo <syg@chromium.org>
|
||||
Date: Wed, 2 Aug 2023 17:41:03 -0700
|
||||
Subject: Merged: [builtins] Clear FixedArray slot in Promise builtins
|
||||
|
||||
Fixed: chromium:1468943
|
||||
(cherry picked from commit a84849ed718932b94dc877bb44a2d38eb8a0aef9)
|
||||
|
||||
Change-Id: Ia2b181c373c15bd1840e2a1572c0e930cddcd788
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4753495
|
||||
Commit-Queue: Adam Klein <adamk@chromium.org>
|
||||
Reviewed-by: Adam Klein <adamk@chromium.org>
|
||||
Auto-Submit: Shu-yu Guo <syg@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/11.6@{#28}
|
||||
Cr-Branched-From: e29c028f391389a7a60ee37097e3ca9e396d6fa4-refs/heads/11.6.189@{#3}
|
||||
Cr-Branched-From: 95cbef20e2aa556a1ea75431a48b36c4de6b9934-refs/heads/main@{#88340}
|
||||
|
||||
diff --git a/src/builtins/promise-all-element-closure.tq b/src/builtins/promise-all-element-closure.tq
|
||||
index db3fb0134cf5bf0065174153171ef44a726a6fff..036e3c7b7473eae98f39a6da4472e826420086c8 100644
|
||||
--- a/src/builtins/promise-all-element-closure.tq
|
||||
+++ b/src/builtins/promise-all-element-closure.tq
|
||||
@@ -175,11 +175,22 @@ transitioning macro PromiseAllResolveElementClosure<F: type>(
|
||||
*NativeContextSlot(
|
||||
nativeContext, ContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX);
|
||||
|
||||
- // If resolve and reject handlers close over values to keep track of whether
|
||||
- // an input promise is already settled, mark the values array as COW before
|
||||
- // letting it escape to user code.
|
||||
- if (hasResolveAndRejectClosures) MakeFixedArrayCOW(values);
|
||||
-
|
||||
+ // After this point, values escapes to user code.
|
||||
+ //
|
||||
+ // If resolve and reject handlers close over values to keep track of
|
||||
+ // whether an input promise is already settled, mark the values array as
|
||||
+ // COW. The original values array is still needed to guard against resolve
|
||||
+ // or reject being called multiple times for an element.
|
||||
+ //
|
||||
+ // Otherwise, clear the slot.
|
||||
+ if (hasResolveAndRejectClosures) {
|
||||
+ MakeFixedArrayCOW(values);
|
||||
+ } else {
|
||||
+ *ContextSlot(
|
||||
+ promiseContext,
|
||||
+ PromiseAllResolveElementContextSlots::
|
||||
+ kPromiseAllResolveElementValuesSlot) = kEmptyFixedArray;
|
||||
+ }
|
||||
const valuesArray = NewJSArray(arrayMap, values);
|
||||
Call(promiseContext, resolve, Undefined, valuesArray);
|
||||
}
|
||||
diff --git a/src/builtins/promise-all.tq b/src/builtins/promise-all.tq
|
||||
index 4d131abb44b7593d3e361d1d2f971380ee91850c..7205279526fa9edd93f154feb9694c22cae68606 100644
|
||||
--- a/src/builtins/promise-all.tq
|
||||
+++ b/src/builtins/promise-all.tq
|
||||
@@ -278,15 +278,16 @@ Reject(JSAny) {
|
||||
|
||||
check(remainingElementsCount >= 0);
|
||||
|
||||
+ const valuesRef:&FixedArray = ContextSlot(
|
||||
+ resolveElementContext,
|
||||
+ PromiseAllResolveElementContextSlots::
|
||||
+ kPromiseAllResolveElementValuesSlot);
|
||||
+ const values = *valuesRef;
|
||||
+
|
||||
if (remainingElementsCount > 0) {
|
||||
// Pre-allocate the backing store for the {values} to the desired
|
||||
// capacity. We may already have elements in "values" - this happens
|
||||
// when the Thenable calls the resolve callback immediately.
|
||||
- const valuesRef:&FixedArray = ContextSlot(
|
||||
- resolveElementContext,
|
||||
- PromiseAllResolveElementContextSlots::
|
||||
- kPromiseAllResolveElementValuesSlot);
|
||||
- const values = *valuesRef;
|
||||
// 'index' is a 1-based index and incremented after every Promise. Later we
|
||||
// use 'values' as a 0-based array, so capacity 'index - 1' is enough.
|
||||
const newCapacity = SmiUntag(index) - 1;
|
||||
@@ -301,19 +302,23 @@ Reject(JSAny) {
|
||||
// Let valuesArray be CreateArrayFromList(values).
|
||||
// Perform ? Call(resultCapability.[[Resolve]], undefined,
|
||||
// « valuesArray »).
|
||||
-
|
||||
- const values: FixedArray = *ContextSlot(
|
||||
- resolveElementContext,
|
||||
- PromiseAllResolveElementContextSlots::
|
||||
- kPromiseAllResolveElementValuesSlot);
|
||||
const arrayMap =
|
||||
*NativeContextSlot(
|
||||
nativeContext, ContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX);
|
||||
|
||||
+ // After this point, values escapes to user code.
|
||||
+ //
|
||||
// If resolve and reject handlers close over values to keep track of
|
||||
// whether an input promise is already settled, mark the values array as
|
||||
- // COW before letting it escape to user code.
|
||||
- if (hasResolveAndRejectClosures) MakeFixedArrayCOW(values);
|
||||
+ // COW. The original values array is still needed to guard against resolve
|
||||
+ // or reject being called multiple times for an element.
|
||||
+ //
|
||||
+ // Otherwise, clear the slot.
|
||||
+ if (hasResolveAndRejectClosures) {
|
||||
+ MakeFixedArrayCOW(values);
|
||||
+ } else {
|
||||
+ *valuesRef = kEmptyFixedArray;
|
||||
+ }
|
||||
|
||||
const valuesArray = NewJSArray(arrayMap, values);
|
||||
Call(nativeContext, UnsafeCast<JSAny>(resolve), Undefined, valuesArray);
|
||||
diff --git a/src/builtins/promise-any.tq b/src/builtins/promise-any.tq
|
||||
index 7e707e649f11bc946a6d1173180d7293fe94d8ce..45bafac0e6b09143b69b21a7292f9ed6b9c46239 100644
|
||||
--- a/src/builtins/promise-any.tq
|
||||
+++ b/src/builtins/promise-any.tq
|
||||
@@ -313,10 +313,14 @@ Reject(JSAny) {
|
||||
|
||||
// We may already have elements in "errors" - this happens when the
|
||||
// Thenable calls the reject callback immediately.
|
||||
- const errors: FixedArray = *ContextSlot(
|
||||
+ const errorsRef:&FixedArray = ContextSlot(
|
||||
rejectElementContext,
|
||||
PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementErrorsSlot);
|
||||
+ const errors: FixedArray = *errorsRef;
|
||||
+
|
||||
+ // After this point, errors escapes to user code. Clear the slot.
|
||||
+ *errorsRef = kEmptyFixedArray;
|
||||
|
||||
check(errors.length == index - 1);
|
||||
const error = ConstructAggregateError(errors);
|
||||
@@ -0,0 +1,31 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Tebbi <tebbi@chromium.org>
|
||||
Date: Tue, 13 Jun 2023 11:50:11 +0200
|
||||
Subject: Merged: [compiler] check for read-only property on
|
||||
AccessMode::kDefine
|
||||
|
||||
(cherry picked from commit 95eda07ddbc1839e39b3d1ff5db329c0ceb6dfaa)
|
||||
|
||||
Change-Id: Ic5799a32e7c312e41cd0a7e1e6073a235414d56f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4665588
|
||||
Auto-Submit: Tobias Tebbi <tebbi@chromium.org>
|
||||
Reviewed-by: Darius Mercadier <dmercadier@chromium.org>
|
||||
Commit-Queue: Darius Mercadier <dmercadier@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/11.4@{#53}
|
||||
Cr-Branched-From: 8a8a1e7086dacc426965d3875914efa66663c431-refs/heads/11.4.183@{#1}
|
||||
Cr-Branched-From: 5483d8e816e0bbce865cbbc3fa0ab357e6330bab-refs/heads/main@{#87241}
|
||||
|
||||
diff --git a/src/compiler/access-info.cc b/src/compiler/access-info.cc
|
||||
index 7c35df243af97d0fe7ae5b25bd31b01afe1d1e6b..b464581f27535207493c6854b4447bab4cbb3a5f 100644
|
||||
--- a/src/compiler/access-info.cc
|
||||
+++ b/src/compiler/access-info.cc
|
||||
@@ -758,8 +758,7 @@ PropertyAccessInfo AccessInfoFactory::ComputePropertyAccessInfo(
|
||||
}
|
||||
|
||||
if (index.is_found()) {
|
||||
- if (access_mode == AccessMode::kStore ||
|
||||
- access_mode == AccessMode::kStoreInLiteral) {
|
||||
+ if (IsAnyStore(access_mode)) {
|
||||
DCHECK(!map.is_dictionary_map());
|
||||
|
||||
// Don't bother optimizing stores to read-only properties.
|
||||
51
patches/v8/merged_squashed_multiple_commits.patch
Normal file
51
patches/v8/merged_squashed_multiple_commits.patch
Normal file
@@ -0,0 +1,51 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Samuel=20Gro=C3=9F?= <saelo@chromium.org>
|
||||
Date: Thu, 17 Aug 2023 09:10:19 +0000
|
||||
Subject: Merged: Squashed multiple commits.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Merged: [runtime] Recreate enum cache on map update
|
||||
Revision: 1c623f9ff6e077be1c66f155485ea4005ddb6574
|
||||
|
||||
Merged: [runtime] Don't try to create empty enum cache.
|
||||
Revision: 5516e06237c9f0013121f47319e8c253c896d52d
|
||||
|
||||
BUG=chromium:1470668,chromium:1472317
|
||||
R=tebbi@chromium.org
|
||||
|
||||
Change-Id: I31d5491aba663661ba68bb55631747a195ed084e
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4788990
|
||||
Commit-Queue: Samuel Groß <saelo@chromium.org>
|
||||
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/11.6@{#32}
|
||||
Cr-Branched-From: e29c028f391389a7a60ee37097e3ca9e396d6fa4-refs/heads/11.6.189@{#3}
|
||||
Cr-Branched-From: 95cbef20e2aa556a1ea75431a48b36c4de6b9934-refs/heads/main@{#88340}
|
||||
|
||||
diff --git a/src/objects/map-updater.cc b/src/objects/map-updater.cc
|
||||
index be6568aac4730d08601e883b80092bbd6ee8081a..2ebfc84d3e326abf2602a1af8309024a46cb9c9d 100644
|
||||
--- a/src/objects/map-updater.cc
|
||||
+++ b/src/objects/map-updater.cc
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "src/execution/isolate.h"
|
||||
#include "src/handles/handles.h"
|
||||
#include "src/objects/field-type.h"
|
||||
+#include "src/objects/keys.h"
|
||||
#include "src/objects/objects-inl.h"
|
||||
#include "src/objects/objects.h"
|
||||
#include "src/objects/property-details.h"
|
||||
@@ -1035,6 +1036,13 @@ MapUpdater::State MapUpdater::ConstructNewMap() {
|
||||
// the new descriptors to maintain descriptors sharing invariant.
|
||||
split_map->ReplaceDescriptors(isolate_, *new_descriptors);
|
||||
|
||||
+ // If the old descriptors had an enum cache, make sure the new ones do too.
|
||||
+ if (old_descriptors_->enum_cache().keys().length() > 0 &&
|
||||
+ new_map->NumberOfEnumerableProperties() > 0) {
|
||||
+ FastKeyAccumulator::InitializeFastPropertyEnumCache(
|
||||
+ isolate_, new_map, new_map->NumberOfEnumerableProperties());
|
||||
+ }
|
||||
+
|
||||
if (has_integrity_level_transition_) {
|
||||
target_map_ = new_map;
|
||||
state_ = kAtIntegrityLevelSource;
|
||||
105
patches/v8/promise_allsettled_mark_values_array_as_cow.patch
Normal file
105
patches/v8/promise_allsettled_mark_values_array_as_cow.patch
Normal file
@@ -0,0 +1,105 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shu-yu Guo <syg@chromium.org>
|
||||
Date: Thu, 27 Oct 2022 18:02:55 -0700
|
||||
Subject: Mark values array as COW
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Bug: chromium:1377790
|
||||
Change-Id: I36bb9e35ca7ecaaa7ed4605f1a19293bc662f341
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3988925
|
||||
Auto-Submit: Shu-yu Guo <syg@chromium.org>
|
||||
Reviewed-by: Marja Hölttä <marja@chromium.org>
|
||||
Commit-Queue: Marja Hölttä <marja@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#83969}
|
||||
|
||||
diff --git a/src/builtins/promise-all-element-closure.tq b/src/builtins/promise-all-element-closure.tq
|
||||
index 24b9cfb346e022a0ad80f7712b249d1c38ae562d..db3fb0134cf5bf0065174153171ef44a726a6fff 100644
|
||||
--- a/src/builtins/promise-all-element-closure.tq
|
||||
+++ b/src/builtins/promise-all-element-closure.tq
|
||||
@@ -174,6 +174,12 @@ transitioning macro PromiseAllResolveElementClosure<F: type>(
|
||||
const arrayMap =
|
||||
*NativeContextSlot(
|
||||
nativeContext, ContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX);
|
||||
+
|
||||
+ // If resolve and reject handlers close over values to keep track of whether
|
||||
+ // an input promise is already settled, mark the values array as COW before
|
||||
+ // letting it escape to user code.
|
||||
+ if (hasResolveAndRejectClosures) MakeFixedArrayCOW(values);
|
||||
+
|
||||
const valuesArray = NewJSArray(arrayMap, values);
|
||||
Call(promiseContext, resolve, Undefined, valuesArray);
|
||||
}
|
||||
diff --git a/src/builtins/promise-all.tq b/src/builtins/promise-all.tq
|
||||
index 29c468ed3eb34f9f348f115b8b6a77174e708bcc..4d131abb44b7593d3e361d1d2f971380ee91850c 100644
|
||||
--- a/src/builtins/promise-all.tq
|
||||
+++ b/src/builtins/promise-all.tq
|
||||
@@ -138,7 +138,8 @@ transitioning macro PerformPromiseAll<F1: type, F2: type>(
|
||||
nativeContext: NativeContext, iter: iterator::IteratorRecord,
|
||||
constructor: Constructor, capability: PromiseCapability,
|
||||
promiseResolveFunction: JSAny, createResolveElementFunctor: F1,
|
||||
- createRejectElementFunctor: F2): JSAny labels
|
||||
+ createRejectElementFunctor: F2,
|
||||
+ hasResolveAndRejectClosures: constexpr bool): JSAny labels
|
||||
Reject(JSAny) {
|
||||
const promise = capability.promise;
|
||||
const resolve = capability.resolve;
|
||||
@@ -308,6 +309,12 @@ Reject(JSAny) {
|
||||
const arrayMap =
|
||||
*NativeContextSlot(
|
||||
nativeContext, ContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX);
|
||||
+
|
||||
+ // If resolve and reject handlers close over values to keep track of
|
||||
+ // whether an input promise is already settled, mark the values array as
|
||||
+ // COW before letting it escape to user code.
|
||||
+ if (hasResolveAndRejectClosures) MakeFixedArrayCOW(values);
|
||||
+
|
||||
const valuesArray = NewJSArray(arrayMap, values);
|
||||
Call(nativeContext, UnsafeCast<JSAny>(resolve), Undefined, valuesArray);
|
||||
}
|
||||
@@ -319,7 +326,8 @@ Reject(JSAny) {
|
||||
transitioning macro GeneratePromiseAll<F1: type, F2: type>(
|
||||
implicit context: Context)(
|
||||
receiver: JSAny, iterable: JSAny, createResolveElementFunctor: F1,
|
||||
- createRejectElementFunctor: F2, message: constexpr string): JSAny {
|
||||
+ createRejectElementFunctor: F2, message: constexpr string,
|
||||
+ hasResolveAndRejectClosures: constexpr bool): JSAny {
|
||||
const nativeContext = LoadNativeContext(context);
|
||||
// Let C be the this value.
|
||||
// If Type(C) is not Object, throw a TypeError exception.
|
||||
@@ -352,7 +360,8 @@ transitioning macro GeneratePromiseAll<F1: type, F2: type>(
|
||||
// IfAbruptRejectPromise(result, promiseCapability).
|
||||
return PerformPromiseAll(
|
||||
nativeContext, i, constructor, capability, promiseResolveFunction,
|
||||
- createResolveElementFunctor, createRejectElementFunctor)
|
||||
+ createResolveElementFunctor, createRejectElementFunctor,
|
||||
+ hasResolveAndRejectClosures)
|
||||
otherwise Reject;
|
||||
} catch (e, _message) deferred {
|
||||
goto Reject(e);
|
||||
@@ -368,7 +377,7 @@ transitioning javascript builtin PromiseAll(
|
||||
js-implicit context: Context, receiver: JSAny)(iterable: JSAny): JSAny {
|
||||
return GeneratePromiseAll(
|
||||
receiver, iterable, PromiseAllResolveElementFunctor{},
|
||||
- PromiseAllRejectElementFunctor{}, 'Promise.all');
|
||||
+ PromiseAllRejectElementFunctor{}, 'Promise.all', false);
|
||||
}
|
||||
|
||||
// ES#sec-promise.allsettled
|
||||
@@ -377,7 +386,7 @@ transitioning javascript builtin PromiseAllSettled(
|
||||
js-implicit context: Context, receiver: JSAny)(iterable: JSAny): JSAny {
|
||||
return GeneratePromiseAll(
|
||||
receiver, iterable, PromiseAllSettledResolveElementFunctor{},
|
||||
- PromiseAllSettledRejectElementFunctor{}, 'Promise.allSettled');
|
||||
+ PromiseAllSettledRejectElementFunctor{}, 'Promise.allSettled', true);
|
||||
}
|
||||
|
||||
extern macro PromiseAllResolveElementSharedFunConstant(): SharedFunctionInfo;
|
||||
@@ -385,4 +394,6 @@ extern macro PromiseAllSettledRejectElementSharedFunConstant():
|
||||
SharedFunctionInfo;
|
||||
extern macro PromiseAllSettledResolveElementSharedFunConstant():
|
||||
SharedFunctionInfo;
|
||||
+
|
||||
+extern macro MakeFixedArrayCOW(FixedArray): void;
|
||||
}
|
||||
359
patches/v8/shared-struct_fix_for-in_enumeration.patch
Normal file
359
patches/v8/shared-struct_fix_for-in_enumeration.patch
Normal file
@@ -0,0 +1,359 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shu-yu Guo <syg@chromium.org>
|
||||
Date: Thu, 3 Nov 2022 08:48:39 -0700
|
||||
Subject: Fix for-in enumeration
|
||||
|
||||
for-in enumeration creates an EnumCache, which is currently incorrectly
|
||||
allocated in the per-thread heap. This CL preallocates the enum cache at
|
||||
SharedStructType-creation time.
|
||||
|
||||
Also drive-by fixes typos in the enum cache code.
|
||||
|
||||
Bug: v8:12547, chromium:1379616
|
||||
Change-Id: I1930f88844eca5ccfeebd8dfdcce4ad0bd80ee38
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3997701
|
||||
Commit-Queue: Shu-yu Guo <syg@chromium.org>
|
||||
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#84047}
|
||||
|
||||
diff --git a/src/builtins/builtins-struct.cc b/src/builtins/builtins-struct.cc
|
||||
index a0d75e72086592283070d8014cd043ef3bab1ff5..e0b3831cdc69c1c0acb2ec24925adc310303856e 100644
|
||||
--- a/src/builtins/builtins-struct.cc
|
||||
+++ b/src/builtins/builtins-struct.cc
|
||||
@@ -94,6 +94,16 @@ BUILTIN(SharedStructTypeConstructor) {
|
||||
// to it.
|
||||
instance_map->set_constructor_or_back_pointer(*factory->null_value());
|
||||
|
||||
+ // Pre-create the enum cache in the shared space, as otherwise for-in
|
||||
+ // enumeration will incorrectly create an enum cache in the per-thread heap.
|
||||
+ if (num_properties == 0) {
|
||||
+ instance_map->SetEnumLength(0);
|
||||
+ } else {
|
||||
+ FastKeyAccumulator::InitializeFastPropertyEnumCache(
|
||||
+ isolate, instance_map, num_properties, AllocationType::kSharedOld);
|
||||
+ DCHECK_EQ(num_properties, instance_map->EnumLength());
|
||||
+ }
|
||||
+
|
||||
return *constructor;
|
||||
}
|
||||
|
||||
diff --git a/src/heap/factory.cc b/src/heap/factory.cc
|
||||
index bcb2f6475ec357cb34f923c51e279641c644957d..d1285ab16f4113acd5cdee154f7b1ef133fd8e14 100644
|
||||
--- a/src/heap/factory.cc
|
||||
+++ b/src/heap/factory.cc
|
||||
@@ -415,9 +415,13 @@ Handle<PrototypeInfo> Factory::NewPrototypeInfo() {
|
||||
}
|
||||
|
||||
Handle<EnumCache> Factory::NewEnumCache(Handle<FixedArray> keys,
|
||||
- Handle<FixedArray> indices) {
|
||||
- auto result =
|
||||
- NewStructInternal<EnumCache>(ENUM_CACHE_TYPE, AllocationType::kOld);
|
||||
+ Handle<FixedArray> indices,
|
||||
+ AllocationType allocation) {
|
||||
+ DCHECK(allocation == AllocationType::kOld ||
|
||||
+ allocation == AllocationType::kSharedOld);
|
||||
+ DCHECK_EQ(allocation == AllocationType::kSharedOld,
|
||||
+ keys->InSharedHeap() && indices->InSharedHeap());
|
||||
+ auto result = NewStructInternal<EnumCache>(ENUM_CACHE_TYPE, allocation);
|
||||
DisallowGarbageCollection no_gc;
|
||||
result.set_keys(*keys);
|
||||
result.set_indices(*indices);
|
||||
diff --git a/src/heap/factory.h b/src/heap/factory.h
|
||||
index 6c9cc2d4d8ed1e9c7e14ccb35f6ad61dfa850cfa..748a3f91c881d8bdc723a4f21fcb6adfe6d3876e 100644
|
||||
--- a/src/heap/factory.h
|
||||
+++ b/src/heap/factory.h
|
||||
@@ -183,8 +183,9 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
|
||||
Handle<PrototypeInfo> NewPrototypeInfo();
|
||||
|
||||
// Create a new EnumCache struct.
|
||||
- Handle<EnumCache> NewEnumCache(Handle<FixedArray> keys,
|
||||
- Handle<FixedArray> indices);
|
||||
+ Handle<EnumCache> NewEnumCache(
|
||||
+ Handle<FixedArray> keys, Handle<FixedArray> indices,
|
||||
+ AllocationType allocation = AllocationType::kOld);
|
||||
|
||||
// Create a new Tuple2 struct.
|
||||
Handle<Tuple2> NewTuple2(Handle<Object> value1, Handle<Object> value2,
|
||||
diff --git a/src/objects/descriptor-array.h b/src/objects/descriptor-array.h
|
||||
index 5db091cbfe166a683f3c43273aece6d3d802d448..178e6d03af4be4512fc40257365437482be654eb 100644
|
||||
--- a/src/objects/descriptor-array.h
|
||||
+++ b/src/objects/descriptor-array.h
|
||||
@@ -65,10 +65,10 @@ class DescriptorArray
|
||||
|
||||
void ClearEnumCache();
|
||||
inline void CopyEnumCacheFrom(DescriptorArray array);
|
||||
- static void InitializeOrChangeEnumCache(Handle<DescriptorArray> descriptors,
|
||||
- Isolate* isolate,
|
||||
- Handle<FixedArray> keys,
|
||||
- Handle<FixedArray> indices);
|
||||
+ static void InitializeOrChangeEnumCache(
|
||||
+ Handle<DescriptorArray> descriptors, Isolate* isolate,
|
||||
+ Handle<FixedArray> keys, Handle<FixedArray> indices,
|
||||
+ AllocationType allocation_if_initialize);
|
||||
|
||||
// Accessors for fetching instance descriptor at descriptor number.
|
||||
inline Name GetKey(InternalIndex descriptor_number) const;
|
||||
diff --git a/src/objects/keys.cc b/src/objects/keys.cc
|
||||
index ac21fbf9c3d2d22bbd7049a620849e25d1257b4d..a0796864f1ecc6f1f32ca50635b9cb55cd04d7db 100644
|
||||
--- a/src/objects/keys.cc
|
||||
+++ b/src/objects/keys.cc
|
||||
@@ -312,7 +312,7 @@ void TrySettingEmptyEnumCache(JSReceiver object) {
|
||||
map.SetEnumLength(0);
|
||||
}
|
||||
|
||||
-bool CheckAndInitalizeEmptyEnumCache(JSReceiver object) {
|
||||
+bool CheckAndInitializeEmptyEnumCache(JSReceiver object) {
|
||||
if (object.map().EnumLength() == kInvalidEnumCacheSentinel) {
|
||||
TrySettingEmptyEnumCache(object);
|
||||
}
|
||||
@@ -342,7 +342,7 @@ void FastKeyAccumulator::Prepare() {
|
||||
only_own_has_simple_elements_ = false;
|
||||
}
|
||||
}
|
||||
- bool has_no_properties = CheckAndInitalizeEmptyEnumCache(current);
|
||||
+ bool has_no_properties = CheckAndInitializeEmptyEnumCache(current);
|
||||
if (has_no_properties) continue;
|
||||
last_prototype = current;
|
||||
has_empty_prototype_ = false;
|
||||
@@ -368,7 +368,7 @@ Handle<FixedArray> ReduceFixedArrayTo(Isolate* isolate,
|
||||
return isolate->factory()->CopyFixedArrayUpTo(array, length);
|
||||
}
|
||||
|
||||
-// Initializes and directly returns the enume cache. Users of this function
|
||||
+// Initializes and directly returns the enum cache. Users of this function
|
||||
// have to make sure to never directly leak the enum cache.
|
||||
Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate,
|
||||
Handle<JSObject> object) {
|
||||
@@ -398,51 +398,8 @@ Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate,
|
||||
return ReduceFixedArrayTo(isolate, keys, enum_length);
|
||||
}
|
||||
|
||||
- Handle<DescriptorArray> descriptors =
|
||||
- Handle<DescriptorArray>(map->instance_descriptors(isolate), isolate);
|
||||
- isolate->counters()->enum_cache_misses()->Increment();
|
||||
-
|
||||
- // Create the keys array.
|
||||
- int index = 0;
|
||||
- bool fields_only = true;
|
||||
- keys = isolate->factory()->NewFixedArray(enum_length);
|
||||
- for (InternalIndex i : map->IterateOwnDescriptors()) {
|
||||
- DisallowGarbageCollection no_gc;
|
||||
- PropertyDetails details = descriptors->GetDetails(i);
|
||||
- if (details.IsDontEnum()) continue;
|
||||
- Object key = descriptors->GetKey(i);
|
||||
- if (key.IsSymbol()) continue;
|
||||
- keys->set(index, key);
|
||||
- if (details.location() != PropertyLocation::kField) fields_only = false;
|
||||
- index++;
|
||||
- }
|
||||
- DCHECK_EQ(index, keys->length());
|
||||
-
|
||||
- // Optionally also create the indices array.
|
||||
- Handle<FixedArray> indices = isolate->factory()->empty_fixed_array();
|
||||
- if (fields_only) {
|
||||
- indices = isolate->factory()->NewFixedArray(enum_length);
|
||||
- index = 0;
|
||||
- for (InternalIndex i : map->IterateOwnDescriptors()) {
|
||||
- DisallowGarbageCollection no_gc;
|
||||
- PropertyDetails details = descriptors->GetDetails(i);
|
||||
- if (details.IsDontEnum()) continue;
|
||||
- Object key = descriptors->GetKey(i);
|
||||
- if (key.IsSymbol()) continue;
|
||||
- DCHECK_EQ(PropertyKind::kData, details.kind());
|
||||
- DCHECK_EQ(PropertyLocation::kField, details.location());
|
||||
- FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
|
||||
- indices->set(index, Smi::FromInt(field_index.GetLoadByFieldIndex()));
|
||||
- index++;
|
||||
- }
|
||||
- DCHECK_EQ(index, indices->length());
|
||||
- }
|
||||
-
|
||||
- DescriptorArray::InitializeOrChangeEnumCache(descriptors, isolate, keys,
|
||||
- indices);
|
||||
- if (map->OnlyHasSimpleProperties()) map->SetEnumLength(enum_length);
|
||||
-
|
||||
- return keys;
|
||||
+ return FastKeyAccumulator::InitializeFastPropertyEnumCache(isolate, map,
|
||||
+ enum_length);
|
||||
}
|
||||
|
||||
template <bool fast_properties>
|
||||
@@ -451,7 +408,6 @@ MaybeHandle<FixedArray> GetOwnKeysWithElements(Isolate* isolate,
|
||||
GetKeysConversion convert,
|
||||
bool skip_indices) {
|
||||
Handle<FixedArray> keys;
|
||||
- ElementsAccessor* accessor = object->GetElementsAccessor();
|
||||
if (fast_properties) {
|
||||
keys = GetFastEnumPropertyKeys(isolate, object);
|
||||
} else {
|
||||
@@ -463,6 +419,7 @@ MaybeHandle<FixedArray> GetOwnKeysWithElements(Isolate* isolate,
|
||||
if (skip_indices) {
|
||||
result = keys;
|
||||
} else {
|
||||
+ ElementsAccessor* accessor = object->GetElementsAccessor(isolate);
|
||||
result = accessor->PrependElementIndices(isolate, object, keys, convert,
|
||||
ONLY_ENUMERABLE);
|
||||
}
|
||||
@@ -518,7 +475,7 @@ MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysFast(
|
||||
if (enum_length == kInvalidEnumCacheSentinel) {
|
||||
Handle<FixedArray> keys;
|
||||
// Try initializing the enum cache and return own properties.
|
||||
- if (GetOwnKeysWithUninitializedEnumCache().ToHandle(&keys)) {
|
||||
+ if (GetOwnKeysWithUninitializedEnumLength().ToHandle(&keys)) {
|
||||
if (v8_flags.trace_for_in_enumerate) {
|
||||
PrintF("| strings=%d symbols=0 elements=0 || prototypes>=1 ||\n",
|
||||
keys->length());
|
||||
@@ -534,10 +491,70 @@ MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysFast(
|
||||
skip_indices_);
|
||||
}
|
||||
|
||||
+// static
|
||||
+Handle<FixedArray> FastKeyAccumulator::InitializeFastPropertyEnumCache(
|
||||
+ Isolate* isolate, Handle<Map> map, int enum_length,
|
||||
+ AllocationType allocation) {
|
||||
+ DCHECK_EQ(kInvalidEnumCacheSentinel, map->EnumLength());
|
||||
+ DCHECK_GT(enum_length, 0);
|
||||
+ DCHECK_EQ(enum_length, map->NumberOfEnumerableProperties());
|
||||
+ DCHECK(!map->is_dictionary_map());
|
||||
+
|
||||
+ Handle<DescriptorArray> descriptors =
|
||||
+ Handle<DescriptorArray>(map->instance_descriptors(isolate), isolate);
|
||||
+
|
||||
+ // The enum cache should have been a hit if the number of enumerable
|
||||
+ // properties is fewer than what's already in the cache.
|
||||
+ DCHECK_LT(descriptors->enum_cache().keys().length(), enum_length);
|
||||
+ isolate->counters()->enum_cache_misses()->Increment();
|
||||
+
|
||||
+ // Create the keys array.
|
||||
+ int index = 0;
|
||||
+ bool fields_only = true;
|
||||
+ Handle<FixedArray> keys =
|
||||
+ isolate->factory()->NewFixedArray(enum_length, allocation);
|
||||
+ for (InternalIndex i : map->IterateOwnDescriptors()) {
|
||||
+ DisallowGarbageCollection no_gc;
|
||||
+ PropertyDetails details = descriptors->GetDetails(i);
|
||||
+ if (details.IsDontEnum()) continue;
|
||||
+ Object key = descriptors->GetKey(i);
|
||||
+ if (key.IsSymbol()) continue;
|
||||
+ keys->set(index, key);
|
||||
+ if (details.location() != PropertyLocation::kField) fields_only = false;
|
||||
+ index++;
|
||||
+ }
|
||||
+ DCHECK_EQ(index, keys->length());
|
||||
+
|
||||
+ // Optionally also create the indices array.
|
||||
+ Handle<FixedArray> indices = isolate->factory()->empty_fixed_array();
|
||||
+ if (fields_only) {
|
||||
+ indices = isolate->factory()->NewFixedArray(enum_length, allocation);
|
||||
+ index = 0;
|
||||
+ for (InternalIndex i : map->IterateOwnDescriptors()) {
|
||||
+ DisallowGarbageCollection no_gc;
|
||||
+ PropertyDetails details = descriptors->GetDetails(i);
|
||||
+ if (details.IsDontEnum()) continue;
|
||||
+ Object key = descriptors->GetKey(i);
|
||||
+ if (key.IsSymbol()) continue;
|
||||
+ DCHECK_EQ(PropertyKind::kData, details.kind());
|
||||
+ DCHECK_EQ(PropertyLocation::kField, details.location());
|
||||
+ FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
|
||||
+ indices->set(index, Smi::FromInt(field_index.GetLoadByFieldIndex()));
|
||||
+ index++;
|
||||
+ }
|
||||
+ DCHECK_EQ(index, indices->length());
|
||||
+ }
|
||||
+
|
||||
+ DescriptorArray::InitializeOrChangeEnumCache(descriptors, isolate, keys,
|
||||
+ indices, allocation);
|
||||
+ if (map->OnlyHasSimpleProperties()) map->SetEnumLength(enum_length);
|
||||
+ return keys;
|
||||
+}
|
||||
+
|
||||
MaybeHandle<FixedArray>
|
||||
-FastKeyAccumulator::GetOwnKeysWithUninitializedEnumCache() {
|
||||
+FastKeyAccumulator::GetOwnKeysWithUninitializedEnumLength() {
|
||||
Handle<JSObject> object = Handle<JSObject>::cast(receiver_);
|
||||
- // Uninitalized enum cache
|
||||
+ // Uninitialized enum length
|
||||
Map map = object->map();
|
||||
if (object->elements() != ReadOnlyRoots(isolate_).empty_fixed_array() &&
|
||||
object->elements() !=
|
||||
diff --git a/src/objects/keys.h b/src/objects/keys.h
|
||||
index 4497f1211a42fc6dafc906ea9076f7c44995ac4a..031c407620b6af91ef4eb4453f1415c2a608211b 100644
|
||||
--- a/src/objects/keys.h
|
||||
+++ b/src/objects/keys.h
|
||||
@@ -174,7 +174,7 @@ class KeyAccumulator final {
|
||||
};
|
||||
|
||||
// The FastKeyAccumulator handles the cases where there are no elements on the
|
||||
-// prototype chain and forwords the complex/slow cases to the normal
|
||||
+// prototype chain and forwards the complex/slow cases to the normal
|
||||
// KeyAccumulator. This significantly speeds up the cases where the OWN_ONLY
|
||||
// case where we do not have to walk the prototype chain.
|
||||
class FastKeyAccumulator {
|
||||
@@ -200,6 +200,19 @@ class FastKeyAccumulator {
|
||||
MaybeHandle<FixedArray> GetKeys(
|
||||
GetKeysConversion convert = GetKeysConversion::kKeepNumbers);
|
||||
|
||||
+ // Initialize the the enum cache for a map with all of the following:
|
||||
+ // - uninitialized enum length
|
||||
+ // - fast properties (i.e. !is_dictionary_map())
|
||||
+ // - has >0 enumerable own properties
|
||||
+ //
|
||||
+ // The number of enumerable properties is passed in as an optimization, for
|
||||
+ // when the caller has already computed it.
|
||||
+ //
|
||||
+ // Returns the keys.
|
||||
+ static Handle<FixedArray> InitializeFastPropertyEnumCache(
|
||||
+ Isolate* isolate, Handle<Map> map, int enum_length,
|
||||
+ AllocationType allocation = AllocationType::kOld);
|
||||
+
|
||||
private:
|
||||
void Prepare();
|
||||
MaybeHandle<FixedArray> GetKeysFast(GetKeysConversion convert);
|
||||
@@ -207,7 +220,7 @@ class FastKeyAccumulator {
|
||||
MaybeHandle<FixedArray> GetKeysWithPrototypeInfoCache(
|
||||
GetKeysConversion convert);
|
||||
|
||||
- MaybeHandle<FixedArray> GetOwnKeysWithUninitializedEnumCache();
|
||||
+ MaybeHandle<FixedArray> GetOwnKeysWithUninitializedEnumLength();
|
||||
|
||||
bool MayHaveElements(JSReceiver receiver);
|
||||
bool TryPrototypeInfoCache(Handle<JSReceiver> receiver);
|
||||
diff --git a/src/objects/objects.cc b/src/objects/objects.cc
|
||||
index a7e1833f730e6e5869cd4925cca6dc908859000c..4a90a9ba970bffc78e38cad6e9e7e9053466a138 100644
|
||||
--- a/src/objects/objects.cc
|
||||
+++ b/src/objects/objects.cc
|
||||
@@ -4448,10 +4448,12 @@ void DescriptorArray::Replace(InternalIndex index, Descriptor* descriptor) {
|
||||
// static
|
||||
void DescriptorArray::InitializeOrChangeEnumCache(
|
||||
Handle<DescriptorArray> descriptors, Isolate* isolate,
|
||||
- Handle<FixedArray> keys, Handle<FixedArray> indices) {
|
||||
+ Handle<FixedArray> keys, Handle<FixedArray> indices,
|
||||
+ AllocationType allocation_if_initialize) {
|
||||
EnumCache enum_cache = descriptors->enum_cache();
|
||||
if (enum_cache == ReadOnlyRoots(isolate).empty_enum_cache()) {
|
||||
- enum_cache = *isolate->factory()->NewEnumCache(keys, indices);
|
||||
+ enum_cache = *isolate->factory()->NewEnumCache(keys, indices,
|
||||
+ allocation_if_initialize);
|
||||
descriptors->set_enum_cache(enum_cache);
|
||||
} else {
|
||||
enum_cache.set_keys(*keys);
|
||||
diff --git a/test/mjsunit/shared-memory/shared-struct-surface.js b/test/mjsunit/shared-memory/shared-struct-surface.js
|
||||
index 55a08ccec2a56ee9c0df5fa9a778fe22d6e7e1fb..301a8a114df16262d3ce1e228f951eb911593116 100644
|
||||
--- a/test/mjsunit/shared-memory/shared-struct-surface.js
|
||||
+++ b/test/mjsunit/shared-memory/shared-struct-surface.js
|
||||
@@ -76,3 +76,15 @@ let S = new SharedStructType(['field']);
|
||||
assertEquals(1, entries.length);
|
||||
assertArrayEquals(['field', 42], entries[0]);
|
||||
})();
|
||||
+
|
||||
+(function TestForIn() {
|
||||
+ let fieldNames = [];
|
||||
+ for (let i = 0; i < 512; i++) {
|
||||
+ fieldNames.push('field' + i);
|
||||
+ }
|
||||
+ let S2 = new SharedStructType(fieldNames);
|
||||
+ let s = new S2();
|
||||
+ let propNames = [];
|
||||
+ for (let prop in s) propNames.push(prop);
|
||||
+ assertArrayEquals(propNames, fieldNames);
|
||||
+})();
|
||||
@@ -1,6 +1,6 @@
|
||||
param([string]$gomaDir=$PWD)
|
||||
$cmdPath = Join-Path -Path $gomaDir -ChildPath "goma_ctl.py"
|
||||
Start-Process -FilePath cmd -ArgumentList "/C", "python", "$cmdPath", "ensure_start"
|
||||
$cmdPath = Join-Path -Path $gomaDir -ChildPath "goma_ctl.py"
|
||||
Start-Process -FilePath cmd -ArgumentList "/C", "python3", "$cmdPath", "ensure_start"
|
||||
$timedOut = $false; $waitTime = 0; $waitIncrement = 5; $timeout=120;
|
||||
Do { sleep $waitIncrement; $timedOut = (($waitTime+=$waitIncrement) -gt $timeout); iex "$gomaDir\gomacc.exe port 2" > $null; } Until(($LASTEXITCODE -eq 0) -or $timedOut)
|
||||
if ($timedOut) {
|
||||
|
||||
@@ -1641,13 +1641,6 @@ void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
|
||||
|
||||
void WebContents::PrimaryMainFrameRenderProcessGone(
|
||||
base::TerminationStatus status) {
|
||||
auto weak_this = GetWeakPtr();
|
||||
Emit("crashed", status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
|
||||
|
||||
// User might destroy WebContents in the crashed event.
|
||||
if (!weak_this || !web_contents())
|
||||
return;
|
||||
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
gin_helper::Dictionary details = gin_helper::Dictionary::CreateEmpty(isolate);
|
||||
|
||||
@@ -150,7 +150,13 @@ void ClientFrameViewLinux::Init(NativeWindowViews* window,
|
||||
}
|
||||
|
||||
gfx::Insets ClientFrameViewLinux::GetBorderDecorationInsets() const {
|
||||
return frame_provider_->GetFrameThicknessDip();
|
||||
const auto insets = frame_provider_->GetFrameThicknessDip();
|
||||
// We shouldn't draw frame decorations for the tiled edges.
|
||||
// See https://wayland.app/protocols/xdg-shell#xdg_toplevel:enum:state
|
||||
return gfx::Insets::TLBR(tiled_edges().top ? 0 : insets.top(),
|
||||
tiled_edges().left ? 0 : insets.left(),
|
||||
tiled_edges().bottom ? 0 : insets.bottom(),
|
||||
tiled_edges().right ? 0 : insets.right());
|
||||
}
|
||||
|
||||
gfx::Insets ClientFrameViewLinux::GetInputInsets() const {
|
||||
|
||||
@@ -521,6 +521,13 @@ node::Environment* NodeBindings::CreateEnvironment(
|
||||
electron::fuses::IsOnlyLoadAppFromAsarEnabled()
|
||||
? app_asar_search_paths
|
||||
: search_paths));
|
||||
context->Global()->SetPrivate(
|
||||
context,
|
||||
v8::Private::ForApi(
|
||||
isolate, gin::ConvertToV8(isolate, "appSearchPathsOnlyLoadASAR")
|
||||
.As<v8::String>()),
|
||||
gin::ConvertToV8(isolate,
|
||||
electron::fuses::IsOnlyLoadAppFromAsarEnabled()));
|
||||
}
|
||||
|
||||
base::FilePath resources_path = GetResourcesPath();
|
||||
|
||||
1
typings/internal-ambient.d.ts
vendored
1
typings/internal-ambient.d.ts
vendored
@@ -252,6 +252,7 @@ declare namespace NodeJS {
|
||||
// Additional properties
|
||||
_firstFileName?: string;
|
||||
_serviceStartupScript: string;
|
||||
_getOrCreateArchive?: (path: string) => NodeJS.AsarArchive | null;
|
||||
|
||||
helperExecPath: string;
|
||||
mainModule?: NodeJS.Module | undefined;
|
||||
|
||||
Reference in New Issue
Block a user