Merge pull request #140 from chialab/secure-old-php-versions

build EOL PHP versions from source
This commit is contained in:
le0m
2026-10-23 15:27:33 +02:00
committed by GitHub
99 changed files with 18449 additions and 789 deletions
+94
View File
@@ -0,0 +1,94 @@
name: Build image
description: >
Builds one image for the runner's architecture and tests it. The image is pushed either to the
job's local registry, or by digest to ghcr, recording the digest for the publish workflow.
inputs:
image:
description: Image name without registry, e.g. php-dev.
required: true
tag:
description: Image tag, e.g. 7.4-apache.
required: true
arch:
description: Runner architecture (amd64 or arm64).
required: true
context:
description: Build context.
required: true
file:
description: Dockerfile path, relative to the repository root.
default: ''
build-args:
description: Build arguments.
default: ''
build-contexts:
description: Additional named build contexts.
default: ''
push:
description: Where to push the image, "local" or "ghcr".
default: local
cache-write:
description: Export the build cache to ghcr.
default: 'false'
no-cache:
description: Ignore the build cache.
default: 'false'
test:
description: Make directory whose "test" target checks the image; empty to skip testing.
default: ''
outputs:
ref:
description: Reference to the built image, usable as BASE_IMAGE.
value: ${{ steps.ref.outputs.ref }}
runs:
using: composite
steps:
- name: Build ${{ inputs.image }}
id: build
uses: docker/build-push-action@v5
with:
context: ${{ inputs.context }}
file: ${{ inputs.file }}
build-args: ${{ inputs.build-args }}
build-contexts: ${{ inputs.build-contexts }}
no-cache: ${{ inputs.no-cache == 'true' }}
cache-from: type=registry,ref=ghcr.io/chialab/${{ inputs.image }}:cache-${{ inputs.tag }}-${{ inputs.arch }}
cache-to: ${{ inputs.cache-write == 'true' && format('type=registry,mode=max,image-manifest=true,oci-mediatypes=true,ignore-error=true,ref=ghcr.io/chialab/{0}:cache-{1}-{2}', inputs.image, inputs.tag, inputs.arch) || '' }}
tags: ${{ inputs.push == 'local' && format('localhost:5000/chialab/{0}:{1}', inputs.image, inputs.tag) || '' }}
push: ${{ inputs.push == 'local' }}
outputs: ${{ inputs.push == 'ghcr' && format('type=image,name=ghcr.io/chialab/{0},push-by-digest=true,name-canonical=true,push=true', inputs.image) || '' }}
- name: Resolve ${{ inputs.image }} reference
id: ref
shell: bash
env:
IMAGE: ${{ inputs.image }}
TAG: ${{ inputs.tag }}
DIGEST: ${{ steps.build.outputs.digest }}
PUSH: ${{ inputs.push }}
run: |
if [[ "$PUSH" == 'ghcr' ]]; then
echo "ref=ghcr.io/chialab/$IMAGE@$DIGEST" >> "$GITHUB_OUTPUT"
mkdir -p "$RUNNER_TEMP/digests/$IMAGE"
touch "$RUNNER_TEMP/digests/$IMAGE/${DIGEST#sha256:}"
else
echo "ref=localhost:5000/chialab/$IMAGE:$TAG" >> "$GITHUB_OUTPUT"
fi
- name: Test ${{ inputs.image }}
if: ${{ inputs.test != '' }}
shell: bash
env:
REGISTRY: localhost:5000/
VERSION: ${{ inputs.tag }}
IMAGE: ${{ inputs.image }}
REF: ${{ steps.ref.outputs.ref }}
MAKE_DIR: ${{ inputs.test }}
run: |
docker pull "$REF"
# the Makefile looks the image up by tag
docker tag "$REF" "localhost:5000/chialab/$IMAGE:$VERSION"
make -C "$MAKE_DIR" test
+3 -1
View File
@@ -6,6 +6,8 @@ updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
directories:
- "/"
- "/.github/actions/build-image"
schedule:
interval: "daily"
+195
View File
@@ -0,0 +1,195 @@
name: Build and test images
# Builds and tests each version × flavor natively on amd64 and arm64. Pull requests push to a local
# registry; runs on main push by digest to ghcr and upload the digests for publish-images.yml.
on:
workflow_call:
inputs:
versions:
description: JSON list of PHP versions.
type: string
required: true
flavors:
description: JSON list of flavors.
type: string
default: '[""]'
exclude:
description: JSON list of version/flavor combinations to skip.
type: string
default: '[]'
secrets:
pull-username:
required: true
pull-password:
required: true
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
name: ${{ matrix.version }}${{ matrix.flavor }} (${{ matrix.arch }})
runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }}
strategy:
fail-fast: false
matrix:
version: ${{ fromJSON(inputs.versions) }}
flavor: ${{ fromJSON(inputs.flavors) }}
arch: [ 'amd64', 'arm64' ]
exclude: ${{ fromJSON(inputs.exclude) }}
services:
registry:
image: ${{ github.event_name == 'pull_request' && 'registry:2' || '' }}
ports:
- 5000:5000
env:
PUSH: ${{ github.event_name == 'pull_request' && 'local' || 'ghcr' }}
CACHE_WRITE: ${{ github.event_name != 'pull_request' }}
# Scheduled runs rebuild the extension layers, so they pick up new extension and OS package
# versions; the patched PHP base is only rebuilt when its inputs change.
NO_CACHE: ${{ github.event_name == 'schedule' }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Plan
id: plan
env:
VERSION: ${{ matrix.version }}
FLAVOR: ${{ matrix.flavor }}
ARCH: ${{ matrix.arch }}
run: |
tag="$VERSION$FLAVOR"
flavorDir="${FLAVOR#-}"
eolDir="eol/$VERSION/${flavorDir:-cli}"
[[ -d "$eolDir" ]] && eol=true || eol=false
[[ "$tag" == *alpine* ]] && dockerfile=Dockerfile.alpine || dockerfile=Dockerfile
[[ "$VERSION" == '5.6' && "$ARCH" == 'arm64' ]] && dev=false || dev=true
[[ "$VERSION" == '5.6' || "$VERSION" == '7.0' ]] && pcov=false || pcov=true
[[ "$ARCH" == 'amd64' ]] && xhprof=true || xhprof=false
[[ "$VERSION" == 8.* || "$VERSION" == 'latest' || "$VERSION" == 'alpine' ]] && otel=true || otel=false
{
echo "tag=$tag"
echo "eol=$eol"
echo "eol-dir=$eolDir"
echo "dockerfile=$dockerfile"
echo "dev=$dev"
echo "pcov=$pcov"
echo "xhprof=$xhprof"
echo "otel=$otel"
} >> "$GITHUB_OUTPUT"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver-opts: network=host
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.pull-username }}
password: ${{ secrets.pull-password }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build patched PHP base image
id: base
if: ${{ steps.plan.outputs.eol == 'true' }}
uses: ./.github/actions/build-image
with:
image: php-base
tag: ${{ steps.plan.outputs.tag }}
arch: ${{ matrix.arch }}
context: ${{ steps.plan.outputs.eol-dir }}
build-contexts: |
patches=eol/patches
scripts=eol/scripts
push: ${{ env.PUSH }}
cache-write: ${{ env.CACHE_WRITE }}
- name: Build PHP image
id: php
uses: ./.github/actions/build-image
with:
image: php
tag: ${{ steps.plan.outputs.tag }}
arch: ${{ matrix.arch }}
context: .
file: ${{ steps.plan.outputs.dockerfile }}
build-args: BASE_IMAGE=${{ steps.plan.outputs.eol == 'true' && steps.base.outputs.ref || format('php:{0}', steps.plan.outputs.tag) }}
push: ${{ env.PUSH }}
cache-write: ${{ env.CACHE_WRITE }}
no-cache: ${{ env.NO_CACHE }}
test: .
- name: Build dev image
if: ${{ steps.plan.outputs.dev == 'true' }}
uses: ./.github/actions/build-image
with:
image: php-dev
tag: ${{ steps.plan.outputs.tag }}
arch: ${{ matrix.arch }}
context: ./dev
build-args: BASE_IMAGE=${{ steps.php.outputs.ref }}
push: ${{ env.PUSH }}
cache-write: ${{ env.CACHE_WRITE }}
no-cache: ${{ env.NO_CACHE }}
test: dev
- name: Build PCOV image
if: ${{ steps.plan.outputs.pcov == 'true' }}
uses: ./.github/actions/build-image
with:
image: php-pcov
tag: ${{ steps.plan.outputs.tag }}
arch: ${{ matrix.arch }}
context: ./pcov
build-args: BASE_IMAGE=${{ steps.php.outputs.ref }}
push: ${{ env.PUSH }}
cache-write: ${{ env.CACHE_WRITE }}
no-cache: ${{ env.NO_CACHE }}
test: pcov
- name: Build xhprof image
if: ${{ steps.plan.outputs.xhprof == 'true' }}
uses: ./.github/actions/build-image
with:
image: php-xhprof
tag: ${{ steps.plan.outputs.tag }}
arch: ${{ matrix.arch }}
context: ./xhprof
build-args: BASE_IMAGE=${{ steps.php.outputs.ref }}
push: ${{ env.PUSH }}
cache-write: ${{ env.CACHE_WRITE }}
no-cache: ${{ env.NO_CACHE }}
test: xhprof
- name: Build OTel image
if: ${{ steps.plan.outputs.otel == 'true' }}
uses: ./.github/actions/build-image
with:
image: php-otel
tag: ${{ steps.plan.outputs.tag }}
arch: ${{ matrix.arch }}
context: ./otel
build-args: BASE_IMAGE=${{ steps.php.outputs.ref }}
push: ${{ env.PUSH }}
cache-write: ${{ env.CACHE_WRITE }}
no-cache: ${{ env.NO_CACHE }}
test: otel
- name: Upload digests
if: ${{ env.PUSH == 'ghcr' }}
uses: actions/upload-artifact@v4
with:
name: digests-${{ steps.plan.outputs.tag }}-${{ matrix.arch }}
path: ${{ runner.temp }}/digests/
if-no-files-found: error
retention-days: 7
+92
View File
@@ -0,0 +1,92 @@
name: Publish images
# Publishes the images built and tested by the triggering build-images.yml run: merges each
# image's per-arch digests into a multi-arch tag on ghcr, then copies it to Docker Hub. Nothing is
# rebuilt, and nothing is read from Docker Hub, so publishing doesn't count against its pull limits.
# Callers must skip runs whose commit is no longer the head of main (github.sha), so an older
# commit whose tests finished late can't overwrite the tags of a newer one.
on:
workflow_call:
inputs:
versions:
description: JSON list of PHP versions.
type: string
required: true
flavors:
description: JSON list of flavors.
type: string
default: '[""]'
exclude:
description: JSON list of version/flavor combinations to skip.
type: string
default: '[]'
secrets:
push-username:
required: true
push-password:
required: true
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
publish:
name: ${{ matrix.version }}${{ matrix.flavor }}
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
version: ${{ fromJSON(inputs.versions) }}
flavor: ${{ fromJSON(inputs.flavors) }}
exclude: ${{ fromJSON(inputs.exclude) }}
steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
pattern: digests-${{ matrix.version }}${{ matrix.flavor }}-{amd64,arm64}
path: ${{ runner.temp }}/digests
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create multi-arch tags
env:
TAG: ${{ matrix.version }}${{ matrix.flavor }}
GHCR_USERNAME: ${{ github.repository_owner }}
GHCR_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
DOCKERHUB_USERNAME: ${{ secrets.push-username }}
DOCKERHUB_PASSWORD: ${{ secrets.push-password }}
run: |
shopt -s nullglob
cd "$RUNNER_TEMP/digests"
for arch in amd64 arm64; do
if [[ ! -d "digests-$TAG-$arch" ]]; then
echo "Missing the $arch build of $TAG" >&2
exit 1
fi
done
for image in $(find . -mindepth 2 -maxdepth 2 -type d -printf '%f\n' | sort -u); do
sources=()
for digest in digests-*/"$image"/*; do
sources+=("ghcr.io/chialab/$image@sha256:$(basename "$digest")")
done
docker buildx imagetools create -t "ghcr.io/chialab/$image:$TAG" "${sources[@]}"
# The patched base image is internal and stays on ghcr.
if [[ "$image" != 'php-base' ]]; then
skopeo copy --all --preserve-digests \
--src-creds "$GHCR_USERNAME:$GHCR_PASSWORD" \
--dest-creds "$DOCKERHUB_USERNAME:$DOCKERHUB_PASSWORD" \
"docker://ghcr.io/chialab/$image:$TAG" "docker://docker.io/chialab/$image:$TAG"
fi
done
+13 -87
View File
@@ -8,90 +8,16 @@ on:
jobs:
publish-5:
name: Build and publish PHP 5 images
runs-on: ubuntu-22.04
if: ${{ github.event_name != 'pull_request' && !contains(github.event.commits[0].message, '[skip ci]') && !contains(github.event.commits[0].message, '[ci skip]') }}
strategy:
fail-fast: false
matrix:
version: [ '5.6' ]
flavor: [ '', '-apache', '-fpm', '-alpine', '-fpm-alpine' ]
exclude:
- version: '5.6'
flavor: '-alpine'
- version: '5.6'
flavor: '-fpm-alpine'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver-opts: network=host
- name: Login to DockerHub (pull)
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_PULL_USER_1 }}
password: ${{ secrets.DOCKER_PULL_PASS_1 }}
- name: Pull base image
run: docker pull chialab/php:${{ matrix.version }}${{ matrix.flavor }}
- name: Login to DockerHub (push)
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build image and push to registry
uses: docker/build-push-action@v5
with:
platforms: linux/amd64,linux/arm64
# cache-from: type=registry,ref=ghcr.io/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
cache-to: type=inline
context: .
file: ${{ ((contains(matrix.flavor, 'alpine') || matrix.version == 'alpine') && 'Dockerfile.alpine') || 'Dockerfile' }}
build-args: |
BASE_IMAGE=php:${{ matrix.version }}${{ matrix.flavor }}
tags: |
chialab/php:${{ matrix.version }}${{ matrix.flavor }}
ghcr.io/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
push: true
- name: Build dev image and push to registry
uses: docker/build-push-action@v5
with:
platforms: linux/amd64
cache-to: type=inline
context: ./dev
build-args: |
BASE_IMAGE=ghcr.io/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
tags: |
chialab/php-dev:${{ matrix.version }}${{ matrix.flavor }}
ghcr.io/chialab/php-dev:${{ matrix.version }}${{ matrix.flavor }}
push: true
- name: Build xhprof image and push to registry
uses: docker/build-push-action@v5
with:
platforms: linux/amd64
cache-to: type=inline
context: ./xhprof
build-args: |
BASE_IMAGE=ghcr.io/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
tags: |
chialab/php-xhprof:${{ matrix.version }}${{ matrix.flavor }}
ghcr.io/chialab/php-xhprof:${{ matrix.version }}${{ matrix.flavor }}
push: true
name: Publish PHP 5 images
if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event != 'pull_request' && github.event.workflow_run.head_sha == github.sha }}
permissions:
actions: read
contents: read
packages: write
uses: ./.github/workflows/publish-images.yml
with:
versions: '["5.6"]'
flavors: '["", "-apache", "-fpm"]'
secrets:
push-username: ${{ secrets.DOCKER_USERNAME }}
push-password: ${{ secrets.DOCKER_PASSWORD }}
+14 -100
View File
@@ -8,103 +8,17 @@ on:
jobs:
publish-7:
name: Build and publish PHP 7 images
runs-on: ubuntu-22.04
if: ${{ github.event.workflow_run.conclusion == 'success' && !contains(github.event.commits[0].message, '[skip ci]') && !contains(github.event.commits[0].message, '[ci skip]') }}
strategy:
fail-fast: false
matrix:
version: [ '7.0', '7.1', '7.2', '7.3', '7.4' ]
flavor: [ '', '-apache', '-fpm', '-alpine', '-fpm-alpine' ]
exclude:
- version: '7.0'
flavor: '-alpine'
- version: '7.0'
flavor: '-fpm-alpine'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver-opts: network=host
- name: Login to DockerHub (pull)
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_PULL_USER_2 }}
password: ${{ secrets.DOCKER_PULL_PASS_2 }}
- name: Pull base image
run: docker pull chialab/php:${{ matrix.version }}${{ matrix.flavor }}
- name: Login to DockerHub (push)
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build image and push to registry
uses: docker/build-push-action@v5
with:
platforms: linux/amd64,linux/arm64
# cache-from: type=registry,ref=ghcr.io/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
cache-to: type=inline
context: .
file: ${{ ((contains(matrix.flavor, 'alpine') || matrix.version == 'alpine') && 'Dockerfile.alpine') || 'Dockerfile' }}
build-args: |
BASE_IMAGE=php:${{ matrix.version }}${{ matrix.flavor }}
tags: |
chialab/php:${{ matrix.version }}${{ matrix.flavor }}
ghcr.io/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
push: true
- name: Build dev image and push to registry
uses: docker/build-push-action@v5
with:
platforms: linux/amd64,linux/arm64
cache-to: type=inline
context: ./dev
build-args: |
BASE_IMAGE=ghcr.io/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
tags: |
chialab/php-dev:${{ matrix.version }}${{ matrix.flavor }}
ghcr.io/chialab/php-dev:${{ matrix.version }}${{ matrix.flavor }}
push: true
- name: Build PCOV image and push to registry
if: ${{ matrix.version >= 7.1 }}
uses: docker/build-push-action@v5
with:
platforms: linux/amd64,linux/arm64
cache-to: type=inline
context: ./pcov
build-args: |
BASE_IMAGE=ghcr.io/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
tags: |
chialab/php-pcov:${{ matrix.version }}${{ matrix.flavor }}
ghcr.io/chialab/php-pcov:${{ matrix.version }}${{ matrix.flavor }}
push: true
- name: Build xhprof image (amd64 only) and push to registry
uses: docker/build-push-action@v5
with:
cache-to: type=inline
context: ./xhprof
build-args: |
BASE_IMAGE=ghcr.io/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
tags: |
chialab/php-xhprof:${{ matrix.version }}${{ matrix.flavor }}
ghcr.io/chialab/php-xhprof:${{ matrix.version }}${{ matrix.flavor }}
push: true
name: Publish PHP 7 images
if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event != 'pull_request' && github.event.workflow_run.head_sha == github.sha }}
permissions:
actions: read
contents: read
packages: write
uses: ./.github/workflows/publish-images.yml
with:
versions: '["7.0", "7.1", "7.2", "7.3", "7.4"]'
flavors: '["", "-apache", "-fpm", "-alpine", "-fpm-alpine"]'
exclude: '[{"version": "7.0", "flavor": "-alpine"}, {"version": "7.0", "flavor": "-fpm-alpine"}]'
secrets:
push-username: ${{ secrets.DOCKER_USERNAME }}
push-password: ${{ secrets.DOCKER_PASSWORD }}
+13 -107
View File
@@ -8,110 +8,16 @@ on:
jobs:
publish-8:
name: Build and publish PHP 8 images
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' && !contains(github.event.commits[0].message, '[skip ci]') && !contains(github.event.commits[0].message, '[ci skip]') }}
strategy:
fail-fast: false
matrix:
version: [ '8.0', '8.1', '8.2', '8.3', '8.4', '8.5' ]
flavor: [ '', '-apache', '-fpm', '-alpine', '-fpm-alpine' ]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver-opts: network=host
- name: Login to DockerHub (pull)
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_PULL_USER_3 }}
password: ${{ secrets.DOCKER_PULL_PASS_3 }}
- name: Pull base image
run: docker pull chialab/php:${{ matrix.version }}${{ matrix.flavor }}
- name: Login to DockerHub (push)
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build image and push to registry
uses: docker/build-push-action@v5
with:
platforms: linux/amd64,linux/arm64
# cache-from: type=registry,ref=ghcr.io/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
cache-to: type=inline
context: .
file: ${{ ((contains(matrix.flavor, 'alpine') || matrix.version == 'alpine') && 'Dockerfile.alpine') || 'Dockerfile' }}
build-args: |
BASE_IMAGE=php:${{ matrix.version }}${{ matrix.flavor }}
tags: |
chialab/php:${{ matrix.version }}${{ matrix.flavor }}
ghcr.io/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
push: true
- name: Build dev image and push to registry
uses: docker/build-push-action@v5
with:
platforms: linux/amd64,linux/arm64
cache-to: type=inline
context: ./dev
build-args: |
BASE_IMAGE=ghcr.io/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
tags: |
chialab/php-dev:${{ matrix.version }}${{ matrix.flavor }}
ghcr.io/chialab/php-dev:${{ matrix.version }}${{ matrix.flavor }}
push: true
- name: Build PCOV image and push to registry
uses: docker/build-push-action@v5
with:
platforms: linux/amd64,linux/arm64
cache-to: type=inline
context: ./pcov
build-args: |
BASE_IMAGE=ghcr.io/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
tags: |
chialab/php-pcov:${{ matrix.version }}${{ matrix.flavor }}
ghcr.io/chialab/php-pcov:${{ matrix.version }}${{ matrix.flavor }}
push: true
- name: Build xhprof image (amd64 only) and push to registry
uses: docker/build-push-action@v5
with:
cache-to: type=inline
context: ./xhprof
build-args: |
BASE_IMAGE=ghcr.io/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
tags: |
chialab/php-xhprof:${{ matrix.version }}${{ matrix.flavor }}
ghcr.io/chialab/php-xhprof:${{ matrix.version }}${{ matrix.flavor }}
push: true
- name: Build OTel image and push to registry
uses: docker/build-push-action@v5
with:
platforms: linux/amd64,linux/arm64
cache-to: type=inline
context: ./otel
build-args: |
BASE_IMAGE=ghcr.io/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
tags: |
chialab/php-otel:${{ matrix.version }}${{ matrix.flavor }}
ghcr.io/chialab/php-otel:${{ matrix.version }}${{ matrix.flavor }}
push: true
name: Publish PHP 8 images
if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event != 'pull_request' && github.event.workflow_run.head_sha == github.sha }}
permissions:
actions: read
contents: read
packages: write
uses: ./.github/workflows/publish-images.yml
with:
versions: '["8.0", "8.1", "8.2", "8.3", "8.4", "8.5"]'
flavors: '["", "-apache", "-fpm", "-alpine", "-fpm-alpine"]'
secrets:
push-username: ${{ secrets.DOCKER_USERNAME }}
push-password: ${{ secrets.DOCKER_PASSWORD }}
+8 -1
View File
@@ -6,11 +6,17 @@ on:
branches: [main]
types: [completed]
# Every completed test run starts this workflow; runs that won't publish get their own group, so
# they can't cancel a publish in progress.
concurrency:
group: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event != 'pull_request' && github.event.workflow_run.head_sha == github.sha && github.workflow || github.run_id }}
cancel-in-progress: true
jobs:
publish-compat:
name: Build and publish compatibility images
runs-on: ubuntu-22.04
if: ${{ github.event.workflow_run.conclusion == 'success' && !contains(github.event.commits[0].message, '[skip ci]') && !contains(github.event.commits[0].message, '[ci skip]') }}
if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event != 'pull_request' && github.event.workflow_run.head_sha == github.sha }}
strategy:
fail-fast: false
matrix:
@@ -57,6 +63,7 @@ jobs:
# cache-from: type=registry,ref=ghcr.io/chialab/php-compat:${{ matrix.version }}${{ matrix.flavor }}
cache-to: type=inline
context: ./compat
build-contexts: patches=eol/patches
file: ${{ format('compat/{0}.{1}{2}', 'Dockerfile', matrix.version, matrix.flavor) }}
tags: |
chialab/php-compat:${{ matrix.version }}${{ matrix.flavor }}
+13 -107
View File
@@ -7,110 +7,16 @@ on:
types: [completed]
jobs:
publish-8:
name: Build and publish PHP 8 images
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' && !contains(github.event.commits[0].message, '[skip ci]') && !contains(github.event.commits[0].message, '[ci skip]') }}
strategy:
fail-fast: false
matrix:
version: [ 'latest', 'alpine' ]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver-opts: network=host
- name: Login to DockerHub (pull)
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_PULL_USER_5 }}
password: ${{ secrets.DOCKER_PULL_PASS_5 }}
- name: Pull base image
run: docker pull chialab/php:${{ matrix.version }}
- name: Login to DockerHub (push)
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build image and push to registry
uses: docker/build-push-action@v5
with:
platforms: linux/amd64,linux/arm64
# cache-from: type=registry,ref=ghcr.io/chialab/php:${{ matrix.version }}
cache-to: type=inline
context: .
file: ${{ ((contains(matrix.flavor, 'alpine') || matrix.version == 'alpine') && 'Dockerfile.alpine') || 'Dockerfile' }}
build-args: |
BASE_IMAGE=php:${{ matrix.version }}
tags: |
chialab/php:${{ matrix.version }}
ghcr.io/chialab/php:${{ matrix.version }}
push: true
- name: Build dev image and push to registry
uses: docker/build-push-action@v5
with:
platforms: linux/amd64,linux/arm64
cache-to: type=inline
context: ./dev
build-args: |
BASE_IMAGE=ghcr.io/chialab/php:${{ matrix.version }}
tags: |
chialab/php-dev:${{ matrix.version }}
ghcr.io/chialab/php-dev:${{ matrix.version }}
push: true
- name: Build PCOV image and push to registry
uses: docker/build-push-action@v5
with:
platforms: linux/amd64,linux/arm64
cache-to: type=inline
context: ./pcov
build-args: |
BASE_IMAGE=ghcr.io/chialab/php:${{ matrix.version }}
tags: |
chialab/php-pcov:${{ matrix.version }}
ghcr.io/chialab/php-pcov:${{ matrix.version }}
push: true
- name: Build xhprof image (amd64 only) and push to registry
uses: docker/build-push-action@v5
with:
cache-to: type=inline
context: ./xhprof
build-args: |
BASE_IMAGE=ghcr.io/chialab/php:${{ matrix.version }}
tags: |
chialab/php-xhprof:${{ matrix.version }}
ghcr.io/chialab/php-xhprof:${{ matrix.version }}
push: true
- name: Build OTel image and push to registry
uses: docker/build-push-action@v5
with:
platforms: linux/amd64,linux/arm64
cache-to: type=inline
context: ./otel
build-args: |
BASE_IMAGE=ghcr.io/chialab/php:${{ matrix.version }}
tags: |
chialab/php-otel:${{ matrix.version }}
ghcr.io/chialab/php-otel:${{ matrix.version }}
push: true
publish-latest:
name: Publish latest PHP images
if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event != 'pull_request' && github.event.workflow_run.head_sha == github.sha }}
permissions:
actions: read
contents: read
packages: write
uses: ./.github/workflows/publish-images.yml
with:
versions: '["latest", "alpine"]'
secrets:
push-username: ${{ secrets.DOCKER_USERNAME }}
push-password: ${{ secrets.DOCKER_PASSWORD }}
+10 -76
View File
@@ -12,79 +12,13 @@ on:
jobs:
test-5:
name: Build and test PHP 5 images
runs-on: ubuntu-22.04
if: ${{ !contains(github.event.commits[0].message, '[skip ci]') && !contains(github.event.commits[0].message, '[ci skip]') }}
strategy:
fail-fast: false
matrix:
version: [ '5.6' ]
flavor: [ '', '-apache', '-fpm', '-alpine', '-fpm-alpine' ]
exclude:
- version: '5.6'
flavor: '-alpine'
- version: '5.6'
flavor: '-fpm-alpine'
services:
registry:
image: registry:2
ports:
- 5000:5000
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_PULL_USER_1 }}
password: ${{ secrets.DOCKER_PULL_PASS_1 }}
- name: Build image for testing
uses: docker/build-push-action@v5
with:
# cache-from: type=registry,ref=ghcr.io/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
cache-to: type=inline
context: .
file: ${{ ((contains(matrix.flavor, 'alpine') || matrix.version == 'alpine') && 'Dockerfile.alpine') || 'Dockerfile' }}
build-args: |
BASE_IMAGE=php:${{ matrix.version }}${{ matrix.flavor }}
tags: localhost:5000/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
push: true
- name: Test image
env:
REGISTRY: localhost:5000/
VERSION: ${{ matrix.version }}${{ matrix.flavor }}
run: 'docker pull localhost:5000/chialab/php:${{ matrix.version }}${{ matrix.flavor }} && make test'
- name: Build dev image for testing
uses: docker/build-push-action@v5
with:
cache-to: type=inline
context: ./dev
build-args: |
BASE_IMAGE=localhost:5000/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
tags: localhost:5000/chialab/php-dev:${{ matrix.version }}${{ matrix.flavor }}
push: true
- name: Test dev image
env:
REGISTRY: localhost:5000/
VERSION: ${{ matrix.version }}${{ matrix.flavor }}
run: 'docker pull localhost:5000/chialab/php-dev:${{ matrix.version }}${{ matrix.flavor }} && make -C dev test'
- name: Build xhprof image for testing
uses: docker/build-push-action@v5
with:
cache-to: type=inline
context: ./xhprof
build-args: |
BASE_IMAGE=localhost:5000/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
tags: localhost:5000/chialab/php-xhprof:${{ matrix.version }}${{ matrix.flavor }}
push: true
- name: Test xhprof image
env:
REGISTRY: localhost:5000/
VERSION: ${{ matrix.version }}${{ matrix.flavor }}
run: 'docker pull localhost:5000/chialab/php-xhprof:${{ matrix.version }}${{ matrix.flavor }} && make -C xhprof test'
permissions:
contents: read
packages: write
uses: ./.github/workflows/build-images.yml
with:
versions: '["5.6"]'
flavors: '["", "-apache", "-fpm"]'
secrets:
pull-username: ${{ secrets.DOCKER_PULL_USER_1 }}
pull-password: ${{ secrets.DOCKER_PULL_PASS_1 }}
+11 -94
View File
@@ -12,97 +12,14 @@ on:
jobs:
test-7:
name: Build and test PHP 7 images
runs-on: ubuntu-22.04
if: ${{ !contains(github.event.commits[0].message, '[skip ci]') && !contains(github.event.commits[0].message, '[ci skip]') }}
strategy:
fail-fast: false
matrix:
version: [ '7.0', '7.1', '7.2', '7.3', '7.4' ]
flavor: [ '', '-apache', '-fpm', '-alpine', '-fpm-alpine' ]
exclude:
- version: '7.0'
flavor: '-alpine'
- version: '7.0'
flavor: '-fpm-alpine'
services:
registry:
image: registry:2
ports:
- 5000:5000
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_PULL_USER_2 }}
password: ${{ secrets.DOCKER_PULL_PASS_2 }}
- name: Build image for testing
uses: docker/build-push-action@v5
with:
# cache-from: type=registry,ref=ghcr.io/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
cache-to: type=inline
context: .
file: ${{ ((contains(matrix.flavor, 'alpine') || matrix.version == 'alpine') && 'Dockerfile.alpine') || 'Dockerfile' }}
build-args: |
BASE_IMAGE=php:${{ matrix.version }}${{ matrix.flavor }}
tags: localhost:5000/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
push: true
- name: Test image
env:
REGISTRY: localhost:5000/
VERSION: ${{ matrix.version }}${{ matrix.flavor }}
run: 'docker pull localhost:5000/chialab/php:${{ matrix.version }}${{ matrix.flavor }} && make test'
- name: Build dev image for testing
uses: docker/build-push-action@v5
with:
cache-to: type=inline
context: ./dev
build-args: |
BASE_IMAGE=localhost:5000/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
tags: localhost:5000/chialab/php-dev:${{ matrix.version }}${{ matrix.flavor }}
push: true
- name: Test dev image
env:
REGISTRY: localhost:5000/
VERSION: ${{ matrix.version }}${{ matrix.flavor }}
run: 'docker pull localhost:5000/chialab/php-dev:${{ matrix.version }}${{ matrix.flavor }} && make -C dev test'
- name: Build PCOV image for testing
if: ${{ matrix.version >= 7.1 }}
uses: docker/build-push-action@v5
with:
cache-to: type=inline
context: ./pcov
build-args: |
BASE_IMAGE=localhost:5000/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
tags: localhost:5000/chialab/php-pcov:${{ matrix.version }}${{ matrix.flavor }}
push: true
- name: Test PCOV image
if: ${{ matrix.version >= 7.1 }}
env:
REGISTRY: localhost:5000/
VERSION: ${{ matrix.version }}${{ matrix.flavor }}
run: 'docker pull localhost:5000/chialab/php-pcov:${{ matrix.version }}${{ matrix.flavor }} && make -C pcov test'
- name: Build xhprof image for testing
uses: docker/build-push-action@v5
with:
cache-to: type=inline
context: ./xhprof
build-args: |
BASE_IMAGE=localhost:5000/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
tags: localhost:5000/chialab/php-xhprof:${{ matrix.version }}${{ matrix.flavor }}
push: true
- name: Test xhprof image
env:
REGISTRY: localhost:5000/
VERSION: ${{ matrix.version }}${{ matrix.flavor }}
run: 'docker pull localhost:5000/chialab/php-xhprof:${{ matrix.version }}${{ matrix.flavor }} && make -C xhprof test'
permissions:
contents: read
packages: write
uses: ./.github/workflows/build-images.yml
with:
versions: '["7.0", "7.1", "7.2", "7.3", "7.4"]'
flavors: '["", "-apache", "-fpm", "-alpine", "-fpm-alpine"]'
exclude: '[{"version": "7.0", "flavor": "-alpine"}, {"version": "7.0", "flavor": "-fpm-alpine"}]'
secrets:
pull-username: ${{ secrets.DOCKER_PULL_USER_2 }}
pull-password: ${{ secrets.DOCKER_PULL_PASS_2 }}
+10 -103
View File
@@ -12,106 +12,13 @@ on:
jobs:
test-8:
name: Build and test PHP 8 images
runs-on: ubuntu-latest
if: ${{ !contains(github.event.commits[0].message, '[skip ci]') && !contains(github.event.commits[0].message, '[ci skip]') }}
strategy:
fail-fast: false
matrix:
version: [ '8.0', '8.1', '8.2', '8.3', '8.4', '8.5' ]
flavor: [ '', '-apache', '-fpm', '-alpine', '-fpm-alpine' ]
services:
registry:
image: registry:2
ports:
- 5000:5000
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_PULL_USER_3 }}
password: ${{ secrets.DOCKER_PULL_PASS_3 }}
- name: Build image for testing
uses: docker/build-push-action@v5
with:
# cache-from: type=registry,ref=ghcr.io/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
cache-to: type=inline
context: .
file: ${{ ((contains(matrix.flavor, 'alpine') || matrix.version == 'alpine') && 'Dockerfile.alpine') || 'Dockerfile' }}
build-args: |
BASE_IMAGE=php:${{ matrix.version }}${{ matrix.flavor }}
tags: localhost:5000/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
push: true
- name: Test image
env:
REGISTRY: localhost:5000/
VERSION: ${{ matrix.version }}${{ matrix.flavor }}
run: 'docker pull localhost:5000/chialab/php:${{ matrix.version }}${{ matrix.flavor }} && make test'
- name: Build dev image for testing
uses: docker/build-push-action@v5
with:
cache-to: type=inline
context: ./dev
build-args: |
BASE_IMAGE=localhost:5000/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
tags: localhost:5000/chialab/php-dev:${{ matrix.version }}${{ matrix.flavor }}
push: true
- name: Test dev image
env:
REGISTRY: localhost:5000/
VERSION: ${{ matrix.version }}${{ matrix.flavor }}
run: 'docker pull localhost:5000/chialab/php-dev:${{ matrix.version }}${{ matrix.flavor }} && make -C dev test'
- name: Build PCOV image for testing
uses: docker/build-push-action@v5
with:
cache-to: type=inline
context: ./pcov
build-args: |
BASE_IMAGE=localhost:5000/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
tags: localhost:5000/chialab/php-pcov:${{ matrix.version }}${{ matrix.flavor }}
push: true
- name: Test PCOV image
env:
REGISTRY: localhost:5000/
VERSION: ${{ matrix.version }}${{ matrix.flavor }}
run: 'docker pull localhost:5000/chialab/php-pcov:${{ matrix.version }}${{ matrix.flavor }} && make -C pcov test'
- name: Build xhprof image for testing
uses: docker/build-push-action@v5
with:
cache-to: type=inline
context: ./xhprof
build-args: |
BASE_IMAGE=localhost:5000/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
tags: localhost:5000/chialab/php-xhprof:${{ matrix.version }}${{ matrix.flavor }}
push: true
- name: Test xhprof image
env:
REGISTRY: localhost:5000/
VERSION: ${{ matrix.version }}${{ matrix.flavor }}
run: 'docker pull localhost:5000/chialab/php-xhprof:${{ matrix.version }}${{ matrix.flavor }} && make -C xhprof test'
- name: Build OTel image for testing
uses: docker/build-push-action@v5
with:
cache-to: type=inline
context: ./otel
build-args: |
BASE_IMAGE=localhost:5000/chialab/php:${{ matrix.version }}${{ matrix.flavor }}
tags: localhost:5000/chialab/php-otel:${{ matrix.version }}${{ matrix.flavor }}
push: true
- name: Test OTel image
env:
REGISTRY: localhost:5000/
VERSION: ${{ matrix.version }}${{ matrix.flavor }}
run: 'docker pull localhost:5000/chialab/php-otel:${{ matrix.version }}${{ matrix.flavor }} && make -C otel test'
permissions:
contents: read
packages: write
uses: ./.github/workflows/build-images.yml
with:
versions: '["8.0", "8.1", "8.2", "8.3", "8.4", "8.5"]'
flavors: '["", "-apache", "-fpm", "-alpine", "-fpm-alpine"]'
secrets:
pull-username: ${{ secrets.DOCKER_PULL_USER_3 }}
pull-password: ${{ secrets.DOCKER_PULL_PASS_3 }}
+5 -1
View File
@@ -9,11 +9,14 @@ on:
pull_request:
types: [opened, synchronize]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test-compat:
name: Build and test compatibility images
runs-on: ubuntu-22.04
if: ${{ !contains(github.event.commits[0].message, '[skip ci]') && !contains(github.event.commits[0].message, '[ci skip]') }}
strategy:
fail-fast: false
matrix:
@@ -40,6 +43,7 @@ jobs:
# cache-from: type=registry,ref=ghcr.io/chialab/php-compat:${{ matrix.version }}${{ matrix.flavor }}
cache-to: type=inline
context: ./compat
build-contexts: patches=eol/patches
file: ${{ format('compat/{0}.{1}{2}', 'Dockerfile', matrix.version, matrix.flavor) }}
tags: localhost:5000/chialab/php-compat:${{ matrix.version }}${{ matrix.flavor }}
push: true
+9 -102
View File
@@ -12,105 +12,12 @@ on:
jobs:
test-latest:
name: Build and test latest PHP images
runs-on: ubuntu-latest
if: ${{ !contains(github.event.commits[0].message, '[skip ci]') && !contains(github.event.commits[0].message, '[ci skip]') }}
strategy:
fail-fast: false
matrix:
version: [ 'latest', 'alpine' ]
services:
registry:
image: registry:2
ports:
- 5000:5000
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_PULL_USER_5 }}
password: ${{ secrets.DOCKER_PULL_PASS_5 }}
- name: Build image for testing
uses: docker/build-push-action@v5
with:
# cache-from: type=registry,ref=ghcr.io/chialab/php:${{ matrix.version }}
cache-to: type=inline
context: .
file: ${{ ((contains(matrix.flavor, 'alpine') || matrix.version == 'alpine') && 'Dockerfile.alpine') || 'Dockerfile' }}
build-args: |
BASE_IMAGE=php:${{ matrix.version }}
tags: localhost:5000/chialab/php:${{ matrix.version }}
push: true
- name: Test image
env:
REGISTRY: localhost:5000/
VERSION: ${{ matrix.version }}
run: 'docker pull localhost:5000/chialab/php:${{ matrix.version }} && make test'
- name: Build dev image for testing
uses: docker/build-push-action@v5
with:
cache-to: type=inline
context: ./dev
build-args: |
BASE_IMAGE=localhost:5000/chialab/php:${{ matrix.version }}
tags: localhost:5000/chialab/php-dev:${{ matrix.version }}
push: true
- name: Test dev image
env:
REGISTRY: localhost:5000/
VERSION: ${{ matrix.version }}
run: 'docker pull localhost:5000/chialab/php-dev:${{ matrix.version }} && make -C dev test'
- name: Build PCOV image for testing
uses: docker/build-push-action@v5
with:
cache-to: type=inline
context: ./pcov
build-args: |
BASE_IMAGE=localhost:5000/chialab/php:${{ matrix.version }}
tags: localhost:5000/chialab/php-pcov:${{ matrix.version }}
push: true
- name: Test PCOV image
env:
REGISTRY: localhost:5000/
VERSION: ${{ matrix.version }}
run: 'docker pull localhost:5000/chialab/php-pcov:${{ matrix.version }} && make -C pcov test'
- name: Build xhprof image for testing
uses: docker/build-push-action@v5
with:
cache-to: type=inline
context: ./xhprof
build-args: |
BASE_IMAGE=localhost:5000/chialab/php:${{ matrix.version }}
tags: localhost:5000/chialab/php-xhprof:${{ matrix.version }}
push: true
- name: Test xhprof image
env:
REGISTRY: localhost:5000/
VERSION: ${{ matrix.version }}
run: 'docker pull localhost:5000/chialab/php-xhprof:${{ matrix.version }} && make -C xhprof test'
- name: Build OTel image for testing
uses: docker/build-push-action@v5
with:
cache-to: type=inline
context: ./otel
build-args: |
BASE_IMAGE=localhost:5000/chialab/php:${{ matrix.version }}
tags: localhost:5000/chialab/php-otel:${{ matrix.version }}
push: true
- name: Test OTel image
env:
REGISTRY: localhost:5000/
VERSION: ${{ matrix.version }}
run: 'docker pull localhost:5000/chialab/php-otel:${{ matrix.version }} && make -C otel test'
permissions:
contents: read
packages: write
uses: ./.github/workflows/build-images.yml
with:
versions: '["latest", "alpine"]'
secrets:
pull-username: ${{ secrets.DOCKER_PULL_USER_5 }}
pull-password: ${{ secrets.DOCKER_PULL_PASS_5 }}
+28 -4
View File
@@ -1,11 +1,17 @@
SHELL := /bin/bash
ALL: build
.PHONY: build test push
.PHONY: build build-base test push
PARENT_IMAGE := php
BASE_IMAGE_NAME := chialab/php-base
IMAGE := chialab/php
VERSION ?= latest
PHP_VERSION = $(firstword $(subst -, ,$(VERSION)))
FLAVOR = $(if $(findstring -,$(VERSION)),$(patsubst $(PHP_VERSION)-%,%,$(VERSION)),cli)
# EOL versions are built from eol/ instead of the official images.
EOL_DIR = $(wildcard eol/$(PHP_VERSION)/$(FLAVOR))
BASE_IMAGE = $(if $(EOL_DIR),$(REGISTRY)$(BASE_IMAGE_NAME):$(VERSION),$(PARENT_IMAGE):$(VERSION))
DOCKERFILE = $(if $(findstring alpine,$(VERSION)),Dockerfile.alpine,Dockerfile)
# Extensions.
EXTENSIONS := \
@@ -42,13 +48,21 @@ ifeq (,$(findstring $(PHP_VERSION), 7.0 7.1 7.2 7.3 7.4 8.0 8.1 8.2 8.3 8.4 8.5
EXTENSIONS += mysql
endif
build:
build: $(if $(EOL_DIR),build-base)
@echo " =====> Building $(REGISTRY)$(IMAGE):$(VERSION)..."
docker image build --quiet --build-arg 'BASE_IMAGE=$(PARENT_IMAGE):$(VERSION)' -t $(REGISTRY)$(IMAGE):$(VERSION) .
docker image build --quiet --build-arg 'BASE_IMAGE=$(BASE_IMAGE)' -f $(DOCKERFILE) -t $(REGISTRY)$(IMAGE):$(VERSION) .
build-base:
@if [[ -z "$(EOL_DIR)" ]]; then \
echo 'No eol/ Dockerfile for $(VERSION)'; \
exit 1; \
fi
@echo " =====> Building $(BASE_IMAGE)..."
docker image build --quiet --build-context patches=eol/patches --build-context scripts=eol/scripts -t $(BASE_IMAGE) $(EOL_DIR)
test:
@echo -e "=====> Testing loaded extensions... \c"
@if [[ -z `docker image ls $(REGISTRY)$(IMAGE) | grep "\s$(VERSION)\s"` ]]; then \
@if ! docker image inspect $(REGISTRY)$(IMAGE):$(VERSION) > /dev/null 2>&1; then \
echo 'FAIL [Missing image!!!]'; \
exit 1; \
fi
@@ -71,6 +85,16 @@ test:
exit 1; \
fi \
fi
@if [[ "$(VERSION)" == *'-fpm'* ]]; then \
if ! docker container run --rm $(REGISTRY)$(IMAGE):$(VERSION) php-fpm -t > /dev/null 2>&1; then \
echo 'FAIL [php-fpm]'; \
exit 1; \
fi \
fi
@if [[ -n "$(EOL_DIR)" && -z `docker container run --rm $(REGISTRY)$(IMAGE):$(VERSION) sh -c '/bin/echo $$PHP_PATCHES'` ]]; then \
echo 'FAIL [PHP_PATCHES]'; \
exit 1; \
fi
@if [[ -z `docker container run --rm $(REGISTRY)$(IMAGE):$(VERSION) composer --version 2> /dev/null | grep '^Composer version 2\.[0-9][0-9]*'` ]]; then \
echo 'FAIL [Composer]'; \
exit 1; \
+5
View File
@@ -57,6 +57,11 @@ If you are really desperate and need PHP 5.6 with support for MySQL 8.x, check t
As you might have guessed, all tags are built on top of the corresponding tag of the official image. Not all tags are supported in order to easen maintenance.
### Security backports for EOL versions
The official images of unsupported PHP versions (5.6 to 8.1) no longer receive security fixes. For those versions we rebuild PHP from the official images' Dockerfiles (see [`eol/`](eol/)), on the same OS release, with security patches applied to the PHP sources. The image layout doesn't change, so `docker-php-ext-*` and `install-php-extensions` keep working.
The `PHP_PATCHES` environment variable and the `it.chialab.php.patches` label list what has been applied. `PHP_VERSION` and `php -v` still report the upstream version, so vulnerability scanners may keep flagging fixed issues.
## Installed extensions
The following modules and extensions have been enabled,
in addition to those you can already find in the [official PHP image](https://hub.docker.com/r/_/php/):
+7
View File
@@ -107,6 +107,13 @@ RUN set -xe; \
COPY --from=php:5.6 /usr/local/bin/docker-php-source /usr/local/bin/
# Security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=5.6,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
+7
View File
@@ -167,6 +167,13 @@ RUN set -xe; \
COPY --from=php:5.6-apache /usr/local/bin/docker-php-source /usr/local/bin/
# Security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=5.6,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
+7
View File
@@ -108,6 +108,13 @@ RUN set -xe; \
COPY --from=php:5.6-fpm /usr/local/bin/docker-php-source /usr/local/bin/
# Security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=5.6,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
+6 -2
View File
@@ -43,11 +43,11 @@ endif
build:
@echo " =====> Building $(REGISTRY)$(IMAGE):$(VERSION)..."
docker image build --quiet -t $(REGISTRY)$(IMAGE):$(VERSION) .
docker image build --quiet --build-context patches=../eol/patches -f Dockerfile.$(VERSION) -t $(REGISTRY)$(IMAGE):$(VERSION) .
test:
@echo -e "=====> Testing loaded extensions... \c"
@if [[ -z `docker image ls $(REGISTRY)$(IMAGE) | grep "\s$(VERSION)\s"` ]]; then \
@if ! docker image inspect $(REGISTRY)$(IMAGE):$(VERSION) > /dev/null 2>&1; then \
echo 'FAIL [Missing image!!!]'; \
exit 1; \
fi
@@ -74,6 +74,10 @@ test:
echo 'FAIL [Composer]'; \
exit 1; \
fi
@if [[ -z `docker container run --rm $(REGISTRY)$(IMAGE):$(VERSION) sh -c '/bin/echo $$PHP_PATCHES'` ]]; then \
echo 'FAIL [PHP_PATCHES]'; \
exit 1; \
fi
@mariadbClientApi=`docker container run --rm $(REGISTRY)$(IMAGE):$(VERSION) php -i | grep -e "Client API.*MariaDB" | wc -l`; \
if [[ "$${mariadbClientApi}" -lt 4 ]]; then \
echo 'FAIL [MariaDB]'; \
+1 -1
View File
@@ -49,7 +49,7 @@ build:
test:
@echo -e "=====> Testing loaded extensions... \c"
@if [[ -z `docker image ls $(REGISTRY)$(IMAGE) | grep "\s$(VERSION)\s"` ]]; then \
@if ! docker image inspect $(REGISTRY)$(IMAGE):$(VERSION) > /dev/null 2>&1; then \
echo 'FAIL [Missing image!!!]'; \
exit 1; \
fi
+286
View File
@@ -0,0 +1,286 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/fab49d4cb1c61e4f74c2dffe06961408212f054c/5.6/stretch/apache),
# with the changes marked "chialab:".
#
FROM debian:stretch-slim
# chialab: Debian stretch has been moved to archive.debian.org.
RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/stretch-updates/d' /etc/apt/sources.list
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN apt-get update && apt-get install -y \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
--no-install-recommends && rm -r /var/lib/apt/lists/*
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
##<autogenerated>##
ENV APACHE_CONFDIR /etc/apache2
ENV APACHE_ENVVARS $APACHE_CONFDIR/envvars
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends apache2; \
rm -rf /var/lib/apt/lists/*; \
\
# generically convert lines like
# export APACHE_RUN_USER=www-data
# into
# : ${APACHE_RUN_USER:=www-data}
# export APACHE_RUN_USER
# so that they can be overridden at runtime ("-e APACHE_RUN_USER=...")
sed -ri 's/^export ([^=]+)=(.*)$/: ${\1:=\2}\nexport \1/' "$APACHE_ENVVARS"; \
\
# setup directories and permissions
. "$APACHE_ENVVARS"; \
for dir in \
"$APACHE_LOCK_DIR" \
"$APACHE_RUN_DIR" \
"$APACHE_LOG_DIR" \
; do \
rm -rvf "$dir"; \
mkdir -p "$dir"; \
chown "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$dir"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
chmod 777 "$dir"; \
done; \
\
# delete the "index.html" that installing Apache drops in here
rm -rvf /var/www/html/*; \
\
# logs should go to stdout / stderr
ln -sfT /dev/stderr "$APACHE_LOG_DIR/error.log"; \
ln -sfT /dev/stdout "$APACHE_LOG_DIR/access.log"; \
ln -sfT /dev/stdout "$APACHE_LOG_DIR/other_vhosts_access.log"; \
chown -R --no-dereference "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$APACHE_LOG_DIR"
# Apache + PHP requires preforking Apache for best results
RUN a2dismod mpm_event && a2enmod mpm_prefork
# PHP files should be handled by PHP, and should be preferred over any other file type
RUN { \
echo '<FilesMatch \.php$>'; \
echo '\tSetHandler application/x-httpd-php'; \
echo '</FilesMatch>'; \
echo; \
echo 'DirectoryIndex disabled'; \
echo 'DirectoryIndex index.php index.html'; \
echo; \
echo '<Directory /var/www/>'; \
echo '\tOptions -Indexes'; \
echo '\tAllowOverride All'; \
echo '</Directory>'; \
} | tee "$APACHE_CONFDIR/conf-available/docker-php.conf" \
&& a2enconf docker-php
ENV PHP_EXTRA_BUILD_DEPS apache2-dev
ENV PHP_EXTRA_CONFIGURE_ARGS --with-apxs2 --disable-cgi
##</autogenerated>##
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# Adds GNU HASH segments to generated executables (this is used if present, and is much faster than sysv hash; in this configuration, sysv hash is also generated)
# https://github.com/docker-library/php/issues/272
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -Wl,--hash-style=both -pie"
ENV GPG_KEYS 0BD78B5F97500D450838F95DFE857D9A90D90EC1 6E4F6AB321FDC07F2C332E3AC2BF0BC433CFC8B3
ENV PHP_VERSION 5.6.40
# chialab: the php.net mirror redirector is gone.
ENV PHP_URL="https://www.php.net/distributions/php-5.6.40.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-5.6.40.tar.xz.asc"
ENV PHP_SHA256="1369a51eee3995d7fbd1c5342e5cc917760e276d561595b6052b21ace2656d1c" PHP_MD5=""
RUN set -xe; \
\
fetchDeps=' \
wget \
'; \
if ! command -v gpg > /dev/null; then \
fetchDeps="$fetchDeps \
dirmngr \
gnupg \
"; \
fi; \
apt-get update; \
apt-get install -y --no-install-recommends $fetchDeps; \
rm -rf /var/lib/apt/lists/*; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
wget -O php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
if [ -n "$PHP_MD5" ]; then \
echo "$PHP_MD5 *php.tar.xz" | md5sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
wget -O php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
# chialab: the SKS keyserver pool is gone.
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
command -v gpgconf > /dev/null && gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false $fetchDeps
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=5.6,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
libcurl4-openssl-dev \
libedit-dev \
libsqlite3-dev \
libssl1.0-dev \
libxml2-dev \
zlib1g-dev \
${PHP_EXTRA_BUILD_DEPS:-} \
; \
rm -rf /var/lib/apt/lists/*; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors intead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
\
--with-curl \
--with-libedit \
--with-openssl \
--with-zlib \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/stretch/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
${PHP_EXTRA_CONFIGURE_ARGS:-} \
; \
make -j "$(nproc)"; \
make install; \
find /usr/local/bin /usr/local/sbin -type f -executable -exec strip --strip-all '{}' + || true; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
\
php --version; \
\
# https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/5.6 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/5.6 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/5.6 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/apache /usr/local/bin/docker-php-entrypoint
ENTRYPOINT ["docker-php-entrypoint"]
##<autogenerated>##
# chialab: from eol/scripts.
COPY --from=scripts apache2-foreground /usr/local/bin/
WORKDIR /var/www/html
EXPOSE 80
CMD ["apache2-foreground"]
##</autogenerated>##
+221
View File
@@ -0,0 +1,221 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/fab49d4cb1c61e4f74c2dffe06961408212f054c/5.6/stretch/cli),
# with the changes marked "chialab:".
#
FROM debian:stretch-slim
# chialab: Debian stretch has been moved to archive.debian.org.
RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/stretch-updates/d' /etc/apt/sources.list
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN apt-get update && apt-get install -y \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
--no-install-recommends && rm -r /var/lib/apt/lists/*
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
##<autogenerated>##
##</autogenerated>##
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# Adds GNU HASH segments to generated executables (this is used if present, and is much faster than sysv hash; in this configuration, sysv hash is also generated)
# https://github.com/docker-library/php/issues/272
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -Wl,--hash-style=both -pie"
ENV GPG_KEYS 0BD78B5F97500D450838F95DFE857D9A90D90EC1 6E4F6AB321FDC07F2C332E3AC2BF0BC433CFC8B3
ENV PHP_VERSION 5.6.40
# chialab: the php.net mirror redirector is gone.
ENV PHP_URL="https://www.php.net/distributions/php-5.6.40.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-5.6.40.tar.xz.asc"
ENV PHP_SHA256="1369a51eee3995d7fbd1c5342e5cc917760e276d561595b6052b21ace2656d1c" PHP_MD5=""
RUN set -xe; \
\
fetchDeps=' \
wget \
'; \
if ! command -v gpg > /dev/null; then \
fetchDeps="$fetchDeps \
dirmngr \
gnupg \
"; \
fi; \
apt-get update; \
apt-get install -y --no-install-recommends $fetchDeps; \
rm -rf /var/lib/apt/lists/*; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
wget -O php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
if [ -n "$PHP_MD5" ]; then \
echo "$PHP_MD5 *php.tar.xz" | md5sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
wget -O php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
# chialab: the SKS keyserver pool is gone.
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
command -v gpgconf > /dev/null && gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false $fetchDeps
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=5.6,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
libcurl4-openssl-dev \
libedit-dev \
libsqlite3-dev \
libssl1.0-dev \
libxml2-dev \
zlib1g-dev \
${PHP_EXTRA_BUILD_DEPS:-} \
; \
rm -rf /var/lib/apt/lists/*; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors intead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
\
--with-curl \
--with-libedit \
--with-openssl \
--with-zlib \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/stretch/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
${PHP_EXTRA_CONFIGURE_ARGS:-} \
; \
make -j "$(nproc)"; \
make install; \
find /usr/local/bin /usr/local/sbin -type f -executable -exec strip --strip-all '{}' + || true; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
\
php --version; \
\
# https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/5.6 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/5.6 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/5.6 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/cli /usr/local/bin/docker-php-entrypoint
ENTRYPOINT ["docker-php-entrypoint"]
##<autogenerated>##
CMD ["php", "-a"]
##</autogenerated>##
+261
View File
@@ -0,0 +1,261 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/fab49d4cb1c61e4f74c2dffe06961408212f054c/5.6/stretch/fpm),
# with the changes marked "chialab:".
#
FROM debian:stretch-slim
# chialab: Debian stretch has been moved to archive.debian.org.
RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/stretch-updates/d' /etc/apt/sources.list
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN apt-get update && apt-get install -y \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
--no-install-recommends && rm -r /var/lib/apt/lists/*
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
##<autogenerated>##
ENV PHP_EXTRA_CONFIGURE_ARGS --enable-fpm --with-fpm-user=www-data --with-fpm-group=www-data --disable-cgi
##</autogenerated>##
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# Adds GNU HASH segments to generated executables (this is used if present, and is much faster than sysv hash; in this configuration, sysv hash is also generated)
# https://github.com/docker-library/php/issues/272
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -Wl,--hash-style=both -pie"
ENV GPG_KEYS 0BD78B5F97500D450838F95DFE857D9A90D90EC1 6E4F6AB321FDC07F2C332E3AC2BF0BC433CFC8B3
ENV PHP_VERSION 5.6.40
# chialab: the php.net mirror redirector is gone.
ENV PHP_URL="https://www.php.net/distributions/php-5.6.40.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-5.6.40.tar.xz.asc"
ENV PHP_SHA256="1369a51eee3995d7fbd1c5342e5cc917760e276d561595b6052b21ace2656d1c" PHP_MD5=""
RUN set -xe; \
\
fetchDeps=' \
wget \
'; \
if ! command -v gpg > /dev/null; then \
fetchDeps="$fetchDeps \
dirmngr \
gnupg \
"; \
fi; \
apt-get update; \
apt-get install -y --no-install-recommends $fetchDeps; \
rm -rf /var/lib/apt/lists/*; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
wget -O php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
if [ -n "$PHP_MD5" ]; then \
echo "$PHP_MD5 *php.tar.xz" | md5sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
wget -O php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
# chialab: the SKS keyserver pool is gone.
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
command -v gpgconf > /dev/null && gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false $fetchDeps
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=5.6,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
libcurl4-openssl-dev \
libedit-dev \
libsqlite3-dev \
libssl1.0-dev \
libxml2-dev \
zlib1g-dev \
${PHP_EXTRA_BUILD_DEPS:-} \
; \
rm -rf /var/lib/apt/lists/*; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors intead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
\
--with-curl \
--with-libedit \
--with-openssl \
--with-zlib \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/stretch/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
${PHP_EXTRA_CONFIGURE_ARGS:-} \
; \
make -j "$(nproc)"; \
make install; \
find /usr/local/bin /usr/local/sbin -type f -executable -exec strip --strip-all '{}' + || true; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
\
php --version; \
\
# https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/5.6 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/5.6 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/5.6 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/fpm /usr/local/bin/docker-php-entrypoint
ENTRYPOINT ["docker-php-entrypoint"]
##<autogenerated>##
WORKDIR /var/www/html
RUN set -ex \
&& cd /usr/local/etc \
&& if [ -d php-fpm.d ]; then \
# for some reason, upstream's php-fpm.conf.default has "include=NONE/etc/php-fpm.d/*.conf"
sed 's!=NONE/!=!g' php-fpm.conf.default | tee php-fpm.conf > /dev/null; \
cp php-fpm.d/www.conf.default php-fpm.d/www.conf; \
else \
# PHP 5.x doesn't use "include=" by default, so we'll create our own simple config that mimics PHP 7+ for consistency
mkdir php-fpm.d; \
cp php-fpm.conf.default php-fpm.d/www.conf; \
{ \
echo '[global]'; \
echo 'include=etc/php-fpm.d/*.conf'; \
} | tee php-fpm.conf; \
fi \
&& { \
echo '[global]'; \
echo 'error_log = /proc/self/fd/2'; \
echo; \
echo '[www]'; \
echo '; if we send this to /proc/self/fd/1, it never appears'; \
echo 'access.log = /proc/self/fd/2'; \
echo; \
echo 'clear_env = no'; \
echo; \
echo '; Ensure worker stdout and stderr are sent to the main error log.'; \
echo 'catch_workers_output = yes'; \
} | tee php-fpm.d/docker.conf \
&& { \
echo '[global]'; \
echo 'daemonize = no'; \
echo; \
echo '[www]'; \
echo 'listen = 9000'; \
} | tee php-fpm.d/zz-docker.conf
EXPOSE 9000
CMD ["php-fpm"]
##</autogenerated>##
+280
View File
@@ -0,0 +1,280 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/0e5c984e02d9027c25794bfb5002a2f9da26a7ec/7.0/stretch/apache),
# with the changes marked "chialab:".
#
FROM debian:stretch-slim
# chialab: Debian stretch has been moved to archive.debian.org.
RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/stretch-updates/d' /etc/apt/sources.list
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN apt-get update && apt-get install -y \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
--no-install-recommends && rm -r /var/lib/apt/lists/*
ENV PHP_INI_DIR /usr/local/etc/php
RUN mkdir -p $PHP_INI_DIR/conf.d
##<autogenerated>##
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
apache2 \
&& rm -rf /var/lib/apt/lists/*
ENV APACHE_CONFDIR /etc/apache2
ENV APACHE_ENVVARS $APACHE_CONFDIR/envvars
RUN set -eux; \
\
# generically convert lines like
# export APACHE_RUN_USER=www-data
# into
# : ${APACHE_RUN_USER:=www-data}
# export APACHE_RUN_USER
# so that they can be overridden at runtime ("-e APACHE_RUN_USER=...")
sed -ri 's/^export ([^=]+)=(.*)$/: ${\1:=\2}\nexport \1/' "$APACHE_ENVVARS"; \
\
# setup directories and permissions
. "$APACHE_ENVVARS"; \
for dir in \
"$APACHE_LOCK_DIR" \
"$APACHE_RUN_DIR" \
"$APACHE_LOG_DIR" \
/var/www/html \
; do \
rm -rvf "$dir"; \
mkdir -p "$dir"; \
chown "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$dir"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
chmod 777 "$dir"; \
done; \
\
# logs should go to stdout / stderr
ln -sfT /dev/stderr "$APACHE_LOG_DIR/error.log"; \
ln -sfT /dev/stdout "$APACHE_LOG_DIR/access.log"; \
ln -sfT /dev/stdout "$APACHE_LOG_DIR/other_vhosts_access.log"; \
chown -R --no-dereference "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$APACHE_LOG_DIR"
# Apache + PHP requires preforking Apache for best results
RUN a2dismod mpm_event && a2enmod mpm_prefork
# PHP files should be handled by PHP, and should be preferred over any other file type
RUN { \
echo '<FilesMatch \.php$>'; \
echo '\tSetHandler application/x-httpd-php'; \
echo '</FilesMatch>'; \
echo; \
echo 'DirectoryIndex disabled'; \
echo 'DirectoryIndex index.php index.html'; \
echo; \
echo '<Directory /var/www/>'; \
echo '\tOptions -Indexes'; \
echo '\tAllowOverride All'; \
echo '</Directory>'; \
} | tee "$APACHE_CONFDIR/conf-available/docker-php.conf" \
&& a2enconf docker-php
ENV PHP_EXTRA_BUILD_DEPS apache2-dev
ENV PHP_EXTRA_CONFIGURE_ARGS --with-apxs2 --disable-cgi
##</autogenerated>##
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# Adds GNU HASH segments to generated executables (this is used if present, and is much faster than sysv hash; in this configuration, sysv hash is also generated)
# https://github.com/docker-library/php/issues/272
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -Wl,--hash-style=both -pie"
ENV GPG_KEYS 1A4E8B7277C42E53DBA9C7B9BCAA30EA9C0D5763 6E4F6AB321FDC07F2C332E3AC2BF0BC433CFC8B3
ENV PHP_VERSION 7.0.33
# chialab: the php.net mirror redirector is gone.
ENV PHP_URL="https://www.php.net/distributions/php-7.0.33.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.0.33.tar.xz.asc"
ENV PHP_SHA256="ab8c5be6e32b1f8d032909dedaaaa4bbb1a209e519abb01a52ce3914f9a13d96" PHP_MD5=""
RUN set -xe; \
\
fetchDeps=' \
wget \
'; \
if ! command -v gpg > /dev/null; then \
fetchDeps="$fetchDeps \
dirmngr \
gnupg \
"; \
fi; \
apt-get update; \
apt-get install -y --no-install-recommends $fetchDeps; \
rm -rf /var/lib/apt/lists/*; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
wget -O php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
if [ -n "$PHP_MD5" ]; then \
echo "$PHP_MD5 *php.tar.xz" | md5sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
wget -O php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
# chialab: the SKS keyserver pool is gone.
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
command -v gpgconf > /dev/null && gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false $fetchDeps
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.0,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
libcurl4-openssl-dev \
libedit-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
zlib1g-dev \
${PHP_EXTRA_BUILD_DEPS:-} \
; \
rm -rf /var/lib/apt/lists/*; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors intead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
\
--with-curl \
--with-libedit \
--with-openssl \
--with-zlib \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/stretch/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
${PHP_EXTRA_CONFIGURE_ARGS:-} \
; \
make -j "$(nproc)"; \
make install; \
find /usr/local/bin /usr/local/sbin -type f -executable -exec strip --strip-all '{}' + || true; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
\
php --version; \
\
# https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/5.6 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/5.6 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/5.6 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/apache /usr/local/bin/docker-php-entrypoint
ENTRYPOINT ["docker-php-entrypoint"]
##<autogenerated>##
# chialab: from eol/scripts.
COPY --from=scripts apache2-foreground /usr/local/bin/
WORKDIR /var/www/html
EXPOSE 80
CMD ["apache2-foreground"]
##</autogenerated>##
+215
View File
@@ -0,0 +1,215 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/0e5c984e02d9027c25794bfb5002a2f9da26a7ec/7.0/stretch/cli),
# with the changes marked "chialab:".
#
FROM debian:stretch-slim
# chialab: Debian stretch has been moved to archive.debian.org.
RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/stretch-updates/d' /etc/apt/sources.list
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN apt-get update && apt-get install -y \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
--no-install-recommends && rm -r /var/lib/apt/lists/*
ENV PHP_INI_DIR /usr/local/etc/php
RUN mkdir -p $PHP_INI_DIR/conf.d
##<autogenerated>##
##</autogenerated>##
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# Adds GNU HASH segments to generated executables (this is used if present, and is much faster than sysv hash; in this configuration, sysv hash is also generated)
# https://github.com/docker-library/php/issues/272
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -Wl,--hash-style=both -pie"
ENV GPG_KEYS 1A4E8B7277C42E53DBA9C7B9BCAA30EA9C0D5763 6E4F6AB321FDC07F2C332E3AC2BF0BC433CFC8B3
ENV PHP_VERSION 7.0.33
# chialab: the php.net mirror redirector is gone.
ENV PHP_URL="https://www.php.net/distributions/php-7.0.33.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.0.33.tar.xz.asc"
ENV PHP_SHA256="ab8c5be6e32b1f8d032909dedaaaa4bbb1a209e519abb01a52ce3914f9a13d96" PHP_MD5=""
RUN set -xe; \
\
fetchDeps=' \
wget \
'; \
if ! command -v gpg > /dev/null; then \
fetchDeps="$fetchDeps \
dirmngr \
gnupg \
"; \
fi; \
apt-get update; \
apt-get install -y --no-install-recommends $fetchDeps; \
rm -rf /var/lib/apt/lists/*; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
wget -O php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
if [ -n "$PHP_MD5" ]; then \
echo "$PHP_MD5 *php.tar.xz" | md5sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
wget -O php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
# chialab: the SKS keyserver pool is gone.
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
command -v gpgconf > /dev/null && gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false $fetchDeps
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.0,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
libcurl4-openssl-dev \
libedit-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
zlib1g-dev \
${PHP_EXTRA_BUILD_DEPS:-} \
; \
rm -rf /var/lib/apt/lists/*; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors intead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
\
--with-curl \
--with-libedit \
--with-openssl \
--with-zlib \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/stretch/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
${PHP_EXTRA_CONFIGURE_ARGS:-} \
; \
make -j "$(nproc)"; \
make install; \
find /usr/local/bin /usr/local/sbin -type f -executable -exec strip --strip-all '{}' + || true; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
\
php --version; \
\
# https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/5.6 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/5.6 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/5.6 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/cli /usr/local/bin/docker-php-entrypoint
ENTRYPOINT ["docker-php-entrypoint"]
##<autogenerated>##
CMD ["php", "-a"]
##</autogenerated>##
+255
View File
@@ -0,0 +1,255 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/0e5c984e02d9027c25794bfb5002a2f9da26a7ec/7.0/stretch/fpm),
# with the changes marked "chialab:".
#
FROM debian:stretch-slim
# chialab: Debian stretch has been moved to archive.debian.org.
RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/stretch-updates/d' /etc/apt/sources.list
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN apt-get update && apt-get install -y \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
--no-install-recommends && rm -r /var/lib/apt/lists/*
ENV PHP_INI_DIR /usr/local/etc/php
RUN mkdir -p $PHP_INI_DIR/conf.d
##<autogenerated>##
ENV PHP_EXTRA_CONFIGURE_ARGS --enable-fpm --with-fpm-user=www-data --with-fpm-group=www-data --disable-cgi
##</autogenerated>##
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# Adds GNU HASH segments to generated executables (this is used if present, and is much faster than sysv hash; in this configuration, sysv hash is also generated)
# https://github.com/docker-library/php/issues/272
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -Wl,--hash-style=both -pie"
ENV GPG_KEYS 1A4E8B7277C42E53DBA9C7B9BCAA30EA9C0D5763 6E4F6AB321FDC07F2C332E3AC2BF0BC433CFC8B3
ENV PHP_VERSION 7.0.33
# chialab: the php.net mirror redirector is gone.
ENV PHP_URL="https://www.php.net/distributions/php-7.0.33.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.0.33.tar.xz.asc"
ENV PHP_SHA256="ab8c5be6e32b1f8d032909dedaaaa4bbb1a209e519abb01a52ce3914f9a13d96" PHP_MD5=""
RUN set -xe; \
\
fetchDeps=' \
wget \
'; \
if ! command -v gpg > /dev/null; then \
fetchDeps="$fetchDeps \
dirmngr \
gnupg \
"; \
fi; \
apt-get update; \
apt-get install -y --no-install-recommends $fetchDeps; \
rm -rf /var/lib/apt/lists/*; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
wget -O php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
if [ -n "$PHP_MD5" ]; then \
echo "$PHP_MD5 *php.tar.xz" | md5sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
wget -O php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
# chialab: the SKS keyserver pool is gone.
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
command -v gpgconf > /dev/null && gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false $fetchDeps
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.0,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
libcurl4-openssl-dev \
libedit-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
zlib1g-dev \
${PHP_EXTRA_BUILD_DEPS:-} \
; \
rm -rf /var/lib/apt/lists/*; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors intead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
\
--with-curl \
--with-libedit \
--with-openssl \
--with-zlib \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/stretch/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
${PHP_EXTRA_CONFIGURE_ARGS:-} \
; \
make -j "$(nproc)"; \
make install; \
find /usr/local/bin /usr/local/sbin -type f -executable -exec strip --strip-all '{}' + || true; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
\
php --version; \
\
# https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/5.6 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/5.6 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/5.6 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/fpm /usr/local/bin/docker-php-entrypoint
ENTRYPOINT ["docker-php-entrypoint"]
##<autogenerated>##
WORKDIR /var/www/html
RUN set -ex \
&& cd /usr/local/etc \
&& if [ -d php-fpm.d ]; then \
# for some reason, upstream's php-fpm.conf.default has "include=NONE/etc/php-fpm.d/*.conf"
sed 's!=NONE/!=!g' php-fpm.conf.default | tee php-fpm.conf > /dev/null; \
cp php-fpm.d/www.conf.default php-fpm.d/www.conf; \
else \
# PHP 5.x doesn't use "include=" by default, so we'll create our own simple config that mimics PHP 7+ for consistency
mkdir php-fpm.d; \
cp php-fpm.conf.default php-fpm.d/www.conf; \
{ \
echo '[global]'; \
echo 'include=etc/php-fpm.d/*.conf'; \
} | tee php-fpm.conf; \
fi \
&& { \
echo '[global]'; \
echo 'error_log = /proc/self/fd/2'; \
echo; \
echo '[www]'; \
echo '; if we send this to /proc/self/fd/1, it never appears'; \
echo 'access.log = /proc/self/fd/2'; \
echo; \
echo 'clear_env = no'; \
echo; \
echo '; Ensure worker stdout and stderr are sent to the main error log.'; \
echo 'catch_workers_output = yes'; \
} | tee php-fpm.d/docker.conf \
&& { \
echo '[global]'; \
echo 'daemonize = no'; \
echo; \
echo '[www]'; \
echo 'listen = 9000'; \
} | tee php-fpm.d/zz-docker.conf
EXPOSE 9000
CMD ["php-fpm"]
##</autogenerated>##
+197
View File
@@ -0,0 +1,197 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/2bf33a859340cf4932a7bce5ae7bc935fc778b9d/7.1/alpine3.10/cli),
# with the changes marked "chialab:".
#
FROM alpine:3.10
# dependencies required for running "phpize"
# these get automatically installed and removed by "docker-php-ext-*" (unless they're already installed)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev dpkg \
file \
g++ \
gcc \
libc-dev \
make \
pkgconf \
re2c
# persistent / runtime deps
RUN apk add --no-cache \
ca-certificates \
curl \
tar \
xz \
# https://github.com/docker-library/php/issues/494
openssl
# ensure www-data user exists
RUN set -eux; \
addgroup -g 82 -S www-data; \
adduser -u 82 -D -S -G www-data www-data
# 82 is the standard uid/gid for "www-data" in Alpine
# https://git.alpinelinux.org/aports/tree/main/apache2/apache2.pre-install?h=3.9-stable
# https://git.alpinelinux.org/aports/tree/main/lighttpd/lighttpd.pre-install?h=3.9-stable
# https://git.alpinelinux.org/aports/tree/main/nginx/nginx.pre-install?h=3.9-stable
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
##<autogenerated>##
##</autogenerated>##
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# Adds GNU HASH segments to generated executables (this is used if present, and is much faster than sysv hash; in this configuration, sysv hash is also generated)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -Wl,--hash-style=both -pie"
ENV GPG_KEYS A917B1ECDA84AEC2B568FED6F50ABC807BD5DCD0 528995BFEDFBA7191D46839EF9BA0ADA31CBD89E 1729F83938DA44E27BA0F4D3DBDB397470D12172
ENV PHP_VERSION 7.1.33
# chialab: the php.net mirror redirector is gone.
ENV PHP_URL="https://www.php.net/distributions/php-7.1.33.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.1.33.tar.xz.asc"
ENV PHP_SHA256="bd7c0a9bd5433289ee01fd440af3715309faf583f75832b64fe169c100d52968" PHP_MD5=""
RUN set -eux; \
\
apk add --no-cache --virtual .fetch-deps gnupg; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
if [ -n "$PHP_MD5" ]; then \
echo "$PHP_MD5 *php.tar.xz" | md5sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
# chialab: the SKS keyserver pool is gone.
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apk del --no-network .fetch-deps
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.1,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
coreutils \
curl-dev \
libedit-dev \
libxml2-dev \
openssl-dev \
sqlite-dev \
; \
\
export CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors intead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-libedit \
--with-openssl \
--with-zlib \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/stretch/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-musl' && echo '--without-pcre-jit') \
\
${PHP_EXTRA_CONFIGURE_ARGS:-} \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find /usr/local/bin /usr/local/sbin -type f -perm +0111 -exec strip --strip-all '{}' + || true; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)"; \
apk add --no-cache $runDeps; \
\
apk del --no-network .build-deps; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/5.6 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.1 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.1 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/cli /usr/local/bin/docker-php-entrypoint
ENTRYPOINT ["docker-php-entrypoint"]
##<autogenerated>##
CMD ["php", "-a"]
##</autogenerated>##
+294
View File
@@ -0,0 +1,294 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/2bf33a859340cf4932a7bce5ae7bc935fc778b9d/7.1/buster/apache),
# with the changes marked "chialab:".
#
FROM debian:buster-slim
# chialab: Debian buster has been moved to archive.debian.org.
RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/buster-updates/d' /etc/apt/sources.list
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
; \
rm -rf /var/lib/apt/lists/*
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
##<autogenerated>##
ENV APACHE_CONFDIR /etc/apache2
ENV APACHE_ENVVARS $APACHE_CONFDIR/envvars
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends apache2; \
rm -rf /var/lib/apt/lists/*; \
\
# generically convert lines like
# export APACHE_RUN_USER=www-data
# into
# : ${APACHE_RUN_USER:=www-data}
# export APACHE_RUN_USER
# so that they can be overridden at runtime ("-e APACHE_RUN_USER=...")
sed -ri 's/^export ([^=]+)=(.*)$/: ${\1:=\2}\nexport \1/' "$APACHE_ENVVARS"; \
\
# setup directories and permissions
. "$APACHE_ENVVARS"; \
for dir in \
"$APACHE_LOCK_DIR" \
"$APACHE_RUN_DIR" \
"$APACHE_LOG_DIR" \
; do \
rm -rvf "$dir"; \
mkdir -p "$dir"; \
chown "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$dir"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
chmod 777 "$dir"; \
done; \
\
# delete the "index.html" that installing Apache drops in here
rm -rvf /var/www/html/*; \
\
# logs should go to stdout / stderr
ln -sfT /dev/stderr "$APACHE_LOG_DIR/error.log"; \
ln -sfT /dev/stdout "$APACHE_LOG_DIR/access.log"; \
ln -sfT /dev/stdout "$APACHE_LOG_DIR/other_vhosts_access.log"; \
chown -R --no-dereference "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$APACHE_LOG_DIR"
# Apache + PHP requires preforking Apache for best results
RUN a2dismod mpm_event && a2enmod mpm_prefork
# PHP files should be handled by PHP, and should be preferred over any other file type
RUN { \
echo '<FilesMatch \.php$>'; \
echo '\tSetHandler application/x-httpd-php'; \
echo '</FilesMatch>'; \
echo; \
echo 'DirectoryIndex disabled'; \
echo 'DirectoryIndex index.php index.html'; \
echo; \
echo '<Directory /var/www/>'; \
echo '\tOptions -Indexes'; \
echo '\tAllowOverride All'; \
echo '</Directory>'; \
} | tee "$APACHE_CONFDIR/conf-available/docker-php.conf" \
&& a2enconf docker-php
ENV PHP_EXTRA_BUILD_DEPS apache2-dev
ENV PHP_EXTRA_CONFIGURE_ARGS --with-apxs2 --disable-cgi
##</autogenerated>##
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# Adds GNU HASH segments to generated executables (this is used if present, and is much faster than sysv hash; in this configuration, sysv hash is also generated)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -Wl,--hash-style=both -pie"
ENV GPG_KEYS A917B1ECDA84AEC2B568FED6F50ABC807BD5DCD0 528995BFEDFBA7191D46839EF9BA0ADA31CBD89E 1729F83938DA44E27BA0F4D3DBDB397470D12172
ENV PHP_VERSION 7.1.33
# chialab: the php.net mirror redirector is gone.
ENV PHP_URL="https://www.php.net/distributions/php-7.1.33.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.1.33.tar.xz.asc"
ENV PHP_SHA256="bd7c0a9bd5433289ee01fd440af3715309faf583f75832b64fe169c100d52968" PHP_MD5=""
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends gnupg dirmngr; \
rm -rf /var/lib/apt/lists/*; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
if [ -n "$PHP_MD5" ]; then \
echo "$PHP_MD5 *php.tar.xz" | md5sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
# chialab: the SKS keyserver pool is gone.
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.1,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
libcurl4-openssl-dev \
libedit-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
zlib1g-dev \
${PHP_EXTRA_BUILD_DEPS:-} \
; \
rm -rf /var/lib/apt/lists/*; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors intead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-libedit \
--with-openssl \
--with-zlib \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/stretch/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
${PHP_EXTRA_CONFIGURE_ARGS:-} \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find /usr/local/bin /usr/local/sbin -type f -executable -exec strip --strip-all '{}' + || true; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/5.6 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.1 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.1 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/apache /usr/local/bin/docker-php-entrypoint
# temporary "freetype-config" workaround for https://github.com/docker-library/php/issues/865 (https://bugs.php.net/bug.php?id=76324)
RUN { echo '#!/bin/sh'; echo 'exec pkg-config "$@" freetype2'; } > /usr/local/bin/freetype-config && chmod +x /usr/local/bin/freetype-config
ENTRYPOINT ["docker-php-entrypoint"]
##<autogenerated>##
# https://httpd.apache.org/docs/2.4/stopping.html#gracefulstop
STOPSIGNAL SIGWINCH
# chialab: from eol/scripts.
COPY --from=scripts apache2-foreground /usr/local/bin/
WORKDIR /var/www/html
EXPOSE 80
CMD ["apache2-foreground"]
##</autogenerated>##
+226
View File
@@ -0,0 +1,226 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/2bf33a859340cf4932a7bce5ae7bc935fc778b9d/7.1/buster/cli),
# with the changes marked "chialab:".
#
FROM debian:buster-slim
# chialab: Debian buster has been moved to archive.debian.org.
RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/buster-updates/d' /etc/apt/sources.list
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
; \
rm -rf /var/lib/apt/lists/*
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
##<autogenerated>##
##</autogenerated>##
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# Adds GNU HASH segments to generated executables (this is used if present, and is much faster than sysv hash; in this configuration, sysv hash is also generated)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -Wl,--hash-style=both -pie"
ENV GPG_KEYS A917B1ECDA84AEC2B568FED6F50ABC807BD5DCD0 528995BFEDFBA7191D46839EF9BA0ADA31CBD89E 1729F83938DA44E27BA0F4D3DBDB397470D12172
ENV PHP_VERSION 7.1.33
# chialab: the php.net mirror redirector is gone.
ENV PHP_URL="https://www.php.net/distributions/php-7.1.33.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.1.33.tar.xz.asc"
ENV PHP_SHA256="bd7c0a9bd5433289ee01fd440af3715309faf583f75832b64fe169c100d52968" PHP_MD5=""
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends gnupg dirmngr; \
rm -rf /var/lib/apt/lists/*; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
if [ -n "$PHP_MD5" ]; then \
echo "$PHP_MD5 *php.tar.xz" | md5sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
# chialab: the SKS keyserver pool is gone.
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.1,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
libcurl4-openssl-dev \
libedit-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
zlib1g-dev \
${PHP_EXTRA_BUILD_DEPS:-} \
; \
rm -rf /var/lib/apt/lists/*; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors intead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-libedit \
--with-openssl \
--with-zlib \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/stretch/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
${PHP_EXTRA_CONFIGURE_ARGS:-} \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find /usr/local/bin /usr/local/sbin -type f -executable -exec strip --strip-all '{}' + || true; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/5.6 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.1 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.1 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/cli /usr/local/bin/docker-php-entrypoint
# temporary "freetype-config" workaround for https://github.com/docker-library/php/issues/865 (https://bugs.php.net/bug.php?id=76324)
RUN { echo '#!/bin/sh'; echo 'exec pkg-config "$@" freetype2'; } > /usr/local/bin/freetype-config && chmod +x /usr/local/bin/freetype-config
ENTRYPOINT ["docker-php-entrypoint"]
##<autogenerated>##
CMD ["php", "-a"]
##</autogenerated>##
+241
View File
@@ -0,0 +1,241 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/2bf33a859340cf4932a7bce5ae7bc935fc778b9d/7.1/alpine3.10/fpm),
# with the changes marked "chialab:".
#
FROM alpine:3.10
# dependencies required for running "phpize"
# these get automatically installed and removed by "docker-php-ext-*" (unless they're already installed)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev dpkg \
file \
g++ \
gcc \
libc-dev \
make \
pkgconf \
re2c
# persistent / runtime deps
RUN apk add --no-cache \
ca-certificates \
curl \
tar \
xz \
# https://github.com/docker-library/php/issues/494
openssl
# ensure www-data user exists
RUN set -eux; \
addgroup -g 82 -S www-data; \
adduser -u 82 -D -S -G www-data www-data
# 82 is the standard uid/gid for "www-data" in Alpine
# https://git.alpinelinux.org/aports/tree/main/apache2/apache2.pre-install?h=3.9-stable
# https://git.alpinelinux.org/aports/tree/main/lighttpd/lighttpd.pre-install?h=3.9-stable
# https://git.alpinelinux.org/aports/tree/main/nginx/nginx.pre-install?h=3.9-stable
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
##<autogenerated>##
ENV PHP_EXTRA_CONFIGURE_ARGS --enable-fpm --with-fpm-user=www-data --with-fpm-group=www-data --disable-cgi
##</autogenerated>##
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# Adds GNU HASH segments to generated executables (this is used if present, and is much faster than sysv hash; in this configuration, sysv hash is also generated)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -Wl,--hash-style=both -pie"
ENV GPG_KEYS A917B1ECDA84AEC2B568FED6F50ABC807BD5DCD0 528995BFEDFBA7191D46839EF9BA0ADA31CBD89E 1729F83938DA44E27BA0F4D3DBDB397470D12172
ENV PHP_VERSION 7.1.33
# chialab: the php.net mirror redirector is gone.
ENV PHP_URL="https://www.php.net/distributions/php-7.1.33.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.1.33.tar.xz.asc"
ENV PHP_SHA256="bd7c0a9bd5433289ee01fd440af3715309faf583f75832b64fe169c100d52968" PHP_MD5=""
RUN set -eux; \
\
apk add --no-cache --virtual .fetch-deps gnupg; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
if [ -n "$PHP_MD5" ]; then \
echo "$PHP_MD5 *php.tar.xz" | md5sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
# chialab: the SKS keyserver pool is gone.
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apk del --no-network .fetch-deps
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.1,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
coreutils \
curl-dev \
libedit-dev \
libxml2-dev \
openssl-dev \
sqlite-dev \
; \
\
export CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors intead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-libedit \
--with-openssl \
--with-zlib \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/stretch/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-musl' && echo '--without-pcre-jit') \
\
${PHP_EXTRA_CONFIGURE_ARGS:-} \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find /usr/local/bin /usr/local/sbin -type f -perm +0111 -exec strip --strip-all '{}' + || true; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)"; \
apk add --no-cache $runDeps; \
\
apk del --no-network .build-deps; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/5.6 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.1 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.1 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/fpm /usr/local/bin/docker-php-entrypoint
ENTRYPOINT ["docker-php-entrypoint"]
##<autogenerated>##
WORKDIR /var/www/html
RUN set -eux; \
cd /usr/local/etc; \
if [ -d php-fpm.d ]; then \
# for some reason, upstream's php-fpm.conf.default has "include=NONE/etc/php-fpm.d/*.conf"
sed 's!=NONE/!=!g' php-fpm.conf.default | tee php-fpm.conf > /dev/null; \
cp php-fpm.d/www.conf.default php-fpm.d/www.conf; \
else \
# PHP 5.x doesn't use "include=" by default, so we'll create our own simple config that mimics PHP 7+ for consistency
mkdir php-fpm.d; \
cp php-fpm.conf.default php-fpm.d/www.conf; \
{ \
echo '[global]'; \
echo 'include=etc/php-fpm.d/*.conf'; \
} | tee php-fpm.conf; \
fi; \
{ \
echo '[global]'; \
echo 'error_log = /proc/self/fd/2'; \
echo; \
echo '[www]'; \
echo '; if we send this to /proc/self/fd/1, it never appears'; \
echo 'access.log = /proc/self/fd/2'; \
echo; \
echo 'clear_env = no'; \
echo; \
echo '; Ensure worker stdout and stderr are sent to the main error log.'; \
echo 'catch_workers_output = yes'; \
} | tee php-fpm.d/docker.conf; \
{ \
echo '[global]'; \
echo 'daemonize = no'; \
echo; \
echo '[www]'; \
echo 'listen = 9000'; \
} | tee php-fpm.d/zz-docker.conf
# Override stop signal to stop process gracefully
# https://github.com/php/php-src/blob/17baa87faddc2550def3ae7314236826bc1b1398/sapi/fpm/php-fpm.8.in#L163
STOPSIGNAL SIGQUIT
EXPOSE 9000
CMD ["php-fpm"]
##</autogenerated>##
+270
View File
@@ -0,0 +1,270 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/2bf33a859340cf4932a7bce5ae7bc935fc778b9d/7.1/buster/fpm),
# with the changes marked "chialab:".
#
FROM debian:buster-slim
# chialab: Debian buster has been moved to archive.debian.org.
RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/buster-updates/d' /etc/apt/sources.list
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
; \
rm -rf /var/lib/apt/lists/*
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
##<autogenerated>##
ENV PHP_EXTRA_CONFIGURE_ARGS --enable-fpm --with-fpm-user=www-data --with-fpm-group=www-data --disable-cgi
##</autogenerated>##
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# Adds GNU HASH segments to generated executables (this is used if present, and is much faster than sysv hash; in this configuration, sysv hash is also generated)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -Wl,--hash-style=both -pie"
ENV GPG_KEYS A917B1ECDA84AEC2B568FED6F50ABC807BD5DCD0 528995BFEDFBA7191D46839EF9BA0ADA31CBD89E 1729F83938DA44E27BA0F4D3DBDB397470D12172
ENV PHP_VERSION 7.1.33
# chialab: the php.net mirror redirector is gone.
ENV PHP_URL="https://www.php.net/distributions/php-7.1.33.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.1.33.tar.xz.asc"
ENV PHP_SHA256="bd7c0a9bd5433289ee01fd440af3715309faf583f75832b64fe169c100d52968" PHP_MD5=""
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends gnupg dirmngr; \
rm -rf /var/lib/apt/lists/*; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
if [ -n "$PHP_MD5" ]; then \
echo "$PHP_MD5 *php.tar.xz" | md5sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
# chialab: the SKS keyserver pool is gone.
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.1,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
libcurl4-openssl-dev \
libedit-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
zlib1g-dev \
${PHP_EXTRA_BUILD_DEPS:-} \
; \
rm -rf /var/lib/apt/lists/*; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors intead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-libedit \
--with-openssl \
--with-zlib \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/stretch/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
${PHP_EXTRA_CONFIGURE_ARGS:-} \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find /usr/local/bin /usr/local/sbin -type f -executable -exec strip --strip-all '{}' + || true; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/5.6 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.1 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.1 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/fpm /usr/local/bin/docker-php-entrypoint
# temporary "freetype-config" workaround for https://github.com/docker-library/php/issues/865 (https://bugs.php.net/bug.php?id=76324)
RUN { echo '#!/bin/sh'; echo 'exec pkg-config "$@" freetype2'; } > /usr/local/bin/freetype-config && chmod +x /usr/local/bin/freetype-config
ENTRYPOINT ["docker-php-entrypoint"]
##<autogenerated>##
WORKDIR /var/www/html
RUN set -eux; \
cd /usr/local/etc; \
if [ -d php-fpm.d ]; then \
# for some reason, upstream's php-fpm.conf.default has "include=NONE/etc/php-fpm.d/*.conf"
sed 's!=NONE/!=!g' php-fpm.conf.default | tee php-fpm.conf > /dev/null; \
cp php-fpm.d/www.conf.default php-fpm.d/www.conf; \
else \
# PHP 5.x doesn't use "include=" by default, so we'll create our own simple config that mimics PHP 7+ for consistency
mkdir php-fpm.d; \
cp php-fpm.conf.default php-fpm.d/www.conf; \
{ \
echo '[global]'; \
echo 'include=etc/php-fpm.d/*.conf'; \
} | tee php-fpm.conf; \
fi; \
{ \
echo '[global]'; \
echo 'error_log = /proc/self/fd/2'; \
echo; \
echo '[www]'; \
echo '; if we send this to /proc/self/fd/1, it never appears'; \
echo 'access.log = /proc/self/fd/2'; \
echo; \
echo 'clear_env = no'; \
echo; \
echo '; Ensure worker stdout and stderr are sent to the main error log.'; \
echo 'catch_workers_output = yes'; \
} | tee php-fpm.d/docker.conf; \
{ \
echo '[global]'; \
echo 'daemonize = no'; \
echo; \
echo '[www]'; \
echo 'listen = 9000'; \
} | tee php-fpm.d/zz-docker.conf
# Override stop signal to stop process gracefully
# https://github.com/php/php-src/blob/17baa87faddc2550def3ae7314236826bc1b1398/sapi/fpm/php-fpm.8.in#L163
STOPSIGNAL SIGQUIT
EXPOSE 9000
CMD ["php-fpm"]
##</autogenerated>##
+200
View File
@@ -0,0 +1,200 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/20ebff40bb865416f3767540df06ad1df384337d/7.2/alpine3.12/cli),
# with the changes marked "chialab:".
#
FROM alpine:3.12
# dependencies required for running "phpize"
# these get automatically installed and removed by "docker-php-ext-*" (unless they're already installed)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev dpkg \
file \
g++ \
gcc \
libc-dev \
make \
pkgconf \
re2c
# persistent / runtime deps
RUN apk add --no-cache \
ca-certificates \
curl \
tar \
xz \
# https://github.com/docker-library/php/issues/494
openssl
# ensure www-data user exists
RUN set -eux; \
addgroup -g 82 -S www-data; \
adduser -u 82 -D -S -G www-data www-data
# 82 is the standard uid/gid for "www-data" in Alpine
# https://git.alpinelinux.org/aports/tree/main/apache2/apache2.pre-install?h=3.9-stable
# https://git.alpinelinux.org/aports/tree/main/lighttpd/lighttpd.pre-install?h=3.9-stable
# https://git.alpinelinux.org/aports/tree/main/nginx/nginx.pre-install?h=3.9-stable
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS 1729F83938DA44E27BA0F4D3DBDB397470D12172 B1B44D8F021E4E2D6021E995DC9FF8D3EE5AF27F
ENV PHP_VERSION 7.2.34
ENV PHP_URL="https://www.php.net/distributions/php-7.2.34.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.2.34.tar.xz.asc"
ENV PHP_SHA256="409e11bc6a2c18707dfc44bc61c820ddfd81e17481470f3405ee7822d8379903"
RUN set -eux; \
\
apk add --no-cache --virtual .fetch-deps gnupg; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
# chialab: the SKS keyserver pool is gone.
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apk del --no-network .fetch-deps
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.2,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
argon2-dev \
coreutils \
curl-dev \
libedit-dev \
libsodium-dev \
libxml2-dev \
openssl-dev \
sqlite-dev \
; \
\
export CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash (7.2+)
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-libedit \
--with-openssl \
--with-zlib \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/stretch/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-musl' && echo '--without-pcre-jit') \
\
${PHP_EXTRA_CONFIGURE_ARGS:-} \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find /usr/local/bin /usr/local/sbin -type f -perm +0111 -exec strip --strip-all '{}' + || true; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)"; \
apk add --no-cache $runDeps; \
\
apk del --no-network .build-deps; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.2 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.2 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/cli /usr/local/bin/docker-php-entrypoint
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
ENTRYPOINT ["docker-php-entrypoint"]
CMD ["php", "-a"]
+298
View File
@@ -0,0 +1,298 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/20ebff40bb865416f3767540df06ad1df384337d/7.2/buster/apache),
# with the changes marked "chialab:".
#
FROM debian:buster-slim
# chialab: Debian buster has been moved to archive.debian.org.
RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/buster-updates/d' /etc/apt/sources.list
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
; \
rm -rf /var/lib/apt/lists/*
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
ENV APACHE_CONFDIR /etc/apache2
ENV APACHE_ENVVARS $APACHE_CONFDIR/envvars
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends apache2; \
rm -rf /var/lib/apt/lists/*; \
\
# generically convert lines like
# export APACHE_RUN_USER=www-data
# into
# : ${APACHE_RUN_USER:=www-data}
# export APACHE_RUN_USER
# so that they can be overridden at runtime ("-e APACHE_RUN_USER=...")
sed -ri 's/^export ([^=]+)=(.*)$/: ${\1:=\2}\nexport \1/' "$APACHE_ENVVARS"; \
\
# setup directories and permissions
. "$APACHE_ENVVARS"; \
for dir in \
"$APACHE_LOCK_DIR" \
"$APACHE_RUN_DIR" \
"$APACHE_LOG_DIR" \
; do \
rm -rvf "$dir"; \
mkdir -p "$dir"; \
chown "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$dir"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
chmod 777 "$dir"; \
done; \
\
# delete the "index.html" that installing Apache drops in here
rm -rvf /var/www/html/*; \
\
# logs should go to stdout / stderr
ln -sfT /dev/stderr "$APACHE_LOG_DIR/error.log"; \
ln -sfT /dev/stdout "$APACHE_LOG_DIR/access.log"; \
ln -sfT /dev/stdout "$APACHE_LOG_DIR/other_vhosts_access.log"; \
chown -R --no-dereference "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$APACHE_LOG_DIR"
# Apache + PHP requires preforking Apache for best results
RUN a2dismod mpm_event && a2enmod mpm_prefork
# PHP files should be handled by PHP, and should be preferred over any other file type
RUN { \
echo '<FilesMatch \.php$>'; \
echo '\tSetHandler application/x-httpd-php'; \
echo '</FilesMatch>'; \
echo; \
echo 'DirectoryIndex disabled'; \
echo 'DirectoryIndex index.php index.html'; \
echo; \
echo '<Directory /var/www/>'; \
echo '\tOptions -Indexes'; \
echo '\tAllowOverride All'; \
echo '</Directory>'; \
} | tee "$APACHE_CONFDIR/conf-available/docker-php.conf" \
&& a2enconf docker-php
ENV PHP_EXTRA_BUILD_DEPS apache2-dev
ENV PHP_EXTRA_CONFIGURE_ARGS --with-apxs2 --disable-cgi
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS 1729F83938DA44E27BA0F4D3DBDB397470D12172 B1B44D8F021E4E2D6021E995DC9FF8D3EE5AF27F
ENV PHP_VERSION 7.2.34
ENV PHP_URL="https://www.php.net/distributions/php-7.2.34.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.2.34.tar.xz.asc"
ENV PHP_SHA256="409e11bc6a2c18707dfc44bc61c820ddfd81e17481470f3405ee7822d8379903"
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends gnupg dirmngr; \
rm -rf /var/lib/apt/lists/*; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
# chialab: the SKS keyserver pool is gone.
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.2,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
libargon2-dev \
libcurl4-openssl-dev \
libedit-dev \
libsodium-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
zlib1g-dev \
${PHP_EXTRA_BUILD_DEPS:-} \
; \
rm -rf /var/lib/apt/lists/*; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash (7.2+)
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-libedit \
--with-openssl \
--with-zlib \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/stretch/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
${PHP_EXTRA_CONFIGURE_ARGS:-} \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find /usr/local/bin /usr/local/sbin -type f -executable -exec strip --strip-all '{}' + || true; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.2 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.2 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/apache /usr/local/bin/docker-php-entrypoint
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
# temporary "freetype-config" workaround for https://github.com/docker-library/php/issues/865 (https://bugs.php.net/bug.php?id=76324)
RUN { echo '#!/bin/sh'; echo 'exec pkg-config "$@" freetype2'; } > /usr/local/bin/freetype-config && chmod +x /usr/local/bin/freetype-config
ENTRYPOINT ["docker-php-entrypoint"]
# https://httpd.apache.org/docs/2.4/stopping.html#gracefulstop
STOPSIGNAL SIGWINCH
# chialab: from eol/scripts.
COPY --from=scripts apache2-foreground /usr/local/bin/
WORKDIR /var/www/html
EXPOSE 80
CMD ["apache2-foreground"]
+229
View File
@@ -0,0 +1,229 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/20ebff40bb865416f3767540df06ad1df384337d/7.2/buster/cli),
# with the changes marked "chialab:".
#
FROM debian:buster-slim
# chialab: Debian buster has been moved to archive.debian.org.
RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/buster-updates/d' /etc/apt/sources.list
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
; \
rm -rf /var/lib/apt/lists/*
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS 1729F83938DA44E27BA0F4D3DBDB397470D12172 B1B44D8F021E4E2D6021E995DC9FF8D3EE5AF27F
ENV PHP_VERSION 7.2.34
ENV PHP_URL="https://www.php.net/distributions/php-7.2.34.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.2.34.tar.xz.asc"
ENV PHP_SHA256="409e11bc6a2c18707dfc44bc61c820ddfd81e17481470f3405ee7822d8379903"
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends gnupg dirmngr; \
rm -rf /var/lib/apt/lists/*; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
# chialab: the SKS keyserver pool is gone.
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.2,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
libargon2-dev \
libcurl4-openssl-dev \
libedit-dev \
libsodium-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
zlib1g-dev \
${PHP_EXTRA_BUILD_DEPS:-} \
; \
rm -rf /var/lib/apt/lists/*; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash (7.2+)
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-libedit \
--with-openssl \
--with-zlib \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/stretch/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
${PHP_EXTRA_CONFIGURE_ARGS:-} \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find /usr/local/bin /usr/local/sbin -type f -executable -exec strip --strip-all '{}' + || true; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.2 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.2 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/cli /usr/local/bin/docker-php-entrypoint
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
# temporary "freetype-config" workaround for https://github.com/docker-library/php/issues/865 (https://bugs.php.net/bug.php?id=76324)
RUN { echo '#!/bin/sh'; echo 'exec pkg-config "$@" freetype2'; } > /usr/local/bin/freetype-config && chmod +x /usr/local/bin/freetype-config
ENTRYPOINT ["docker-php-entrypoint"]
CMD ["php", "-a"]
+245
View File
@@ -0,0 +1,245 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/20ebff40bb865416f3767540df06ad1df384337d/7.2/alpine3.12/fpm),
# with the changes marked "chialab:".
#
FROM alpine:3.12
# dependencies required for running "phpize"
# these get automatically installed and removed by "docker-php-ext-*" (unless they're already installed)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev dpkg \
file \
g++ \
gcc \
libc-dev \
make \
pkgconf \
re2c
# persistent / runtime deps
RUN apk add --no-cache \
ca-certificates \
curl \
tar \
xz \
# https://github.com/docker-library/php/issues/494
openssl
# ensure www-data user exists
RUN set -eux; \
addgroup -g 82 -S www-data; \
adduser -u 82 -D -S -G www-data www-data
# 82 is the standard uid/gid for "www-data" in Alpine
# https://git.alpinelinux.org/aports/tree/main/apache2/apache2.pre-install?h=3.9-stable
# https://git.alpinelinux.org/aports/tree/main/lighttpd/lighttpd.pre-install?h=3.9-stable
# https://git.alpinelinux.org/aports/tree/main/nginx/nginx.pre-install?h=3.9-stable
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
ENV PHP_EXTRA_CONFIGURE_ARGS --enable-fpm --with-fpm-user=www-data --with-fpm-group=www-data --disable-cgi
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS 1729F83938DA44E27BA0F4D3DBDB397470D12172 B1B44D8F021E4E2D6021E995DC9FF8D3EE5AF27F
ENV PHP_VERSION 7.2.34
ENV PHP_URL="https://www.php.net/distributions/php-7.2.34.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.2.34.tar.xz.asc"
ENV PHP_SHA256="409e11bc6a2c18707dfc44bc61c820ddfd81e17481470f3405ee7822d8379903"
RUN set -eux; \
\
apk add --no-cache --virtual .fetch-deps gnupg; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
# chialab: the SKS keyserver pool is gone.
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apk del --no-network .fetch-deps
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.2,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
argon2-dev \
coreutils \
curl-dev \
libedit-dev \
libsodium-dev \
libxml2-dev \
openssl-dev \
sqlite-dev \
; \
\
export CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash (7.2+)
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-libedit \
--with-openssl \
--with-zlib \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/stretch/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-musl' && echo '--without-pcre-jit') \
\
${PHP_EXTRA_CONFIGURE_ARGS:-} \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find /usr/local/bin /usr/local/sbin -type f -perm +0111 -exec strip --strip-all '{}' + || true; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)"; \
apk add --no-cache $runDeps; \
\
apk del --no-network .build-deps; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.2 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.2 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/fpm /usr/local/bin/docker-php-entrypoint
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
ENTRYPOINT ["docker-php-entrypoint"]
WORKDIR /var/www/html
RUN set -eux; \
cd /usr/local/etc; \
if [ -d php-fpm.d ]; then \
# for some reason, upstream's php-fpm.conf.default has "include=NONE/etc/php-fpm.d/*.conf"
sed 's!=NONE/!=!g' php-fpm.conf.default | tee php-fpm.conf > /dev/null; \
cp php-fpm.d/www.conf.default php-fpm.d/www.conf; \
else \
# PHP 5.x doesn't use "include=" by default, so we'll create our own simple config that mimics PHP 7+ for consistency
mkdir php-fpm.d; \
cp php-fpm.conf.default php-fpm.d/www.conf; \
{ \
echo '[global]'; \
echo 'include=etc/php-fpm.d/*.conf'; \
} | tee php-fpm.conf; \
fi; \
{ \
echo '[global]'; \
echo 'error_log = /proc/self/fd/2'; \
echo; \
echo '[www]'; \
echo '; if we send this to /proc/self/fd/1, it never appears'; \
echo 'access.log = /proc/self/fd/2'; \
echo; \
echo 'clear_env = no'; \
echo; \
echo '; Ensure worker stdout and stderr are sent to the main error log.'; \
echo 'catch_workers_output = yes'; \
} | tee php-fpm.d/docker.conf; \
{ \
echo '[global]'; \
echo 'daemonize = no'; \
echo; \
echo '[www]'; \
echo 'listen = 9000'; \
} | tee php-fpm.d/zz-docker.conf
# Override stop signal to stop process gracefully
# https://github.com/php/php-src/blob/17baa87faddc2550def3ae7314236826bc1b1398/sapi/fpm/php-fpm.8.in#L163
STOPSIGNAL SIGQUIT
EXPOSE 9000
CMD ["php-fpm"]
+274
View File
@@ -0,0 +1,274 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/20ebff40bb865416f3767540df06ad1df384337d/7.2/buster/fpm),
# with the changes marked "chialab:".
#
FROM debian:buster-slim
# chialab: Debian buster has been moved to archive.debian.org.
RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/buster-updates/d' /etc/apt/sources.list
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
; \
rm -rf /var/lib/apt/lists/*
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
ENV PHP_EXTRA_CONFIGURE_ARGS --enable-fpm --with-fpm-user=www-data --with-fpm-group=www-data --disable-cgi
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS 1729F83938DA44E27BA0F4D3DBDB397470D12172 B1B44D8F021E4E2D6021E995DC9FF8D3EE5AF27F
ENV PHP_VERSION 7.2.34
ENV PHP_URL="https://www.php.net/distributions/php-7.2.34.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.2.34.tar.xz.asc"
ENV PHP_SHA256="409e11bc6a2c18707dfc44bc61c820ddfd81e17481470f3405ee7822d8379903"
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends gnupg dirmngr; \
rm -rf /var/lib/apt/lists/*; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
# chialab: the SKS keyserver pool is gone.
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.2,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
libargon2-dev \
libcurl4-openssl-dev \
libedit-dev \
libsodium-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
zlib1g-dev \
${PHP_EXTRA_BUILD_DEPS:-} \
; \
rm -rf /var/lib/apt/lists/*; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash (7.2+)
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-libedit \
--with-openssl \
--with-zlib \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/stretch/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
${PHP_EXTRA_CONFIGURE_ARGS:-} \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find /usr/local/bin /usr/local/sbin -type f -executable -exec strip --strip-all '{}' + || true; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.2 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.2 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/fpm /usr/local/bin/docker-php-entrypoint
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
# temporary "freetype-config" workaround for https://github.com/docker-library/php/issues/865 (https://bugs.php.net/bug.php?id=76324)
RUN { echo '#!/bin/sh'; echo 'exec pkg-config "$@" freetype2'; } > /usr/local/bin/freetype-config && chmod +x /usr/local/bin/freetype-config
ENTRYPOINT ["docker-php-entrypoint"]
WORKDIR /var/www/html
RUN set -eux; \
cd /usr/local/etc; \
if [ -d php-fpm.d ]; then \
# for some reason, upstream's php-fpm.conf.default has "include=NONE/etc/php-fpm.d/*.conf"
sed 's!=NONE/!=!g' php-fpm.conf.default | tee php-fpm.conf > /dev/null; \
cp php-fpm.d/www.conf.default php-fpm.d/www.conf; \
else \
# PHP 5.x doesn't use "include=" by default, so we'll create our own simple config that mimics PHP 7+ for consistency
mkdir php-fpm.d; \
cp php-fpm.conf.default php-fpm.d/www.conf; \
{ \
echo '[global]'; \
echo 'include=etc/php-fpm.d/*.conf'; \
} | tee php-fpm.conf; \
fi; \
{ \
echo '[global]'; \
echo 'error_log = /proc/self/fd/2'; \
echo; \
echo '[www]'; \
echo '; if we send this to /proc/self/fd/1, it never appears'; \
echo 'access.log = /proc/self/fd/2'; \
echo; \
echo 'clear_env = no'; \
echo; \
echo '; Ensure worker stdout and stderr are sent to the main error log.'; \
echo 'catch_workers_output = yes'; \
} | tee php-fpm.d/docker.conf; \
{ \
echo '[global]'; \
echo 'daemonize = no'; \
echo; \
echo '[www]'; \
echo 'listen = 9000'; \
} | tee php-fpm.d/zz-docker.conf
# Override stop signal to stop process gracefully
# https://github.com/php/php-src/blob/17baa87faddc2550def3ae7314236826bc1b1398/sapi/fpm/php-fpm.8.in#L163
STOPSIGNAL SIGQUIT
EXPOSE 9000
CMD ["php-fpm"]
+215
View File
@@ -0,0 +1,215 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/35d0a696b273c31f41ae224f189c19e794df91ae/7.3/alpine3.15/cli),
# with the changes marked "chialab:".
#
FROM alpine:3.15
# dependencies required for running "phpize"
# these get automatically installed and removed by "docker-php-ext-*" (unless they're already installed)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev dpkg \
file \
g++ \
gcc \
libc-dev \
make \
pkgconf \
re2c
# persistent / runtime deps
RUN apk add --no-cache \
ca-certificates \
curl \
tar \
xz \
# https://github.com/docker-library/php/issues/494
openssl
# ensure www-data user exists
RUN set -eux; \
adduser -u 82 -D -S -G www-data www-data
# 82 is the standard uid/gid for "www-data" in Alpine
# https://git.alpinelinux.org/aports/tree/main/apache2/apache2.pre-install?h=3.14-stable
# https://git.alpinelinux.org/aports/tree/main/lighttpd/lighttpd.pre-install?h=3.14-stable
# https://git.alpinelinux.org/aports/tree/main/nginx/nginx.pre-install?h=3.14-stable
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS CBAF69F173A0FEA4B537F470D66C9593118BCCB6 F38252826ACD957EF380D39F2F7956BC5DA04B5D
ENV PHP_VERSION 7.3.33
ENV PHP_URL="https://www.php.net/distributions/php-7.3.33.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.3.33.tar.xz.asc"
ENV PHP_SHA256="166eaccde933381da9516a2b70ad0f447d7cec4b603d07b9a916032b215b90cc"
RUN set -eux; \
\
apk add --no-cache --virtual .fetch-deps gnupg; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apk del --no-network .fetch-deps
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.3,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
argon2-dev \
coreutils \
curl-dev \
gnu-libiconv-dev \
libsodium-dev \
libxml2-dev \
openssl-dev \
readline-dev \
sqlite-dev \
; \
\
# make sure musl's iconv doesn't get used (https://www.php.net/manual/en/intro.iconv.php)
rm -vf /usr/include/iconv.h; \
# PHP < 8 doesn't know to look deeper for GNU libiconv: https://github.com/php/php-src/commit/b480e6841ecd5317faa136647a2b8253a4c2d0df
ln -sv /usr/include/gnu-libiconv/*.h /usr/include/; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-iconv=/usr \
--with-openssl \
--with-readline \
--with-zlib \
\
# https://github.com/docker-library/php/pull/1259
--enable-phpdbg \
--enable-phpdbg-readline \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/bullseye/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-musl' && echo '--without-pcre-jit') \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find \
/usr/local \
-type f \
-perm '/0111' \
-exec sh -euxc ' \
strip --strip-all "$@" || : \
' -- '{}' + \
; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)"; \
apk add --no-cache $runDeps; \
\
apk del --no-network .build-deps; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.3 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.3 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/cli /usr/local/bin/docker-php-entrypoint
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
ENTRYPOINT ["docker-php-entrypoint"]
CMD ["php", "-a"]
+307
View File
@@ -0,0 +1,307 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/35d0a696b273c31f41ae224f189c19e794df91ae/7.3/bullseye/apache),
# with the changes marked "chialab:".
#
FROM debian:bullseye-slim
# chialab: Debian bullseye has been moved to archive.debian.org.
RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/bullseye-updates/d' /etc/apt/sources.list
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
; \
rm -rf /var/lib/apt/lists/*
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
ENV APACHE_CONFDIR /etc/apache2
ENV APACHE_ENVVARS $APACHE_CONFDIR/envvars
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends apache2; \
rm -rf /var/lib/apt/lists/*; \
\
# generically convert lines like
# export APACHE_RUN_USER=www-data
# into
# : ${APACHE_RUN_USER:=www-data}
# export APACHE_RUN_USER
# so that they can be overridden at runtime ("-e APACHE_RUN_USER=...")
sed -ri 's/^export ([^=]+)=(.*)$/: ${\1:=\2}\nexport \1/' "$APACHE_ENVVARS"; \
\
# setup directories and permissions
. "$APACHE_ENVVARS"; \
for dir in \
"$APACHE_LOCK_DIR" \
"$APACHE_RUN_DIR" \
"$APACHE_LOG_DIR" \
; do \
rm -rvf "$dir"; \
mkdir -p "$dir"; \
chown "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$dir"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
chmod 777 "$dir"; \
done; \
\
# delete the "index.html" that installing Apache drops in here
rm -rvf /var/www/html/*; \
\
# logs should go to stdout / stderr
ln -sfT /dev/stderr "$APACHE_LOG_DIR/error.log"; \
ln -sfT /dev/stdout "$APACHE_LOG_DIR/access.log"; \
ln -sfT /dev/stdout "$APACHE_LOG_DIR/other_vhosts_access.log"; \
chown -R --no-dereference "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$APACHE_LOG_DIR"
# Apache + PHP requires preforking Apache for best results
RUN a2dismod mpm_event && a2enmod mpm_prefork
# PHP files should be handled by PHP, and should be preferred over any other file type
RUN { \
echo '<FilesMatch \.php$>'; \
echo '\tSetHandler application/x-httpd-php'; \
echo '</FilesMatch>'; \
echo; \
echo 'DirectoryIndex disabled'; \
echo 'DirectoryIndex index.php index.html'; \
echo; \
echo '<Directory /var/www/>'; \
echo '\tOptions -Indexes'; \
echo '\tAllowOverride All'; \
echo '</Directory>'; \
} | tee "$APACHE_CONFDIR/conf-available/docker-php.conf" \
&& a2enconf docker-php
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS CBAF69F173A0FEA4B537F470D66C9593118BCCB6 F38252826ACD957EF380D39F2F7956BC5DA04B5D
ENV PHP_VERSION 7.3.33
ENV PHP_URL="https://www.php.net/distributions/php-7.3.33.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.3.33.tar.xz.asc"
ENV PHP_SHA256="166eaccde933381da9516a2b70ad0f447d7cec4b603d07b9a916032b215b90cc"
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends gnupg dirmngr; \
rm -rf /var/lib/apt/lists/*; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.3,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
apache2-dev \
libargon2-dev \
libcurl4-openssl-dev \
libreadline-dev \
libsodium-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
zlib1g-dev \
; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-iconv \
--with-openssl \
--with-readline \
--with-zlib \
\
# https://github.com/bwoebi/phpdbg-docs/issues/1#issuecomment-163872806 ("phpdbg is primarily a CLI debugger, and is not suitable for debugging an fpm stack.")
--disable-phpdbg \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/bullseye/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
--disable-cgi \
\
--with-apxs2 \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find \
/usr/local \
-type f \
-perm '/0111' \
-exec sh -euxc ' \
strip --strip-all "$@" || : \
' -- '{}' + \
; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
rm -rf /var/lib/apt/lists/*; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.3 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.3 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/apache /usr/local/bin/docker-php-entrypoint
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
# temporary "freetype-config" workaround for https://github.com/docker-library/php/issues/865 (https://bugs.php.net/bug.php?id=76324)
RUN { echo '#!/bin/sh'; echo 'exec pkg-config "$@" freetype2'; } > /usr/local/bin/freetype-config && chmod +x /usr/local/bin/freetype-config
ENTRYPOINT ["docker-php-entrypoint"]
# https://httpd.apache.org/docs/2.4/stopping.html#gracefulstop
STOPSIGNAL SIGWINCH
# chialab: from eol/scripts.
COPY --from=scripts apache2-foreground /usr/local/bin/
WORKDIR /var/www/html
EXPOSE 80
CMD ["apache2-foreground"]
+240
View File
@@ -0,0 +1,240 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/35d0a696b273c31f41ae224f189c19e794df91ae/7.3/bullseye/cli),
# with the changes marked "chialab:".
#
FROM debian:bullseye-slim
# chialab: Debian bullseye has been moved to archive.debian.org.
RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/bullseye-updates/d' /etc/apt/sources.list
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
; \
rm -rf /var/lib/apt/lists/*
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS CBAF69F173A0FEA4B537F470D66C9593118BCCB6 F38252826ACD957EF380D39F2F7956BC5DA04B5D
ENV PHP_VERSION 7.3.33
ENV PHP_URL="https://www.php.net/distributions/php-7.3.33.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.3.33.tar.xz.asc"
ENV PHP_SHA256="166eaccde933381da9516a2b70ad0f447d7cec4b603d07b9a916032b215b90cc"
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends gnupg dirmngr; \
rm -rf /var/lib/apt/lists/*; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.3,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
libargon2-dev \
libcurl4-openssl-dev \
libreadline-dev \
libsodium-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
zlib1g-dev \
; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-iconv \
--with-openssl \
--with-readline \
--with-zlib \
\
# https://github.com/docker-library/php/pull/1259
--enable-phpdbg \
--enable-phpdbg-readline \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/bullseye/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
# https://github.com/docker-library/php/pull/939#issuecomment-730501748
--enable-embed \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find \
/usr/local \
-type f \
-perm '/0111' \
-exec sh -euxc ' \
strip --strip-all "$@" || : \
' -- '{}' + \
; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
rm -rf /var/lib/apt/lists/*; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.3 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.3 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/cli /usr/local/bin/docker-php-entrypoint
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
# temporary "freetype-config" workaround for https://github.com/docker-library/php/issues/865 (https://bugs.php.net/bug.php?id=76324)
RUN { echo '#!/bin/sh'; echo 'exec pkg-config "$@" freetype2'; } > /usr/local/bin/freetype-config && chmod +x /usr/local/bin/freetype-config
ENTRYPOINT ["docker-php-entrypoint"]
CMD ["php", "-a"]
+265
View File
@@ -0,0 +1,265 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/35d0a696b273c31f41ae224f189c19e794df91ae/7.3/alpine3.15/fpm),
# with the changes marked "chialab:".
#
FROM alpine:3.15
# dependencies required for running "phpize"
# these get automatically installed and removed by "docker-php-ext-*" (unless they're already installed)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev dpkg \
file \
g++ \
gcc \
libc-dev \
make \
pkgconf \
re2c
# persistent / runtime deps
RUN apk add --no-cache \
ca-certificates \
curl \
tar \
xz \
# https://github.com/docker-library/php/issues/494
openssl
# ensure www-data user exists
RUN set -eux; \
adduser -u 82 -D -S -G www-data www-data
# 82 is the standard uid/gid for "www-data" in Alpine
# https://git.alpinelinux.org/aports/tree/main/apache2/apache2.pre-install?h=3.14-stable
# https://git.alpinelinux.org/aports/tree/main/lighttpd/lighttpd.pre-install?h=3.14-stable
# https://git.alpinelinux.org/aports/tree/main/nginx/nginx.pre-install?h=3.14-stable
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS CBAF69F173A0FEA4B537F470D66C9593118BCCB6 F38252826ACD957EF380D39F2F7956BC5DA04B5D
ENV PHP_VERSION 7.3.33
ENV PHP_URL="https://www.php.net/distributions/php-7.3.33.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.3.33.tar.xz.asc"
ENV PHP_SHA256="166eaccde933381da9516a2b70ad0f447d7cec4b603d07b9a916032b215b90cc"
RUN set -eux; \
\
apk add --no-cache --virtual .fetch-deps gnupg; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apk del --no-network .fetch-deps
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.3,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
argon2-dev \
coreutils \
curl-dev \
gnu-libiconv-dev \
libsodium-dev \
libxml2-dev \
openssl-dev \
readline-dev \
sqlite-dev \
; \
\
# make sure musl's iconv doesn't get used (https://www.php.net/manual/en/intro.iconv.php)
rm -vf /usr/include/iconv.h; \
# PHP < 8 doesn't know to look deeper for GNU libiconv: https://github.com/php/php-src/commit/b480e6841ecd5317faa136647a2b8253a4c2d0df
ln -sv /usr/include/gnu-libiconv/*.h /usr/include/; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-iconv=/usr \
--with-openssl \
--with-readline \
--with-zlib \
\
# https://github.com/bwoebi/phpdbg-docs/issues/1#issuecomment-163872806 ("phpdbg is primarily a CLI debugger, and is not suitable for debugging an fpm stack.")
--disable-phpdbg \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/bullseye/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-musl' && echo '--without-pcre-jit') \
\
--disable-cgi \
\
--enable-fpm \
--with-fpm-user=www-data \
--with-fpm-group=www-data \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find \
/usr/local \
-type f \
-perm '/0111' \
-exec sh -euxc ' \
strip --strip-all "$@" || : \
' -- '{}' + \
; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)"; \
apk add --no-cache $runDeps; \
\
apk del --no-network .build-deps; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.3 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.3 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/fpm /usr/local/bin/docker-php-entrypoint
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
ENTRYPOINT ["docker-php-entrypoint"]
WORKDIR /var/www/html
RUN set -eux; \
cd /usr/local/etc; \
if [ -d php-fpm.d ]; then \
# for some reason, upstream's php-fpm.conf.default has "include=NONE/etc/php-fpm.d/*.conf"
sed 's!=NONE/!=!g' php-fpm.conf.default | tee php-fpm.conf > /dev/null; \
cp php-fpm.d/www.conf.default php-fpm.d/www.conf; \
else \
# PHP 5.x doesn't use "include=" by default, so we'll create our own simple config that mimics PHP 7+ for consistency
mkdir php-fpm.d; \
cp php-fpm.conf.default php-fpm.d/www.conf; \
{ \
echo '[global]'; \
echo 'include=etc/php-fpm.d/*.conf'; \
} | tee php-fpm.conf; \
fi; \
{ \
echo '[global]'; \
echo 'error_log = /proc/self/fd/2'; \
echo; echo '; https://github.com/docker-library/php/pull/725#issuecomment-443540114'; echo 'log_limit = 8192'; \
echo; \
echo '[www]'; \
echo '; if we send this to /proc/self/fd/1, it never appears'; \
echo 'access.log = /proc/self/fd/2'; \
echo; \
echo 'clear_env = no'; \
echo; \
echo '; Ensure worker stdout and stderr are sent to the main error log.'; \
echo 'catch_workers_output = yes'; \
echo 'decorate_workers_output = no'; \
} | tee php-fpm.d/docker.conf; \
{ \
echo '[global]'; \
echo 'daemonize = no'; \
echo; \
echo '[www]'; \
echo 'listen = 9000'; \
} | tee php-fpm.d/zz-docker.conf
# Override stop signal to stop process gracefully
# https://github.com/php/php-src/blob/17baa87faddc2550def3ae7314236826bc1b1398/sapi/fpm/php-fpm.8.in#L163
STOPSIGNAL SIGQUIT
EXPOSE 9000
CMD ["php-fpm"]
+287
View File
@@ -0,0 +1,287 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/35d0a696b273c31f41ae224f189c19e794df91ae/7.3/bullseye/fpm),
# with the changes marked "chialab:".
#
FROM debian:bullseye-slim
# chialab: Debian bullseye has been moved to archive.debian.org.
RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/bullseye-updates/d' /etc/apt/sources.list
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
; \
rm -rf /var/lib/apt/lists/*
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS CBAF69F173A0FEA4B537F470D66C9593118BCCB6 F38252826ACD957EF380D39F2F7956BC5DA04B5D
ENV PHP_VERSION 7.3.33
ENV PHP_URL="https://www.php.net/distributions/php-7.3.33.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.3.33.tar.xz.asc"
ENV PHP_SHA256="166eaccde933381da9516a2b70ad0f447d7cec4b603d07b9a916032b215b90cc"
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends gnupg dirmngr; \
rm -rf /var/lib/apt/lists/*; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.3,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
libargon2-dev \
libcurl4-openssl-dev \
libreadline-dev \
libsodium-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
zlib1g-dev \
; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-iconv \
--with-openssl \
--with-readline \
--with-zlib \
\
# https://github.com/bwoebi/phpdbg-docs/issues/1#issuecomment-163872806 ("phpdbg is primarily a CLI debugger, and is not suitable for debugging an fpm stack.")
--disable-phpdbg \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/bullseye/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
--disable-cgi \
\
--enable-fpm \
--with-fpm-user=www-data \
--with-fpm-group=www-data \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find \
/usr/local \
-type f \
-perm '/0111' \
-exec sh -euxc ' \
strip --strip-all "$@" || : \
' -- '{}' + \
; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
rm -rf /var/lib/apt/lists/*; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.3 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.3 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/fpm /usr/local/bin/docker-php-entrypoint
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
# temporary "freetype-config" workaround for https://github.com/docker-library/php/issues/865 (https://bugs.php.net/bug.php?id=76324)
RUN { echo '#!/bin/sh'; echo 'exec pkg-config "$@" freetype2'; } > /usr/local/bin/freetype-config && chmod +x /usr/local/bin/freetype-config
ENTRYPOINT ["docker-php-entrypoint"]
WORKDIR /var/www/html
RUN set -eux; \
cd /usr/local/etc; \
if [ -d php-fpm.d ]; then \
# for some reason, upstream's php-fpm.conf.default has "include=NONE/etc/php-fpm.d/*.conf"
sed 's!=NONE/!=!g' php-fpm.conf.default | tee php-fpm.conf > /dev/null; \
cp php-fpm.d/www.conf.default php-fpm.d/www.conf; \
else \
# PHP 5.x doesn't use "include=" by default, so we'll create our own simple config that mimics PHP 7+ for consistency
mkdir php-fpm.d; \
cp php-fpm.conf.default php-fpm.d/www.conf; \
{ \
echo '[global]'; \
echo 'include=etc/php-fpm.d/*.conf'; \
} | tee php-fpm.conf; \
fi; \
{ \
echo '[global]'; \
echo 'error_log = /proc/self/fd/2'; \
echo; echo '; https://github.com/docker-library/php/pull/725#issuecomment-443540114'; echo 'log_limit = 8192'; \
echo; \
echo '[www]'; \
echo '; if we send this to /proc/self/fd/1, it never appears'; \
echo 'access.log = /proc/self/fd/2'; \
echo; \
echo 'clear_env = no'; \
echo; \
echo '; Ensure worker stdout and stderr are sent to the main error log.'; \
echo 'catch_workers_output = yes'; \
echo 'decorate_workers_output = no'; \
} | tee php-fpm.d/docker.conf; \
{ \
echo '[global]'; \
echo 'daemonize = no'; \
echo; \
echo '[www]'; \
echo 'listen = 9000'; \
} | tee php-fpm.d/zz-docker.conf
# Override stop signal to stop process gracefully
# https://github.com/php/php-src/blob/17baa87faddc2550def3ae7314236826bc1b1398/sapi/fpm/php-fpm.8.in#L163
STOPSIGNAL SIGQUIT
EXPOSE 9000
CMD ["php-fpm"]
+220
View File
@@ -0,0 +1,220 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/1361ba95d80570e3984f9de9f765948246191557/7.4/alpine3.16/cli),
# with the changes marked "chialab:".
#
FROM alpine:3.16
# dependencies required for running "phpize"
# these get automatically installed and removed by "docker-php-ext-*" (unless they're already installed)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev dpkg \
file \
g++ \
gcc \
libc-dev \
make \
pkgconf \
re2c
# persistent / runtime deps
RUN apk add --no-cache \
ca-certificates \
curl \
tar \
xz \
# https://github.com/docker-library/php/issues/494
openssl
# ensure www-data user exists
RUN set -eux; \
adduser -u 82 -D -S -G www-data www-data
# 82 is the standard uid/gid for "www-data" in Alpine
# https://git.alpinelinux.org/aports/tree/main/apache2/apache2.pre-install?h=3.14-stable
# https://git.alpinelinux.org/aports/tree/main/lighttpd/lighttpd.pre-install?h=3.14-stable
# https://git.alpinelinux.org/aports/tree/main/nginx/nginx.pre-install?h=3.14-stable
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS 42670A7FE4D0441C8E4632349E4FDC074A4EF02D 5A52880781F755608BF815FC910DEB46F53EA312
ENV PHP_VERSION 7.4.33
ENV PHP_URL="https://www.php.net/distributions/php-7.4.33.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.4.33.tar.xz.asc"
ENV PHP_SHA256="924846abf93bc613815c55dd3f5809377813ac62a9ec4eb3778675b82a27b927"
RUN set -eux; \
\
apk add --no-cache --virtual .fetch-deps gnupg; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apk del --no-network .fetch-deps
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.4,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
argon2-dev \
coreutils \
curl-dev \
gnu-libiconv-dev \
libsodium-dev \
libxml2-dev \
linux-headers \
oniguruma-dev \
openssl-dev \
readline-dev \
sqlite-dev \
; \
\
# make sure musl's iconv doesn't get used (https://www.php.net/manual/en/intro.iconv.php)
rm -vf /usr/include/iconv.h; \
# PHP < 8 doesn't know to look deeper for GNU libiconv: https://github.com/php/php-src/commit/b480e6841ecd5317faa136647a2b8253a4c2d0df
ln -sv /usr/include/gnu-libiconv/*.h /usr/include/; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-iconv=/usr \
--with-openssl \
--with-readline \
--with-zlib \
\
# https://github.com/docker-library/php/pull/1259
--enable-phpdbg \
--enable-phpdbg-readline \
\
# in PHP 7.4+, the pecl/pear installers are officially deprecated (requiring an explicit "--with-pear")
--with-pear \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/bullseye/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-musl' && echo '--without-pcre-jit') \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find \
/usr/local \
-type f \
-perm '/0111' \
-exec sh -euxc ' \
strip --strip-all "$@" || : \
' -- '{}' + \
; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)"; \
apk add --no-cache $runDeps; \
\
apk del --no-network .build-deps; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.3 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.4 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/cli /usr/local/bin/docker-php-entrypoint
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
ENTRYPOINT ["docker-php-entrypoint"]
CMD ["php", "-a"]
+308
View File
@@ -0,0 +1,308 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/1361ba95d80570e3984f9de9f765948246191557/7.4/bullseye/apache),
# with the changes marked "chialab:".
#
FROM debian:bullseye-slim
# chialab: Debian bullseye has been moved to archive.debian.org.
RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/bullseye-updates/d' /etc/apt/sources.list
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
; \
rm -rf /var/lib/apt/lists/*
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
ENV APACHE_CONFDIR /etc/apache2
ENV APACHE_ENVVARS $APACHE_CONFDIR/envvars
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends apache2; \
rm -rf /var/lib/apt/lists/*; \
\
# generically convert lines like
# export APACHE_RUN_USER=www-data
# into
# : ${APACHE_RUN_USER:=www-data}
# export APACHE_RUN_USER
# so that they can be overridden at runtime ("-e APACHE_RUN_USER=...")
sed -ri 's/^export ([^=]+)=(.*)$/: ${\1:=\2}\nexport \1/' "$APACHE_ENVVARS"; \
\
# setup directories and permissions
. "$APACHE_ENVVARS"; \
for dir in \
"$APACHE_LOCK_DIR" \
"$APACHE_RUN_DIR" \
"$APACHE_LOG_DIR" \
; do \
rm -rvf "$dir"; \
mkdir -p "$dir"; \
chown "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$dir"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
chmod 777 "$dir"; \
done; \
\
# delete the "index.html" that installing Apache drops in here
rm -rvf /var/www/html/*; \
\
# logs should go to stdout / stderr
ln -sfT /dev/stderr "$APACHE_LOG_DIR/error.log"; \
ln -sfT /dev/stdout "$APACHE_LOG_DIR/access.log"; \
ln -sfT /dev/stdout "$APACHE_LOG_DIR/other_vhosts_access.log"; \
chown -R --no-dereference "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$APACHE_LOG_DIR"
# Apache + PHP requires preforking Apache for best results
RUN a2dismod mpm_event && a2enmod mpm_prefork
# PHP files should be handled by PHP, and should be preferred over any other file type
RUN { \
echo '<FilesMatch \.php$>'; \
echo '\tSetHandler application/x-httpd-php'; \
echo '</FilesMatch>'; \
echo; \
echo 'DirectoryIndex disabled'; \
echo 'DirectoryIndex index.php index.html'; \
echo; \
echo '<Directory /var/www/>'; \
echo '\tOptions -Indexes'; \
echo '\tAllowOverride All'; \
echo '</Directory>'; \
} | tee "$APACHE_CONFDIR/conf-available/docker-php.conf" \
&& a2enconf docker-php
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS 42670A7FE4D0441C8E4632349E4FDC074A4EF02D 5A52880781F755608BF815FC910DEB46F53EA312
ENV PHP_VERSION 7.4.33
ENV PHP_URL="https://www.php.net/distributions/php-7.4.33.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.4.33.tar.xz.asc"
ENV PHP_SHA256="924846abf93bc613815c55dd3f5809377813ac62a9ec4eb3778675b82a27b927"
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends gnupg dirmngr; \
rm -rf /var/lib/apt/lists/*; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.4,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
apache2-dev \
libargon2-dev \
libcurl4-openssl-dev \
libonig-dev \
libreadline-dev \
libsodium-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
zlib1g-dev \
; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-iconv \
--with-openssl \
--with-readline \
--with-zlib \
\
# https://github.com/bwoebi/phpdbg-docs/issues/1#issuecomment-163872806 ("phpdbg is primarily a CLI debugger, and is not suitable for debugging an fpm stack.")
--disable-phpdbg \
\
# in PHP 7.4+, the pecl/pear installers are officially deprecated (requiring an explicit "--with-pear")
--with-pear \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/bullseye/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
--disable-cgi \
\
--with-apxs2 \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find \
/usr/local \
-type f \
-perm '/0111' \
-exec sh -euxc ' \
strip --strip-all "$@" || : \
' -- '{}' + \
; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
rm -rf /var/lib/apt/lists/*; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.3 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.4 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/apache /usr/local/bin/docker-php-entrypoint
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
ENTRYPOINT ["docker-php-entrypoint"]
# https://httpd.apache.org/docs/2.4/stopping.html#gracefulstop
STOPSIGNAL SIGWINCH
# chialab: from eol/scripts.
COPY --from=scripts apache2-foreground /usr/local/bin/
WORKDIR /var/www/html
EXPOSE 80
CMD ["apache2-foreground"]
+241
View File
@@ -0,0 +1,241 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/1361ba95d80570e3984f9de9f765948246191557/7.4/bullseye/cli),
# with the changes marked "chialab:".
#
FROM debian:bullseye-slim
# chialab: Debian bullseye has been moved to archive.debian.org.
RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/bullseye-updates/d' /etc/apt/sources.list
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
; \
rm -rf /var/lib/apt/lists/*
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS 42670A7FE4D0441C8E4632349E4FDC074A4EF02D 5A52880781F755608BF815FC910DEB46F53EA312
ENV PHP_VERSION 7.4.33
ENV PHP_URL="https://www.php.net/distributions/php-7.4.33.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.4.33.tar.xz.asc"
ENV PHP_SHA256="924846abf93bc613815c55dd3f5809377813ac62a9ec4eb3778675b82a27b927"
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends gnupg dirmngr; \
rm -rf /var/lib/apt/lists/*; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.4,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
libargon2-dev \
libcurl4-openssl-dev \
libonig-dev \
libreadline-dev \
libsodium-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
zlib1g-dev \
; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-iconv \
--with-openssl \
--with-readline \
--with-zlib \
\
# https://github.com/docker-library/php/pull/1259
--enable-phpdbg \
--enable-phpdbg-readline \
\
# in PHP 7.4+, the pecl/pear installers are officially deprecated (requiring an explicit "--with-pear")
--with-pear \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/bullseye/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
# https://github.com/docker-library/php/pull/939#issuecomment-730501748
--enable-embed \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find \
/usr/local \
-type f \
-perm '/0111' \
-exec sh -euxc ' \
strip --strip-all "$@" || : \
' -- '{}' + \
; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
rm -rf /var/lib/apt/lists/*; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.3 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.4 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/cli /usr/local/bin/docker-php-entrypoint
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
ENTRYPOINT ["docker-php-entrypoint"]
CMD ["php", "-a"]
+270
View File
@@ -0,0 +1,270 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/1361ba95d80570e3984f9de9f765948246191557/7.4/alpine3.16/fpm),
# with the changes marked "chialab:".
#
FROM alpine:3.16
# dependencies required for running "phpize"
# these get automatically installed and removed by "docker-php-ext-*" (unless they're already installed)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev dpkg \
file \
g++ \
gcc \
libc-dev \
make \
pkgconf \
re2c
# persistent / runtime deps
RUN apk add --no-cache \
ca-certificates \
curl \
tar \
xz \
# https://github.com/docker-library/php/issues/494
openssl
# ensure www-data user exists
RUN set -eux; \
adduser -u 82 -D -S -G www-data www-data
# 82 is the standard uid/gid for "www-data" in Alpine
# https://git.alpinelinux.org/aports/tree/main/apache2/apache2.pre-install?h=3.14-stable
# https://git.alpinelinux.org/aports/tree/main/lighttpd/lighttpd.pre-install?h=3.14-stable
# https://git.alpinelinux.org/aports/tree/main/nginx/nginx.pre-install?h=3.14-stable
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS 42670A7FE4D0441C8E4632349E4FDC074A4EF02D 5A52880781F755608BF815FC910DEB46F53EA312
ENV PHP_VERSION 7.4.33
ENV PHP_URL="https://www.php.net/distributions/php-7.4.33.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.4.33.tar.xz.asc"
ENV PHP_SHA256="924846abf93bc613815c55dd3f5809377813ac62a9ec4eb3778675b82a27b927"
RUN set -eux; \
\
apk add --no-cache --virtual .fetch-deps gnupg; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apk del --no-network .fetch-deps
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.4,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
argon2-dev \
coreutils \
curl-dev \
gnu-libiconv-dev \
libsodium-dev \
libxml2-dev \
linux-headers \
oniguruma-dev \
openssl-dev \
readline-dev \
sqlite-dev \
; \
\
# make sure musl's iconv doesn't get used (https://www.php.net/manual/en/intro.iconv.php)
rm -vf /usr/include/iconv.h; \
# PHP < 8 doesn't know to look deeper for GNU libiconv: https://github.com/php/php-src/commit/b480e6841ecd5317faa136647a2b8253a4c2d0df
ln -sv /usr/include/gnu-libiconv/*.h /usr/include/; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-iconv=/usr \
--with-openssl \
--with-readline \
--with-zlib \
\
# https://github.com/bwoebi/phpdbg-docs/issues/1#issuecomment-163872806 ("phpdbg is primarily a CLI debugger, and is not suitable for debugging an fpm stack.")
--disable-phpdbg \
\
# in PHP 7.4+, the pecl/pear installers are officially deprecated (requiring an explicit "--with-pear")
--with-pear \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/bullseye/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-musl' && echo '--without-pcre-jit') \
\
--disable-cgi \
\
--enable-fpm \
--with-fpm-user=www-data \
--with-fpm-group=www-data \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find \
/usr/local \
-type f \
-perm '/0111' \
-exec sh -euxc ' \
strip --strip-all "$@" || : \
' -- '{}' + \
; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)"; \
apk add --no-cache $runDeps; \
\
apk del --no-network .build-deps; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.3 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.4 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/fpm /usr/local/bin/docker-php-entrypoint
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
ENTRYPOINT ["docker-php-entrypoint"]
WORKDIR /var/www/html
RUN set -eux; \
cd /usr/local/etc; \
if [ -d php-fpm.d ]; then \
# for some reason, upstream's php-fpm.conf.default has "include=NONE/etc/php-fpm.d/*.conf"
sed 's!=NONE/!=!g' php-fpm.conf.default | tee php-fpm.conf > /dev/null; \
cp php-fpm.d/www.conf.default php-fpm.d/www.conf; \
else \
# PHP 5.x doesn't use "include=" by default, so we'll create our own simple config that mimics PHP 7+ for consistency
mkdir php-fpm.d; \
cp php-fpm.conf.default php-fpm.d/www.conf; \
{ \
echo '[global]'; \
echo 'include=etc/php-fpm.d/*.conf'; \
} | tee php-fpm.conf; \
fi; \
{ \
echo '[global]'; \
echo 'error_log = /proc/self/fd/2'; \
echo; echo '; https://github.com/docker-library/php/pull/725#issuecomment-443540114'; echo 'log_limit = 8192'; \
echo; \
echo '[www]'; \
echo '; if we send this to /proc/self/fd/1, it never appears'; \
echo 'access.log = /proc/self/fd/2'; \
echo; \
echo 'clear_env = no'; \
echo; \
echo '; Ensure worker stdout and stderr are sent to the main error log.'; \
echo 'catch_workers_output = yes'; \
echo 'decorate_workers_output = no'; \
} | tee php-fpm.d/docker.conf; \
{ \
echo '[global]'; \
echo 'daemonize = no'; \
echo; \
echo '[www]'; \
echo 'listen = 9000'; \
} | tee php-fpm.d/zz-docker.conf
# Override stop signal to stop process gracefully
# https://github.com/php/php-src/blob/17baa87faddc2550def3ae7314236826bc1b1398/sapi/fpm/php-fpm.8.in#L163
STOPSIGNAL SIGQUIT
EXPOSE 9000
CMD ["php-fpm"]
+288
View File
@@ -0,0 +1,288 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/1361ba95d80570e3984f9de9f765948246191557/7.4/bullseye/fpm),
# with the changes marked "chialab:".
#
FROM debian:bullseye-slim
# chialab: Debian bullseye has been moved to archive.debian.org.
RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/bullseye-updates/d' /etc/apt/sources.list
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
; \
rm -rf /var/lib/apt/lists/*
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 777 /var/www/html
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS 42670A7FE4D0441C8E4632349E4FDC074A4EF02D 5A52880781F755608BF815FC910DEB46F53EA312
ENV PHP_VERSION 7.4.33
ENV PHP_URL="https://www.php.net/distributions/php-7.4.33.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-7.4.33.tar.xz.asc"
ENV PHP_SHA256="924846abf93bc613815c55dd3f5809377813ac62a9ec4eb3778675b82a27b927"
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends gnupg dirmngr; \
rm -rf /var/lib/apt/lists/*; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=7.4,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
libargon2-dev \
libcurl4-openssl-dev \
libonig-dev \
libreadline-dev \
libsodium-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
zlib1g-dev \
; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-iconv \
--with-openssl \
--with-readline \
--with-zlib \
\
# https://github.com/bwoebi/phpdbg-docs/issues/1#issuecomment-163872806 ("phpdbg is primarily a CLI debugger, and is not suitable for debugging an fpm stack.")
--disable-phpdbg \
\
# in PHP 7.4+, the pecl/pear installers are officially deprecated (requiring an explicit "--with-pear")
--with-pear \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/bullseye/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
--disable-cgi \
\
--enable-fpm \
--with-fpm-user=www-data \
--with-fpm-group=www-data \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find \
/usr/local \
-type f \
-perm '/0111' \
-exec sh -euxc ' \
strip --strip-all "$@" || : \
' -- '{}' + \
; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
rm -rf /var/lib/apt/lists/*; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.3 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.4 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/fpm /usr/local/bin/docker-php-entrypoint
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
ENTRYPOINT ["docker-php-entrypoint"]
WORKDIR /var/www/html
RUN set -eux; \
cd /usr/local/etc; \
if [ -d php-fpm.d ]; then \
# for some reason, upstream's php-fpm.conf.default has "include=NONE/etc/php-fpm.d/*.conf"
sed 's!=NONE/!=!g' php-fpm.conf.default | tee php-fpm.conf > /dev/null; \
cp php-fpm.d/www.conf.default php-fpm.d/www.conf; \
else \
# PHP 5.x doesn't use "include=" by default, so we'll create our own simple config that mimics PHP 7+ for consistency
mkdir php-fpm.d; \
cp php-fpm.conf.default php-fpm.d/www.conf; \
{ \
echo '[global]'; \
echo 'include=etc/php-fpm.d/*.conf'; \
} | tee php-fpm.conf; \
fi; \
{ \
echo '[global]'; \
echo 'error_log = /proc/self/fd/2'; \
echo; echo '; https://github.com/docker-library/php/pull/725#issuecomment-443540114'; echo 'log_limit = 8192'; \
echo; \
echo '[www]'; \
echo '; if we send this to /proc/self/fd/1, it never appears'; \
echo 'access.log = /proc/self/fd/2'; \
echo; \
echo 'clear_env = no'; \
echo; \
echo '; Ensure worker stdout and stderr are sent to the main error log.'; \
echo 'catch_workers_output = yes'; \
echo 'decorate_workers_output = no'; \
} | tee php-fpm.d/docker.conf; \
{ \
echo '[global]'; \
echo 'daemonize = no'; \
echo; \
echo '[www]'; \
echo 'listen = 9000'; \
} | tee php-fpm.d/zz-docker.conf
# Override stop signal to stop process gracefully
# https://github.com/php/php-src/blob/17baa87faddc2550def3ae7314236826bc1b1398/sapi/fpm/php-fpm.8.in#L163
STOPSIGNAL SIGQUIT
EXPOSE 9000
CMD ["php-fpm"]
+218
View File
@@ -0,0 +1,218 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/df4636cac888ec860ccbf0f200637b88a2fb22ab/8.0/alpine3.16/cli),
# with the changes marked "chialab:".
#
FROM alpine:3.16
# dependencies required for running "phpize"
# these get automatically installed and removed by "docker-php-ext-*" (unless they're already installed)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev dpkg \
file \
g++ \
gcc \
libc-dev \
make \
pkgconf \
re2c
# persistent / runtime deps
RUN apk add --no-cache \
ca-certificates \
curl \
tar \
xz \
# https://github.com/docker-library/php/issues/494
openssl
# ensure www-data user exists
RUN set -eux; \
adduser -u 82 -D -S -G www-data www-data
# 82 is the standard uid/gid for "www-data" in Alpine
# https://git.alpinelinux.org/aports/tree/main/apache2/apache2.pre-install?h=3.14-stable
# https://git.alpinelinux.org/aports/tree/main/lighttpd/lighttpd.pre-install?h=3.14-stable
# https://git.alpinelinux.org/aports/tree/main/nginx/nginx.pre-install?h=3.14-stable
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 1777 /var/www/html
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS 1729F83938DA44E27BA0F4D3DBDB397470D12172 BFDDD28642824F8118EF77909B67A5C12229118F 2C16C765DBE54A088130F1BC4B9B5F600B55F3B4 39B641343D8C104B2B146DC3F9C39DC0B9698544
ENV PHP_VERSION 8.0.30
ENV PHP_URL="https://www.php.net/distributions/php-8.0.30.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-8.0.30.tar.xz.asc"
ENV PHP_SHA256="216ab305737a5d392107112d618a755dc5df42058226f1670e9db90e77d777d9"
RUN set -eux; \
\
apk add --no-cache --virtual .fetch-deps gnupg; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apk del --no-network .fetch-deps
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=8.0,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
argon2-dev \
coreutils \
curl-dev \
gnu-libiconv-dev \
libsodium-dev \
libxml2-dev \
linux-headers \
oniguruma-dev \
openssl-dev \
readline-dev \
sqlite-dev \
; \
\
# make sure musl's iconv doesn't get used (https://www.php.net/manual/en/intro.iconv.php)
rm -vf /usr/include/iconv.h; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-iconv=/usr \
--with-openssl \
--with-readline \
--with-zlib \
\
# https://github.com/docker-library/php/pull/1259
--enable-phpdbg \
--enable-phpdbg-readline \
\
# in PHP 7.4+, the pecl/pear installers are officially deprecated (requiring an explicit "--with-pear")
--with-pear \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/bullseye/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-musl' && echo '--without-pcre-jit') \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find \
/usr/local \
-type f \
-perm '/0111' \
-exec sh -euxc ' \
strip --strip-all "$@" || : \
' -- '{}' + \
; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)"; \
apk add --no-cache $runDeps; \
\
apk del --no-network .build-deps; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.3 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.4 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/cli /usr/local/bin/docker-php-entrypoint
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
ENTRYPOINT ["docker-php-entrypoint"]
CMD ["php", "-a"]
+308
View File
@@ -0,0 +1,308 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/df4636cac888ec860ccbf0f200637b88a2fb22ab/8.0/bullseye/apache),
# with the changes marked "chialab:".
#
FROM debian:bullseye-slim
# chialab: Debian bullseye has been moved to archive.debian.org.
RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/bullseye-updates/d' /etc/apt/sources.list
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
; \
rm -rf /var/lib/apt/lists/*
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 1777 /var/www/html
ENV APACHE_CONFDIR /etc/apache2
ENV APACHE_ENVVARS $APACHE_CONFDIR/envvars
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends apache2; \
rm -rf /var/lib/apt/lists/*; \
\
# generically convert lines like
# export APACHE_RUN_USER=www-data
# into
# : ${APACHE_RUN_USER:=www-data}
# export APACHE_RUN_USER
# so that they can be overridden at runtime ("-e APACHE_RUN_USER=...")
sed -ri 's/^export ([^=]+)=(.*)$/: ${\1:=\2}\nexport \1/' "$APACHE_ENVVARS"; \
\
# setup directories and permissions
. "$APACHE_ENVVARS"; \
for dir in \
"$APACHE_LOCK_DIR" \
"$APACHE_RUN_DIR" \
"$APACHE_LOG_DIR" \
; do \
rm -rvf "$dir"; \
mkdir -p "$dir"; \
chown "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$dir"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
chmod 1777 "$dir"; \
done; \
\
# delete the "index.html" that installing Apache drops in here
rm -rvf /var/www/html/*; \
\
# logs should go to stdout / stderr
ln -sfT /dev/stderr "$APACHE_LOG_DIR/error.log"; \
ln -sfT /dev/stdout "$APACHE_LOG_DIR/access.log"; \
ln -sfT /dev/stdout "$APACHE_LOG_DIR/other_vhosts_access.log"; \
chown -R --no-dereference "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$APACHE_LOG_DIR"
# Apache + PHP requires preforking Apache for best results
RUN a2dismod mpm_event && a2enmod mpm_prefork
# PHP files should be handled by PHP, and should be preferred over any other file type
RUN { \
echo '<FilesMatch \.php$>'; \
echo '\tSetHandler application/x-httpd-php'; \
echo '</FilesMatch>'; \
echo; \
echo 'DirectoryIndex disabled'; \
echo 'DirectoryIndex index.php index.html'; \
echo; \
echo '<Directory /var/www/>'; \
echo '\tOptions -Indexes'; \
echo '\tAllowOverride All'; \
echo '</Directory>'; \
} | tee "$APACHE_CONFDIR/conf-available/docker-php.conf" \
&& a2enconf docker-php
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS 1729F83938DA44E27BA0F4D3DBDB397470D12172 BFDDD28642824F8118EF77909B67A5C12229118F 2C16C765DBE54A088130F1BC4B9B5F600B55F3B4 39B641343D8C104B2B146DC3F9C39DC0B9698544
ENV PHP_VERSION 8.0.30
ENV PHP_URL="https://www.php.net/distributions/php-8.0.30.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-8.0.30.tar.xz.asc"
ENV PHP_SHA256="216ab305737a5d392107112d618a755dc5df42058226f1670e9db90e77d777d9"
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends gnupg; \
rm -rf /var/lib/apt/lists/*; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=8.0,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
apache2-dev \
libargon2-dev \
libcurl4-openssl-dev \
libonig-dev \
libreadline-dev \
libsodium-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
zlib1g-dev \
; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-iconv \
--with-openssl \
--with-readline \
--with-zlib \
\
# https://github.com/bwoebi/phpdbg-docs/issues/1#issuecomment-163872806 ("phpdbg is primarily a CLI debugger, and is not suitable for debugging an fpm stack.")
--disable-phpdbg \
\
# in PHP 7.4+, the pecl/pear installers are officially deprecated (requiring an explicit "--with-pear")
--with-pear \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/bullseye/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
--disable-cgi \
\
--with-apxs2 \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find \
/usr/local \
-type f \
-perm '/0111' \
-exec sh -euxc ' \
strip --strip-all "$@" || : \
' -- '{}' + \
; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
rm -rf /var/lib/apt/lists/*; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.3 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.4 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/apache /usr/local/bin/docker-php-entrypoint
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
ENTRYPOINT ["docker-php-entrypoint"]
# https://httpd.apache.org/docs/2.4/stopping.html#gracefulstop
STOPSIGNAL SIGWINCH
# chialab: from eol/scripts.
COPY --from=scripts apache2-foreground /usr/local/bin/
WORKDIR /var/www/html
EXPOSE 80
CMD ["apache2-foreground"]
+241
View File
@@ -0,0 +1,241 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/df4636cac888ec860ccbf0f200637b88a2fb22ab/8.0/bullseye/cli),
# with the changes marked "chialab:".
#
FROM debian:bullseye-slim
# chialab: Debian bullseye has been moved to archive.debian.org.
RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/bullseye-updates/d' /etc/apt/sources.list
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
; \
rm -rf /var/lib/apt/lists/*
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 1777 /var/www/html
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS 1729F83938DA44E27BA0F4D3DBDB397470D12172 BFDDD28642824F8118EF77909B67A5C12229118F 2C16C765DBE54A088130F1BC4B9B5F600B55F3B4 39B641343D8C104B2B146DC3F9C39DC0B9698544
ENV PHP_VERSION 8.0.30
ENV PHP_URL="https://www.php.net/distributions/php-8.0.30.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-8.0.30.tar.xz.asc"
ENV PHP_SHA256="216ab305737a5d392107112d618a755dc5df42058226f1670e9db90e77d777d9"
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends gnupg; \
rm -rf /var/lib/apt/lists/*; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=8.0,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
libargon2-dev \
libcurl4-openssl-dev \
libonig-dev \
libreadline-dev \
libsodium-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
zlib1g-dev \
; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-iconv \
--with-openssl \
--with-readline \
--with-zlib \
\
# https://github.com/docker-library/php/pull/1259
--enable-phpdbg \
--enable-phpdbg-readline \
\
# in PHP 7.4+, the pecl/pear installers are officially deprecated (requiring an explicit "--with-pear")
--with-pear \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/bullseye/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
# https://github.com/docker-library/php/pull/939#issuecomment-730501748
--enable-embed \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find \
/usr/local \
-type f \
-perm '/0111' \
-exec sh -euxc ' \
strip --strip-all "$@" || : \
' -- '{}' + \
; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
rm -rf /var/lib/apt/lists/*; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.3 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.4 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/cli /usr/local/bin/docker-php-entrypoint
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
ENTRYPOINT ["docker-php-entrypoint"]
CMD ["php", "-a"]
+274
View File
@@ -0,0 +1,274 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/df4636cac888ec860ccbf0f200637b88a2fb22ab/8.0/alpine3.16/fpm),
# with the changes marked "chialab:".
#
FROM alpine:3.16
# dependencies required for running "phpize"
# these get automatically installed and removed by "docker-php-ext-*" (unless they're already installed)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev dpkg \
file \
g++ \
gcc \
libc-dev \
make \
pkgconf \
re2c
# persistent / runtime deps
RUN apk add --no-cache \
ca-certificates \
curl \
tar \
xz \
# https://github.com/docker-library/php/issues/494
openssl
# ensure www-data user exists
RUN set -eux; \
adduser -u 82 -D -S -G www-data www-data
# 82 is the standard uid/gid for "www-data" in Alpine
# https://git.alpinelinux.org/aports/tree/main/apache2/apache2.pre-install?h=3.14-stable
# https://git.alpinelinux.org/aports/tree/main/lighttpd/lighttpd.pre-install?h=3.14-stable
# https://git.alpinelinux.org/aports/tree/main/nginx/nginx.pre-install?h=3.14-stable
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 1777 /var/www/html
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS 1729F83938DA44E27BA0F4D3DBDB397470D12172 BFDDD28642824F8118EF77909B67A5C12229118F 2C16C765DBE54A088130F1BC4B9B5F600B55F3B4 39B641343D8C104B2B146DC3F9C39DC0B9698544
ENV PHP_VERSION 8.0.30
ENV PHP_URL="https://www.php.net/distributions/php-8.0.30.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-8.0.30.tar.xz.asc"
ENV PHP_SHA256="216ab305737a5d392107112d618a755dc5df42058226f1670e9db90e77d777d9"
RUN set -eux; \
\
apk add --no-cache --virtual .fetch-deps gnupg; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apk del --no-network .fetch-deps
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=8.0,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
argon2-dev \
coreutils \
curl-dev \
gnu-libiconv-dev \
libsodium-dev \
libxml2-dev \
linux-headers \
oniguruma-dev \
openssl-dev \
readline-dev \
sqlite-dev \
; \
\
# make sure musl's iconv doesn't get used (https://www.php.net/manual/en/intro.iconv.php)
rm -vf /usr/include/iconv.h; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-iconv=/usr \
--with-openssl \
--with-readline \
--with-zlib \
\
# https://github.com/bwoebi/phpdbg-docs/issues/1#issuecomment-163872806 ("phpdbg is primarily a CLI debugger, and is not suitable for debugging an fpm stack.")
--disable-phpdbg \
\
# in PHP 7.4+, the pecl/pear installers are officially deprecated (requiring an explicit "--with-pear")
--with-pear \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/bullseye/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-musl' && echo '--without-pcre-jit') \
\
--disable-cgi \
\
--enable-fpm \
--with-fpm-user=www-data \
--with-fpm-group=www-data \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find \
/usr/local \
-type f \
-perm '/0111' \
-exec sh -euxc ' \
strip --strip-all "$@" || : \
' -- '{}' + \
; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)"; \
apk add --no-cache $runDeps; \
\
apk del --no-network .build-deps; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.3 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.4 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/fpm /usr/local/bin/docker-php-entrypoint
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
ENTRYPOINT ["docker-php-entrypoint"]
WORKDIR /var/www/html
RUN set -eux; \
cd /usr/local/etc; \
if [ -d php-fpm.d ]; then \
# for some reason, upstream's php-fpm.conf.default has "include=NONE/etc/php-fpm.d/*.conf"
sed 's!=NONE/!=!g' php-fpm.conf.default | tee php-fpm.conf > /dev/null; \
cp php-fpm.d/www.conf.default php-fpm.d/www.conf; \
else \
# PHP 5.x doesn't use "include=" by default, so we'll create our own simple config that mimics PHP 7+ for consistency
mkdir php-fpm.d; \
cp php-fpm.conf.default php-fpm.d/www.conf; \
{ \
echo '[global]'; \
echo 'include=etc/php-fpm.d/*.conf'; \
} | tee php-fpm.conf; \
fi; \
{ \
echo '[global]'; \
echo 'error_log = /proc/self/fd/2'; \
echo; echo '; https://github.com/docker-library/php/pull/725#issuecomment-443540114'; echo 'log_limit = 8192'; \
echo; \
echo '[www]'; \
echo '; php-fpm closes STDOUT on startup, so sending logs to /proc/self/fd/1 does not work.'; \
echo '; https://bugs.php.net/bug.php?id=73886'; \
echo 'access.log = /proc/self/fd/2'; \
echo; \
echo 'clear_env = no'; \
echo; \
echo '; Ensure worker stdout and stderr are sent to the main error log.'; \
echo 'catch_workers_output = yes'; \
echo 'decorate_workers_output = no'; \
} | tee php-fpm.d/docker.conf; \
{ \
echo '[global]'; \
echo 'daemonize = no'; \
echo; \
echo '[www]'; \
echo 'listen = 9000'; \
} | tee php-fpm.d/zz-docker.conf; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
{ \
echo '; https://github.com/docker-library/php/issues/878#issuecomment-938595965'; \
echo 'fastcgi.logging = Off'; \
} > "$PHP_INI_DIR/conf.d/docker-fpm.ini"
# Override stop signal to stop process gracefully
# https://github.com/php/php-src/blob/17baa87faddc2550def3ae7314236826bc1b1398/sapi/fpm/php-fpm.8.in#L163
STOPSIGNAL SIGQUIT
EXPOSE 9000
CMD ["php-fpm"]
+294
View File
@@ -0,0 +1,294 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/df4636cac888ec860ccbf0f200637b88a2fb22ab/8.0/bullseye/fpm),
# with the changes marked "chialab:".
#
FROM debian:bullseye-slim
# chialab: Debian bullseye has been moved to archive.debian.org.
RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/bullseye-updates/d' /etc/apt/sources.list
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
; \
rm -rf /var/lib/apt/lists/*
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 1777 /var/www/html
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS 1729F83938DA44E27BA0F4D3DBDB397470D12172 BFDDD28642824F8118EF77909B67A5C12229118F 2C16C765DBE54A088130F1BC4B9B5F600B55F3B4 39B641343D8C104B2B146DC3F9C39DC0B9698544
ENV PHP_VERSION 8.0.30
ENV PHP_URL="https://www.php.net/distributions/php-8.0.30.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-8.0.30.tar.xz.asc"
ENV PHP_SHA256="216ab305737a5d392107112d618a755dc5df42058226f1670e9db90e77d777d9"
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends gnupg; \
rm -rf /var/lib/apt/lists/*; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
if [ -n "$PHP_ASC_URL" ]; then \
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
fi; \
\
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=8.0,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
libargon2-dev \
libcurl4-openssl-dev \
libonig-dev \
libreadline-dev \
libsodium-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
zlib1g-dev \
; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-iconv \
--with-openssl \
--with-readline \
--with-zlib \
\
# https://github.com/bwoebi/phpdbg-docs/issues/1#issuecomment-163872806 ("phpdbg is primarily a CLI debugger, and is not suitable for debugging an fpm stack.")
--disable-phpdbg \
\
# in PHP 7.4+, the pecl/pear installers are officially deprecated (requiring an explicit "--with-pear")
--with-pear \
\
# bundled pcre does not support JIT on s390x
# https://manpages.debian.org/bullseye/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
$(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
--disable-cgi \
\
--enable-fpm \
--with-fpm-user=www-data \
--with-fpm-group=www-data \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find \
/usr/local \
-type f \
-perm '/0111' \
-exec sh -euxc ' \
strip --strip-all "$@" || : \
' -- '{}' + \
; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
rm -rf /var/lib/apt/lists/*; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.3 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/7.4 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/fpm /usr/local/bin/docker-php-entrypoint
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
ENTRYPOINT ["docker-php-entrypoint"]
WORKDIR /var/www/html
RUN set -eux; \
cd /usr/local/etc; \
if [ -d php-fpm.d ]; then \
# for some reason, upstream's php-fpm.conf.default has "include=NONE/etc/php-fpm.d/*.conf"
sed 's!=NONE/!=!g' php-fpm.conf.default | tee php-fpm.conf > /dev/null; \
cp php-fpm.d/www.conf.default php-fpm.d/www.conf; \
else \
# PHP 5.x doesn't use "include=" by default, so we'll create our own simple config that mimics PHP 7+ for consistency
mkdir php-fpm.d; \
cp php-fpm.conf.default php-fpm.d/www.conf; \
{ \
echo '[global]'; \
echo 'include=etc/php-fpm.d/*.conf'; \
} | tee php-fpm.conf; \
fi; \
{ \
echo '[global]'; \
echo 'error_log = /proc/self/fd/2'; \
echo; echo '; https://github.com/docker-library/php/pull/725#issuecomment-443540114'; echo 'log_limit = 8192'; \
echo; \
echo '[www]'; \
echo '; php-fpm closes STDOUT on startup, so sending logs to /proc/self/fd/1 does not work.'; \
echo '; https://bugs.php.net/bug.php?id=73886'; \
echo 'access.log = /proc/self/fd/2'; \
echo; \
echo 'clear_env = no'; \
echo; \
echo '; Ensure worker stdout and stderr are sent to the main error log.'; \
echo 'catch_workers_output = yes'; \
echo 'decorate_workers_output = no'; \
} | tee php-fpm.d/docker.conf; \
{ \
echo '[global]'; \
echo 'daemonize = no'; \
echo; \
echo '[www]'; \
echo 'listen = 9000'; \
} | tee php-fpm.d/zz-docker.conf; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
{ \
echo '; https://github.com/docker-library/php/issues/878#issuecomment-938595965'; \
echo 'fastcgi.logging = Off'; \
} > "$PHP_INI_DIR/conf.d/docker-fpm.ini"
# Override stop signal to stop process gracefully
# https://github.com/php/php-src/blob/17baa87faddc2550def3ae7314236826bc1b1398/sapi/fpm/php-fpm.8.in#L163
STOPSIGNAL SIGQUIT
EXPOSE 9000
CMD ["php-fpm"]
+242
View File
@@ -0,0 +1,242 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/5c037abaf9dc0095e29807c048d9d1b97e6a9716/8.1/alpine3.21/cli),
# with the changes marked "chialab:".
#
FROM alpine:3.21
# dependencies required for running "phpize"
# these get automatically installed and removed by "docker-php-ext-*" (unless they're already installed)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev dpkg \
file \
g++ \
gcc \
libc-dev \
make \
pkgconf \
re2c
# persistent / runtime deps
RUN apk add --no-cache \
ca-certificates \
curl \
openssl \
tar \
xz
# ensure www-data user exists
RUN set -eux; \
adduser -u 82 -D -S -G www-data www-data
# 82 is the standard uid/gid for "www-data" in Alpine
# https://git.alpinelinux.org/aports/tree/main/apache2/apache2.pre-install?h=3.14-stable
# https://git.alpinelinux.org/aports/tree/main/lighttpd/lighttpd.pre-install?h=3.14-stable
# https://git.alpinelinux.org/aports/tree/main/nginx/nginx.pre-install?h=3.14-stable
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 1777 /var/www/html
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS 528995BFEDFBA7191D46839EF9BA0ADA31CBD89E 39B641343D8C104B2B146DC3F9C39DC0B9698544 F1F692238FBC1666E5A5CCD4199F9DFEF6FFBAFD
ENV PHP_VERSION 8.1.34
ENV PHP_URL="https://www.php.net/distributions/php-8.1.34.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-8.1.34.tar.xz.asc"
ENV PHP_SHA256="ffa9e0982e82eeaea848f57687b425ed173aa278fe563001310ae2638db5c251"
RUN set -eux; \
\
apk add --no-cache --virtual .fetch-deps gnupg; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
\
apk del --no-network .fetch-deps
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=8.1,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
argon2-dev \
coreutils \
curl-dev \
gnu-libiconv-dev \
libsodium-dev \
libxml2-dev \
linux-headers \
oniguruma-dev \
openssl-dev \
patch \
patchutils \
readline-dev \
sqlite-dev \
; \
\
# make sure musl's iconv doesn't get used (https://www.php.net/manual/en/intro.iconv.php)
rm -vf /usr/include/iconv.h; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
# https://github.com/php/php-src/blob/d6299206dd828382753453befd1b915491b741c6/configure.ac#L1496-L1511
PHP_BUILD_PROVIDER='https://github.com/docker-library/php' \
PHP_UNAME='Linux - Docker' \
; \
docker-php-source extract; \
cd /usr/src/php; \
# Apply patches; see https://github.com/docker-library/php/pull/1552
# https://github.com/php/php-src/issues/11678
curl -fL 'https://github.com/php/php-src/commit/577b8ae4226368e66fee7a9b5c58f9e2428372fc.patch?full_index=1' -o 11678.patch; \
echo '6edc20c3bb3e7cc13515abce7f2fffa8ebea6cf7469abfbc78fcdc120350b239 *11678.patch' | sha256sum -c -; \
patch -p1 < 11678.patch; \
rm 11678.patch; \
# https://github.com/php/php-src/pull/19131
# this backported commit broke our ability to apply 14834, which is the fix we need, so this is applied as a reverse patch to undo it
# 19131 was for FreeBSD, so doesn't apply to this alpine build
curl -fL 'https://github.com/php/php-src/commit/a5df26691d1b1f71b964b869510473a5d5413999.patch?full_index=1' -o 19131.patch; \
echo 'c98c01c74d3a6da197116f8511b16fed361ca6bbb6a8af8df629a933f541c213 *19131.patch' | sha256sum -c -; \
patch --reverse -p1 < 19131.patch; \
rm 19131.patch; \
# https://github.com/php/php-src/issues/14834
curl -fL 'https://github.com/php/php-src/commit/67259e451d5d58b4842776c5696a66d74e157609.patch?full_index=1' -o 14834.patch; \
echo 'ed10a1b254091ad676ed204e55628ecbd6c8962004d6185a1821cedecd526c0f *14834.patch' | sha256sum -c -; \
filterdiff -x '*/NEWS' 14834.patch | patch -p1; \
rm 14834.patch; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here for compatibility with existing versions. ftp_ssl_connect() needed ftp to be compiled statically before PHP 7.0 (see https://github.com/docker-library/php/issues/236).
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-iconv=/usr \
--with-openssl \
--with-readline \
--with-zlib \
\
# https://github.com/docker-library/php/pull/1259
--enable-phpdbg \
--enable-phpdbg-readline \
\
# in PHP 7.4+, the pecl/pear installers are officially deprecated (requiring an explicit "--with-pear")
--with-pear \
\
# bundled pcre does not support JIT on riscv64 until 10.41 (php 8.3+)
# https://github.com/PCRE2Project/pcre2/commits/pcre2-10.41/src/sljit/sljitNativeRISCV_64.c
# https://github.com/php/php-src/tree/php-8.3.0/ext/pcre/pcre2lib
$(test "$gnuArch" = 'riscv64-linux-musl' && echo '--without-pcre-jit') \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find \
/usr/local \
-type f \
-perm '/0111' \
-exec sh -euxc ' \
strip --strip-all "$@" || : \
' -- '{}' + \
; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)"; \
apk add --no-cache $runDeps; \
\
apk del --no-network .build-deps; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.3 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/8.1 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/cli /usr/local/bin/docker-php-entrypoint
# enable OPcache by default (https://wiki.php.net/rfc/make_opcache_required)
RUN docker-php-ext-enable opcache
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
ENTRYPOINT ["docker-php-entrypoint"]
CMD ["php", "-a"]
+311
View File
@@ -0,0 +1,311 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/5c037abaf9dc0095e29807c048d9d1b97e6a9716/8.1/trixie/apache),
# with the changes marked "chialab:".
#
FROM debian:trixie-slim
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
; \
apt-get dist-clean
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 1777 /var/www/html
ENV APACHE_CONFDIR /etc/apache2
ENV APACHE_ENVVARS $APACHE_CONFDIR/envvars
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends apache2; \
apt-get dist-clean; \
\
# generically convert lines like
# export APACHE_RUN_USER=www-data
# into
# : ${APACHE_RUN_USER:=www-data}
# export APACHE_RUN_USER
# so that they can be overridden at runtime ("-e APACHE_RUN_USER=...")
sed -ri 's/^export ([^=]+)=(.*)$/: ${\1:=\2}\nexport \1/' "$APACHE_ENVVARS"; \
\
# setup directories and permissions
. "$APACHE_ENVVARS"; \
for dir in \
"$APACHE_LOCK_DIR" \
"$APACHE_RUN_DIR" \
"$APACHE_LOG_DIR" \
# https://salsa.debian.org/apache-team/apache2/-/commit/b97ca8714890ead1ba6c095699dde752e8433205
"$APACHE_RUN_DIR/socks" \
; do \
rm -rvf "$dir"; \
mkdir -p "$dir"; \
chown "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$dir"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
chmod 1777 "$dir"; \
done; \
\
# delete the "index.html" that installing Apache drops in here
rm -rvf /var/www/html/*; \
\
# logs should go to stdout / stderr
ln -sfT /dev/stderr "$APACHE_LOG_DIR/error.log"; \
ln -sfT /dev/stdout "$APACHE_LOG_DIR/access.log"; \
ln -sfT /dev/stdout "$APACHE_LOG_DIR/other_vhosts_access.log"; \
chown -R --no-dereference "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$APACHE_LOG_DIR"
# Apache + PHP requires preforking Apache for best results
RUN a2dismod mpm_event && a2enmod mpm_prefork
# PHP files should be handled by PHP, and should be preferred over any other file type
RUN { \
echo '<FilesMatch \.php$>'; \
echo '\tSetHandler application/x-httpd-php'; \
echo '</FilesMatch>'; \
echo; \
echo 'DirectoryIndex disabled'; \
echo 'DirectoryIndex index.php index.html'; \
echo; \
echo '<Directory /var/www/>'; \
echo '\tOptions -Indexes'; \
echo '\tAllowOverride All'; \
echo '</Directory>'; \
} | tee "$APACHE_CONFDIR/conf-available/docker-php.conf" \
&& a2enconf docker-php
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS 528995BFEDFBA7191D46839EF9BA0ADA31CBD89E 39B641343D8C104B2B146DC3F9C39DC0B9698544 F1F692238FBC1666E5A5CCD4199F9DFEF6FFBAFD
ENV PHP_VERSION 8.1.34
ENV PHP_URL="https://www.php.net/distributions/php-8.1.34.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-8.1.34.tar.xz.asc"
ENV PHP_SHA256="ffa9e0982e82eeaea848f57687b425ed173aa278fe563001310ae2638db5c251"
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends gnupg; \
apt-get dist-clean; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
\
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=8.1,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
apache2-dev \
libargon2-dev \
libcurl4-openssl-dev \
libonig-dev \
libreadline-dev \
libsodium-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
zlib1g-dev \
; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
# https://github.com/php/php-src/blob/d6299206dd828382753453befd1b915491b741c6/configure.ac#L1496-L1511
PHP_BUILD_PROVIDER='https://github.com/docker-library/php' \
PHP_UNAME='Linux - Docker' \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here for compatibility with existing versions. ftp_ssl_connect() needed ftp to be compiled statically before PHP 7.0 (see https://github.com/docker-library/php/issues/236).
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-iconv \
--with-openssl \
--with-readline \
--with-zlib \
\
# https://github.com/bwoebi/phpdbg-docs/issues/1#issuecomment-163872806 ("phpdbg is primarily a CLI debugger, and is not suitable for debugging an fpm stack.")
--disable-phpdbg \
\
# in PHP 7.4+, the pecl/pear installers are officially deprecated (requiring an explicit "--with-pear")
--with-pear \
\
# bundled pcre does not support JIT on riscv64 until 10.41 (php 8.3+)
# https://github.com/PCRE2Project/pcre2/commits/pcre2-10.41/src/sljit/sljitNativeRISCV_64.c
# https://github.com/php/php-src/tree/php-8.3.0/ext/pcre/pcre2lib
$(test "$gnuArch" = 'riscv64-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
--disable-cgi \
\
--with-apxs2 \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find \
/usr/local \
-type f \
-perm '/0111' \
-exec sh -euxc ' \
strip --strip-all "$@" || : \
' -- '{}' + \
; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); printf "*%s\n", so }' \
| sort -u \
| xargs -rt dpkg-query --search \
# https://manpages.debian.org/trixie/dpkg/dpkg-query.1.en.html#S (we ignore diversions and it'll be really unusual for more than one package to provide any given .so file)
| awk 'sub(":$", "", $1) { print $1 }' \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
apt-get dist-clean; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.3 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/8.1 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/apache /usr/local/bin/docker-php-entrypoint
# enable OPcache by default (https://wiki.php.net/rfc/make_opcache_required)
RUN docker-php-ext-enable opcache
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
ENTRYPOINT ["docker-php-entrypoint"]
# https://httpd.apache.org/docs/2.4/stopping.html#gracefulstop
STOPSIGNAL SIGWINCH
# chialab: from eol/scripts.
COPY --from=scripts apache2-foreground /usr/local/bin/
WORKDIR /var/www/html
EXPOSE 80
CMD ["apache2-foreground"]
+242
View File
@@ -0,0 +1,242 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/5c037abaf9dc0095e29807c048d9d1b97e6a9716/8.1/trixie/cli),
# with the changes marked "chialab:".
#
FROM debian:trixie-slim
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
; \
apt-get dist-clean
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 1777 /var/www/html
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS 528995BFEDFBA7191D46839EF9BA0ADA31CBD89E 39B641343D8C104B2B146DC3F9C39DC0B9698544 F1F692238FBC1666E5A5CCD4199F9DFEF6FFBAFD
ENV PHP_VERSION 8.1.34
ENV PHP_URL="https://www.php.net/distributions/php-8.1.34.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-8.1.34.tar.xz.asc"
ENV PHP_SHA256="ffa9e0982e82eeaea848f57687b425ed173aa278fe563001310ae2638db5c251"
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends gnupg; \
apt-get dist-clean; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
\
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=8.1,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
libargon2-dev \
libcurl4-openssl-dev \
libonig-dev \
libreadline-dev \
libsodium-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
zlib1g-dev \
; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
# https://github.com/php/php-src/blob/d6299206dd828382753453befd1b915491b741c6/configure.ac#L1496-L1511
PHP_BUILD_PROVIDER='https://github.com/docker-library/php' \
PHP_UNAME='Linux - Docker' \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here for compatibility with existing versions. ftp_ssl_connect() needed ftp to be compiled statically before PHP 7.0 (see https://github.com/docker-library/php/issues/236).
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-iconv \
--with-openssl \
--with-readline \
--with-zlib \
\
# https://github.com/docker-library/php/pull/1259
--enable-phpdbg \
--enable-phpdbg-readline \
\
# in PHP 7.4+, the pecl/pear installers are officially deprecated (requiring an explicit "--with-pear")
--with-pear \
\
# bundled pcre does not support JIT on riscv64 until 10.41 (php 8.3+)
# https://github.com/PCRE2Project/pcre2/commits/pcre2-10.41/src/sljit/sljitNativeRISCV_64.c
# https://github.com/php/php-src/tree/php-8.3.0/ext/pcre/pcre2lib
$(test "$gnuArch" = 'riscv64-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
# https://github.com/docker-library/php/pull/939#issuecomment-730501748
--enable-embed \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find \
/usr/local \
-type f \
-perm '/0111' \
-exec sh -euxc ' \
strip --strip-all "$@" || : \
' -- '{}' + \
; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); printf "*%s\n", so }' \
| sort -u \
| xargs -rt dpkg-query --search \
# https://manpages.debian.org/trixie/dpkg/dpkg-query.1.en.html#S (we ignore diversions and it'll be really unusual for more than one package to provide any given .so file)
| awk 'sub(":$", "", $1) { print $1 }' \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
apt-get dist-clean; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.3 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/8.1 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/cli /usr/local/bin/docker-php-entrypoint
# enable OPcache by default (https://wiki.php.net/rfc/make_opcache_required)
RUN docker-php-ext-enable opcache
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
ENTRYPOINT ["docker-php-entrypoint"]
CMD ["php", "-a"]
+298
View File
@@ -0,0 +1,298 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/5c037abaf9dc0095e29807c048d9d1b97e6a9716/8.1/alpine3.21/fpm),
# with the changes marked "chialab:".
#
FROM alpine:3.21
# dependencies required for running "phpize"
# these get automatically installed and removed by "docker-php-ext-*" (unless they're already installed)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev dpkg \
file \
g++ \
gcc \
libc-dev \
make \
pkgconf \
re2c
# persistent / runtime deps
RUN apk add --no-cache \
ca-certificates \
curl \
openssl \
tar \
xz
# ensure www-data user exists
RUN set -eux; \
adduser -u 82 -D -S -G www-data www-data
# 82 is the standard uid/gid for "www-data" in Alpine
# https://git.alpinelinux.org/aports/tree/main/apache2/apache2.pre-install?h=3.14-stable
# https://git.alpinelinux.org/aports/tree/main/lighttpd/lighttpd.pre-install?h=3.14-stable
# https://git.alpinelinux.org/aports/tree/main/nginx/nginx.pre-install?h=3.14-stable
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 1777 /var/www/html
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS 528995BFEDFBA7191D46839EF9BA0ADA31CBD89E 39B641343D8C104B2B146DC3F9C39DC0B9698544 F1F692238FBC1666E5A5CCD4199F9DFEF6FFBAFD
ENV PHP_VERSION 8.1.34
ENV PHP_URL="https://www.php.net/distributions/php-8.1.34.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-8.1.34.tar.xz.asc"
ENV PHP_SHA256="ffa9e0982e82eeaea848f57687b425ed173aa278fe563001310ae2638db5c251"
RUN set -eux; \
\
apk add --no-cache --virtual .fetch-deps gnupg; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
\
apk del --no-network .fetch-deps
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=8.1,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
argon2-dev \
coreutils \
curl-dev \
gnu-libiconv-dev \
libsodium-dev \
libxml2-dev \
linux-headers \
oniguruma-dev \
openssl-dev \
patch \
patchutils \
readline-dev \
sqlite-dev \
; \
\
# make sure musl's iconv doesn't get used (https://www.php.net/manual/en/intro.iconv.php)
rm -vf /usr/include/iconv.h; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
# https://github.com/php/php-src/blob/d6299206dd828382753453befd1b915491b741c6/configure.ac#L1496-L1511
PHP_BUILD_PROVIDER='https://github.com/docker-library/php' \
PHP_UNAME='Linux - Docker' \
; \
docker-php-source extract; \
cd /usr/src/php; \
# Apply patches; see https://github.com/docker-library/php/pull/1552
# https://github.com/php/php-src/issues/11678
curl -fL 'https://github.com/php/php-src/commit/577b8ae4226368e66fee7a9b5c58f9e2428372fc.patch?full_index=1' -o 11678.patch; \
echo '6edc20c3bb3e7cc13515abce7f2fffa8ebea6cf7469abfbc78fcdc120350b239 *11678.patch' | sha256sum -c -; \
patch -p1 < 11678.patch; \
rm 11678.patch; \
# https://github.com/php/php-src/pull/19131
# this backported commit broke our ability to apply 14834, which is the fix we need, so this is applied as a reverse patch to undo it
# 19131 was for FreeBSD, so doesn't apply to this alpine build
curl -fL 'https://github.com/php/php-src/commit/a5df26691d1b1f71b964b869510473a5d5413999.patch?full_index=1' -o 19131.patch; \
echo 'c98c01c74d3a6da197116f8511b16fed361ca6bbb6a8af8df629a933f541c213 *19131.patch' | sha256sum -c -; \
patch --reverse -p1 < 19131.patch; \
rm 19131.patch; \
# https://github.com/php/php-src/issues/14834
curl -fL 'https://github.com/php/php-src/commit/67259e451d5d58b4842776c5696a66d74e157609.patch?full_index=1' -o 14834.patch; \
echo 'ed10a1b254091ad676ed204e55628ecbd6c8962004d6185a1821cedecd526c0f *14834.patch' | sha256sum -c -; \
filterdiff -x '*/NEWS' 14834.patch | patch -p1; \
rm 14834.patch; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here for compatibility with existing versions. ftp_ssl_connect() needed ftp to be compiled statically before PHP 7.0 (see https://github.com/docker-library/php/issues/236).
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-iconv=/usr \
--with-openssl \
--with-readline \
--with-zlib \
\
# https://github.com/bwoebi/phpdbg-docs/issues/1#issuecomment-163872806 ("phpdbg is primarily a CLI debugger, and is not suitable for debugging an fpm stack.")
--disable-phpdbg \
\
# in PHP 7.4+, the pecl/pear installers are officially deprecated (requiring an explicit "--with-pear")
--with-pear \
\
# bundled pcre does not support JIT on riscv64 until 10.41 (php 8.3+)
# https://github.com/PCRE2Project/pcre2/commits/pcre2-10.41/src/sljit/sljitNativeRISCV_64.c
# https://github.com/php/php-src/tree/php-8.3.0/ext/pcre/pcre2lib
$(test "$gnuArch" = 'riscv64-linux-musl' && echo '--without-pcre-jit') \
\
--disable-cgi \
\
--enable-fpm \
--with-fpm-user=www-data \
--with-fpm-group=www-data \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find \
/usr/local \
-type f \
-perm '/0111' \
-exec sh -euxc ' \
strip --strip-all "$@" || : \
' -- '{}' + \
; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)"; \
apk add --no-cache $runDeps; \
\
apk del --no-network .build-deps; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.3 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/8.1 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/fpm /usr/local/bin/docker-php-entrypoint
# enable OPcache by default (https://wiki.php.net/rfc/make_opcache_required)
RUN docker-php-ext-enable opcache
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
ENTRYPOINT ["docker-php-entrypoint"]
WORKDIR /var/www/html
RUN set -eux; \
cd /usr/local/etc; \
if [ -d php-fpm.d ]; then \
# for some reason, upstream's php-fpm.conf.default has "include=NONE/etc/php-fpm.d/*.conf"
sed 's!=NONE/!=!g' php-fpm.conf.default | tee php-fpm.conf > /dev/null; \
cp php-fpm.d/www.conf.default php-fpm.d/www.conf; \
else \
# PHP 5.x doesn't use "include=" by default, so we'll create our own simple config that mimics PHP 7+ for consistency
mkdir php-fpm.d; \
cp php-fpm.conf.default php-fpm.d/www.conf; \
{ \
echo '[global]'; \
echo 'include=etc/php-fpm.d/*.conf'; \
} | tee php-fpm.conf; \
fi; \
{ \
echo '[global]'; \
echo 'error_log = /proc/self/fd/2'; \
echo; echo '; https://github.com/docker-library/php/pull/725#issuecomment-443540114'; echo 'log_limit = 8192'; \
echo; \
echo '[www]'; \
echo '; php-fpm closes STDOUT on startup, so sending logs to /proc/self/fd/1 does not work.'; \
echo '; https://bugs.php.net/bug.php?id=73886'; \
echo 'access.log = /proc/self/fd/2'; \
echo; \
echo 'clear_env = no'; \
echo; \
echo '; Ensure worker stdout and stderr are sent to the main error log.'; \
echo 'catch_workers_output = yes'; \
echo 'decorate_workers_output = no'; \
} | tee php-fpm.d/docker.conf; \
{ \
echo '[global]'; \
echo 'daemonize = no'; \
echo; \
echo '[www]'; \
echo 'listen = 9000'; \
} | tee php-fpm.d/zz-docker.conf; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
{ \
echo '; https://github.com/docker-library/php/issues/878#issuecomment-938595965'; \
echo 'fastcgi.logging = Off'; \
} > "$PHP_INI_DIR/conf.d/docker-fpm.ini"
# Override stop signal to stop process gracefully
# https://github.com/php/php-src/blob/17baa87faddc2550def3ae7314236826bc1b1398/sapi/fpm/php-fpm.8.in#L163
STOPSIGNAL SIGQUIT
EXPOSE 9000
CMD ["php-fpm"]
+295
View File
@@ -0,0 +1,295 @@
#
# Taken from the official PHP image's Dockerfile
# (https://github.com/docker-library/php/tree/5c037abaf9dc0095e29807c048d9d1b97e6a9716/8.1/trixie/fpm),
# with the changes marked "chialab:".
#
FROM debian:trixie-slim
# prevent Debian's PHP packages from being installed
# https://github.com/docker-library/php/pull/542
RUN set -eux; \
{ \
echo 'Package: php*'; \
echo 'Pin: release *'; \
echo 'Pin-Priority: -1'; \
} > /etc/apt/preferences.d/no-debian-php
# dependencies required for running "phpize"
# (see persistent deps below)
ENV PHPIZE_DEPS \
autoconf \
dpkg-dev \
file \
g++ \
gcc \
libc-dev \
make \
pkg-config \
re2c
# persistent / runtime deps
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
$PHPIZE_DEPS \
ca-certificates \
curl \
xz-utils \
; \
apt-get dist-clean
ENV PHP_INI_DIR /usr/local/etc/php
RUN set -eux; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
[ ! -d /var/www/html ]; \
mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; \
chmod 1777 /var/www/html
# Apply stack smash protection to functions using local buffers and alloca()
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
# Enable optimization (-O2)
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
ENV GPG_KEYS 528995BFEDFBA7191D46839EF9BA0ADA31CBD89E 39B641343D8C104B2B146DC3F9C39DC0B9698544 F1F692238FBC1666E5A5CCD4199F9DFEF6FFBAFD
ENV PHP_VERSION 8.1.34
ENV PHP_URL="https://www.php.net/distributions/php-8.1.34.tar.xz" PHP_ASC_URL="https://www.php.net/distributions/php-8.1.34.tar.xz.asc"
ENV PHP_SHA256="ffa9e0982e82eeaea848f57687b425ed173aa278fe563001310ae2638db5c251"
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends gnupg; \
apt-get dist-clean; \
\
mkdir -p /usr/src; \
cd /usr/src; \
\
curl -fsSL -o php.tar.xz "$PHP_URL"; \
\
if [ -n "$PHP_SHA256" ]; then \
echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
fi; \
\
curl -fsSL -o php.tar.xz.asc "$PHP_ASC_URL"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify php.tar.xz.asc php.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"; \
\
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false
# chialab: helper scripts are shared by all eol/ images, see eol/scripts.
COPY --from=scripts docker-php-source /usr/local/bin/
# chialab: security backports for this EOL version (see eol/patches).
ENV PHP_PATCHES="CVE-2026-109618 CVE-2026-109619"
LABEL it.chialab.php.patches="CVE-2026-109618 CVE-2026-109619"
RUN --mount=type=bind,from=patches,source=8.1,target=/usr/src/php-patches \
--mount=type=bind,from=patches,source=docker-php-source-patch,target=/usr/local/bin/docker-php-source-patch \
docker-php-source-patch /usr/src/php-patches
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
libargon2-dev \
libcurl4-openssl-dev \
libonig-dev \
libreadline-dev \
libsodium-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
zlib1g-dev \
; \
\
export \
CFLAGS="$PHP_CFLAGS" \
CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS" \
# https://github.com/php/php-src/blob/d6299206dd828382753453befd1b915491b741c6/configure.ac#L1496-L1511
PHP_BUILD_PROVIDER='https://github.com/docker-library/php' \
PHP_UNAME='Linux - Docker' \
; \
docker-php-source extract; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
# https://bugs.php.net/bug.php?id=74125
if [ ! -d /usr/include/curl ]; then \
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
fi; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
\
# make sure invalid --configure-flags are fatal errors instead of just warnings
--enable-option-checking=fatal \
\
# https://github.com/docker-library/php/issues/439
--with-mhash \
\
# https://github.com/docker-library/php/issues/822
--with-pic \
\
# --enable-ftp is included here for compatibility with existing versions. ftp_ssl_connect() needed ftp to be compiled statically before PHP 7.0 (see https://github.com/docker-library/php/issues/236).
--enable-ftp \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# https://wiki.php.net/rfc/argon2_password_hash
--with-password-argon2 \
# https://wiki.php.net/rfc/libsodium
--with-sodium=shared \
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
--with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
\
--with-curl \
--with-iconv \
--with-openssl \
--with-readline \
--with-zlib \
\
# https://github.com/bwoebi/phpdbg-docs/issues/1#issuecomment-163872806 ("phpdbg is primarily a CLI debugger, and is not suitable for debugging an fpm stack.")
--disable-phpdbg \
\
# in PHP 7.4+, the pecl/pear installers are officially deprecated (requiring an explicit "--with-pear")
--with-pear \
\
# bundled pcre does not support JIT on riscv64 until 10.41 (php 8.3+)
# https://github.com/PCRE2Project/pcre2/commits/pcre2-10.41/src/sljit/sljitNativeRISCV_64.c
# https://github.com/php/php-src/tree/php-8.3.0/ext/pcre/pcre2lib
$(test "$gnuArch" = 'riscv64-linux-gnu' && echo '--without-pcre-jit') \
--with-libdir="lib/$debMultiarch" \
\
--disable-cgi \
\
--enable-fpm \
--with-fpm-user=www-data \
--with-fpm-group=www-data \
; \
make -j "$(nproc)"; \
find -type f -name '*.a' -delete; \
make install; \
find \
/usr/local \
-type f \
-perm '/0111' \
-exec sh -euxc ' \
strip --strip-all "$@" || : \
' -- '{}' + \
; \
make clean; \
\
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
cp -v php.ini-* "$PHP_INI_DIR/"; \
\
cd /; \
docker-php-source delete; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); printf "*%s\n", so }' \
| sort -u \
| xargs -rt dpkg-query --search \
# https://manpages.debian.org/trixie/dpkg/dpkg-query.1.en.html#S (we ignore diversions and it'll be really unusual for more than one package to provide any given .so file)
| awk 'sub(":$", "", $1) { print $1 }' \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
apt-get dist-clean; \
\
# update pecl channel definitions https://github.com/docker-library/php/issues/443
pecl update-channels; \
rm -rf /tmp/pear ~/.pearrc; \
\
# smoke test
php --version
# chialab: from eol/scripts.
COPY --from=scripts docker-php-ext-configure/7.2 /usr/local/bin/docker-php-ext-configure
COPY --from=scripts docker-php-ext-enable/7.3 /usr/local/bin/docker-php-ext-enable
COPY --from=scripts docker-php-ext-install/8.1 /usr/local/bin/docker-php-ext-install
COPY --from=scripts docker-php-entrypoint/fpm /usr/local/bin/docker-php-entrypoint
# enable OPcache by default (https://wiki.php.net/rfc/make_opcache_required)
RUN docker-php-ext-enable opcache
# sodium was built as a shared module (so that it can be replaced later if so desired), so let's enable it too (https://github.com/docker-library/php/issues/598)
RUN docker-php-ext-enable sodium
ENTRYPOINT ["docker-php-entrypoint"]
WORKDIR /var/www/html
RUN set -eux; \
cd /usr/local/etc; \
if [ -d php-fpm.d ]; then \
# for some reason, upstream's php-fpm.conf.default has "include=NONE/etc/php-fpm.d/*.conf"
sed 's!=NONE/!=!g' php-fpm.conf.default | tee php-fpm.conf > /dev/null; \
cp php-fpm.d/www.conf.default php-fpm.d/www.conf; \
else \
# PHP 5.x doesn't use "include=" by default, so we'll create our own simple config that mimics PHP 7+ for consistency
mkdir php-fpm.d; \
cp php-fpm.conf.default php-fpm.d/www.conf; \
{ \
echo '[global]'; \
echo 'include=etc/php-fpm.d/*.conf'; \
} | tee php-fpm.conf; \
fi; \
{ \
echo '[global]'; \
echo 'error_log = /proc/self/fd/2'; \
echo; echo '; https://github.com/docker-library/php/pull/725#issuecomment-443540114'; echo 'log_limit = 8192'; \
echo; \
echo '[www]'; \
echo '; php-fpm closes STDOUT on startup, so sending logs to /proc/self/fd/1 does not work.'; \
echo '; https://bugs.php.net/bug.php?id=73886'; \
echo 'access.log = /proc/self/fd/2'; \
echo; \
echo 'clear_env = no'; \
echo; \
echo '; Ensure worker stdout and stderr are sent to the main error log.'; \
echo 'catch_workers_output = yes'; \
echo 'decorate_workers_output = no'; \
} | tee php-fpm.d/docker.conf; \
{ \
echo '[global]'; \
echo 'daemonize = no'; \
echo; \
echo '[www]'; \
echo 'listen = 9000'; \
} | tee php-fpm.d/zz-docker.conf; \
mkdir -p "$PHP_INI_DIR/conf.d"; \
{ \
echo '; https://github.com/docker-library/php/issues/878#issuecomment-938595965'; \
echo 'fastcgi.logging = Off'; \
} > "$PHP_INI_DIR/conf.d/docker-fpm.ini"
# Override stop signal to stop process gracefully
# https://github.com/php/php-src/blob/17baa87faddc2550def3ae7314236826bc1b1398/sapi/fpm/php-fpm.8.in#L163
STOPSIGNAL SIGQUIT
EXPOSE 9000
CMD ["php-fpm"]
+57
View File
@@ -0,0 +1,57 @@
# EOL PHP versions
The official images stop receiving updates once a PHP version reaches end of life. For those
versions we build PHP ourselves from the official images' Dockerfiles, with security patches
applied to the sources, and use the result as the base image instead of `php:<tag>`.
- `<X.Y>/<flavor>/Dockerfile`: the official Dockerfiles, one per tag suffix (`cli`, `apache`,
`fpm`, `alpine`, `fpm-alpine`).
- `scripts/`: the helper scripts copied into the images (`docker-php-*`, `apache2-foreground`),
passed to the build as the `scripts` named context.
- `patches/`: `docker-php-source-patch` and one `<X.Y>/series` of patches per version, passed to
the build as the `patches` named context.
The build picks a directory up on its own: if `eol/<X.Y>/<flavor>` exists, the Makefile and
`build-images.yml` build it as the base image. No workflow lists EOL versions.
## Adding a version
Add it once there is a security patch to apply: `make test` fails an EOL image whose
`PHP_PATCHES` is empty. Until then, keep building on the official image.
1. **Find the source.** Take the last [docker-library/php](https://github.com/docker-library/php)
commit that still has the `<X.Y>/` directory. For each flavor, pick the variant the plain
official tag pointed to: `<X.Y>/<debian-suite>/{cli,apache,fpm}` and
`<X.Y>/alpine<N>/{cli,fpm}` for `alpine` and `fpm-alpine`.
2. **Copy the Dockerfiles** to `eol/<X.Y>/<flavor>/Dockerfile`, with the header used by the
other versions linking the exact source path at that commit. Copy only the Dockerfile, not
the scripts next to it.
3. **Mark every change** with a `# chialab:` comment:
- replace the `COPY docker-php-*` and `COPY apache2-foreground` lines with
`COPY --from=scripts …` (see [Scripts](#scripts));
- add the patch step right after `docker-php-source` is copied, as in the other versions:
`ENV PHP_PATCHES`, `LABEL it.chialab.php.patches` and the `RUN` that bind-mounts
`patches/<X.Y>` and runs `docker-php-source-patch`;
- once the OS release is archived, or a download host or keyserver disappears, fix it the
same way the older versions do.
4. **Add the patches** to `patches/<X.Y>/` and list them in its `series`, with a comment
linking where each one comes from.
5. **Update the range** of EOL versions in the main [README](../README.md).
## Scripts
Each script in `scripts/` covers a range of PHP versions. Versioned scripts are named after the
first version that uses them, and serve every later version until the next file: for example,
`docker-php-ext-install/7.4` is used by both 7.4 and 8.0, and 8.1 has its own file.
Entrypoints vary by flavor rather than version, so they're named `cli` (also for `alpine`),
`fpm` (also for `fpm-alpine`) and `apache`.
When adding a version, compare each script from the docker-library directory with the newest
file in `scripts/`:
- if it's identical, point the new Dockerfile at that file;
- if it differs, add it as `scripts/<script>/<X.Y>` and point the new Dockerfile at it.
`docker-php-source` and `apache2-foreground` are the same for every version so far, so they
have no version directory. If a new version changes one of them, move it into one, like the
other scripts.
@@ -0,0 +1,529 @@
From: Arnaud Le Blanc <arnaud.lb@gmail.com>
Date: Sun, 18 Oct 2026 20:09:54 +0200
Subject: Avoid state corruption via bailout
Minimal mitigation for EOL version.
Fix GHSA-w8hw-w9fx-j79w (CVE-2026-109618)
Fix GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)
Backported from the PHP 7.4 version:
- zend_mm_safe_error_ex() keeps the PHP 5.6 way of finding the script
file and line (TSRM, EG(in_execution)).
- The overflow errors of safe_address() and _safe_emalloc_string(), and
the "String size overflow" errors of concat_function() and
add_*_to_string() (which back ZEND_CONCAT and ZEND_ADD_* in 5.6) exit
the same way.
- GPC arrays start with 2 buckets: nTableMask == 0 marks an uninitialized
hash table in 5.6, so a single bucket cannot be used.
- SG(callback_func) is also reset in sapi_deactivate().
- PHP 5.6 already clears the user error/exception handlers before
destroying them; EG(error_handling) and EG(exception) are reset after
the object store is freed.
- "|| 1" instead of "|| true" in the session upload progress callback.
- The max_multipart_body_parts hunk of the 7.4 patch is left out, the
code is already there.
Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>
---
Zend/zend_API.c | 9 ++++
Zend/zend_API.h | 2 +
Zend/zend_alloc.c | 110 +++++++++++++++++++---------------------
Zend/zend_alloc.h | 6 +++
Zend/zend_execute_API.c | 4 ++
Zend/zend_llist.c | 2 +
Zend/zend_operators.c | 8 +--
Zend/zend_strtod.c | 2 +-
ext/session/session.c | 2 +-
main/SAPI.c | 6 +++
main/main.c | 5 ++
main/php_variables.c | 6 +--
main/rfc1867.c | 27 +++++++---
13 files changed, 114 insertions(+), 75 deletions(-)
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 0757cc92..89cdca5f 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -1016,6 +1016,15 @@ ZEND_API int _array_init(zval *arg, uint size ZEND_FILE_LINE_DC) /* {{{ */
}
/* }}} */
+ZEND_API int _array_init_singleton(zval *arg ZEND_FILE_LINE_DC) /* {{{ */
+{
+ _array_init(arg, 0 ZEND_FILE_LINE_RELAY_CC);
+ /* nTableMask == 0 marks an uninitialized table, so 2 is the smallest usable size */
+ Z_ARRVAL_P(arg)->nTableSize = 2;
+ return SUCCESS;
+}
+/* }}} */
+
static int zend_merge_property(zval **value TSRMLS_DC, int num_args, va_list args, const zend_hash_key *hash_key) /* {{{ */
{
/* which name should a numeric property have ? */
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index 41aa65f2..c17dacd5 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -363,10 +363,12 @@ ZEND_API char *zend_get_type_by_const(int type);
#define array_init(arg) _array_init((arg), 0 ZEND_FILE_LINE_CC)
#define array_init_size(arg, size) _array_init((arg), (size) ZEND_FILE_LINE_CC)
+#define array_init_singleton(arg) _array_init_singleton((arg) ZEND_FILE_LINE_CC)
#define object_init(arg) _object_init((arg) ZEND_FILE_LINE_CC TSRMLS_CC)
#define object_init_ex(arg, ce) _object_init_ex((arg), (ce) ZEND_FILE_LINE_CC TSRMLS_CC)
#define object_and_properties_init(arg, ce, properties) _object_and_properties_init((arg), (ce), (properties) ZEND_FILE_LINE_CC TSRMLS_CC)
ZEND_API int _array_init(zval *arg, uint size ZEND_FILE_LINE_DC);
+ZEND_API int _array_init_singleton(zval *arg ZEND_FILE_LINE_DC);
ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC TSRMLS_DC);
ZEND_API int _object_init_ex(zval *arg, zend_class_entry *ce ZEND_FILE_LINE_DC TSRMLS_DC);
ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *ce, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC);
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
index c7babe12..f84d25ae 100644
--- a/Zend/zend_alloc.c
+++ b/Zend/zend_alloc.c
@@ -91,7 +91,7 @@ static void zend_mm_panic(const char *message)
#if ZEND_DEBUG && defined(HAVE_KILL) && defined(HAVE_GETPID)
kill(getpid(), SIGSEGV);
#endif
- exit(1);
+ _exit(1);
}
/*******************/
@@ -1740,6 +1740,42 @@ ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent
}
}
+ZEND_API void zend_mm_safe_error_ex(const char *format, ...)
+{
+ const char *error_filename;
+ uint error_lineno;
+ va_list args;
+ char buf[1024];
+ TSRMLS_FETCH();
+
+ if (zend_is_compiling(TSRMLS_C)) {
+ error_filename = zend_get_compiled_filename(TSRMLS_C);
+ error_lineno = zend_get_compiled_lineno(TSRMLS_C);
+ } else if (EG(in_execution)) {
+ error_filename = EG(active_op_array)?EG(active_op_array)->filename:NULL;
+ error_lineno = EG(opline_ptr)?(*EG(opline_ptr))->lineno:0;
+ } else {
+ error_filename = NULL;
+ error_lineno = 0;
+ }
+ if (!error_filename) {
+ error_filename = "Unknown";
+ }
+
+ va_start(args, format);
+ vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
+
+ fprintf(stderr, "\nFatal error: %s in %s on line %d\n", buf, error_filename, error_lineno);
+
+/* See http://support.microsoft.com/kb/190351 */
+#ifdef PHP_WIN32
+ fflush(stderr);
+#endif
+
+ _exit(1);
+}
+
static void zend_mm_safe_error(zend_mm_heap *heap,
const char *format,
size_t limit,
@@ -1749,59 +1785,15 @@ static void zend_mm_safe_error(zend_mm_heap *heap,
#endif
size_t size)
{
- if (heap->reserve) {
- _zend_mm_free_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
- heap->reserve = NULL;
- }
- if (heap->overflow == 0) {
- const char *error_filename;
- uint error_lineno;
- TSRMLS_FETCH();
- if (zend_is_compiling(TSRMLS_C)) {
- error_filename = zend_get_compiled_filename(TSRMLS_C);
- error_lineno = zend_get_compiled_lineno(TSRMLS_C);
- } else if (EG(in_execution)) {
- error_filename = EG(active_op_array)?EG(active_op_array)->filename:NULL;
- error_lineno = EG(opline_ptr)?(*EG(opline_ptr))->lineno:0;
- } else {
- error_filename = NULL;
- error_lineno = 0;
- }
- if (!error_filename) {
- error_filename = "Unknown";
- }
- heap->overflow = 1;
- zend_try {
- zend_error_noreturn(E_ERROR,
- format,
- limit,
+ (void) heap;
+
+ zend_mm_safe_error_ex(format,
+ limit,
#if ZEND_DEBUG
- filename,
- lineno,
+ filename,
+ lineno,
#endif
- size);
- } zend_catch {
- if (heap->overflow == 2) {
- fprintf(stderr, "\nFatal error: ");
- fprintf(stderr,
- format,
- limit,
-#if ZEND_DEBUG
- filename,
- lineno,
-#endif
- size);
- fprintf(stderr, " in %s on line %d\n", error_filename, error_lineno);
- }
-/* See http://support.microsoft.com/kb/190351 */
-#ifdef PHP_WIN32
- fflush(stderr);
-#endif
- } zend_end_try();
- } else {
- heap->overflow = 2;
- }
- zend_bailout();
+ size);
}
static zend_mm_free_block *zend_mm_search_large_block(zend_mm_heap *heap, size_t true_size)
@@ -2472,7 +2464,7 @@ static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
"rm"(offset));
if (UNEXPECTED(overflow)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
return 0;
}
return res;
@@ -2501,7 +2493,7 @@ static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
#undef LP_SUFF
if (UNEXPECTED(overflow)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
return 0;
}
return res;
@@ -2522,7 +2514,7 @@ static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
"1"(0));
if (UNEXPECTED(overflow)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
return 0;
}
return res;
@@ -2542,7 +2534,7 @@ static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
"r"(offset));
if (UNEXPECTED(overflow)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
return 0;
}
return res;
@@ -2555,7 +2547,7 @@ static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
zend_ulong64 res = (zend_ulong64)nmemb * (zend_ulong64)size + (zend_ulong64)offset;
if (UNEXPECTED(res > (zend_ulong64)0xFFFFFFFFL)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
return 0;
}
return (size_t) res;
@@ -2570,7 +2562,7 @@ static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
double _delta = (double)res - _d;
if (UNEXPECTED((_d + _delta ) != _d)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
return 0;
}
return res;
@@ -2582,7 +2574,7 @@ ZEND_API void *_safe_emalloc_string(size_t nmemb, size_t size, size_t offset ZEN
{
size_t str_size = safe_address(nmemb, size, offset);
if (UNEXPECTED(str_size > INT_MAX)) {
- zend_error_noreturn(E_ERROR, "String allocation overflow, max size is %d", INT_MAX);
+ zend_mm_safe_error_ex("String allocation overflow, max size is %d", INT_MAX);
}
return emalloc_rel(str_size);
}
diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h
index 719f9c5c..dab0599a 100644
--- a/Zend/zend_alloc.h
+++ b/Zend/zend_alloc.h
@@ -57,6 +57,12 @@ ZEND_API char *zend_strndup(const char *s, unsigned int length) ZEND_ATTRIBUTE_M
ZEND_API void *_emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE(1);
ZEND_API void *_safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
ZEND_API void *_safe_emalloc_string(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
+
+#if defined(__GNUC__) && __GNUC__ >= 3 && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX) && !defined(__osf__)
+ZEND_API void zend_mm_safe_error_ex(const char *format, ...) __attribute__ ((noreturn));
+#else
+ZEND_API void zend_mm_safe_error_ex(const char *format, ...);
+#endif
ZEND_API void *_safe_malloc(size_t nmemb, size_t size, size_t offset) ZEND_ATTRIBUTE_MALLOC;
ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
ZEND_API void *_ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE2(1,2);
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index bf754d25..a7a7b9ba 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -307,6 +307,10 @@ void shutdown_executor(TSRMLS_D) /* {{{ */
}
} zend_end_try();
+ /* may be used by zend_error before init_executor */
+ EG(error_handling) = EH_NORMAL;
+ EG(exception) = NULL;
+
zend_try {
clean_non_persistent_constants(TSRMLS_C);
} zend_end_try();
diff --git a/Zend/zend_llist.c b/Zend/zend_llist.c
index 3d597a37..5be49408 100644
--- a/Zend/zend_llist.c
+++ b/Zend/zend_llist.c
@@ -115,6 +115,8 @@ ZEND_API void zend_llist_destroy(zend_llist *l)
current = next;
}
+ l->head = NULL;
+ l->tail = NULL;
l->count = 0;
}
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index 450153ff..192592b0 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -1400,7 +1400,7 @@ ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2)
char *buf;
if (UNEXPECTED(length < 0)) {
- zend_error(E_ERROR, "String size overflow");
+ zend_mm_safe_error_ex("String size overflow");
}
buf = str_erealloc(Z_STRVAL_P(op1), length + 1);
@@ -1419,7 +1419,7 @@ ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2
char *buf;
if (UNEXPECTED(length < 0)) {
- zend_error(E_ERROR, "String size overflow");
+ zend_mm_safe_error_ex("String size overflow");
}
buf = str_erealloc(Z_STRVAL_P(op1), length + 1);
@@ -1465,7 +1465,7 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{
if (Z_STRLEN_P(result) < 0 || (int) (Z_STRLEN_P(op1) + Z_STRLEN_P(op2)) < 0) {
efree(Z_STRVAL_P(result));
ZVAL_EMPTY_STRING(result);
- zend_error(E_ERROR, "String size overflow");
+ zend_mm_safe_error_ex("String size overflow");
}
Z_STRVAL_P(result) = safe_erealloc(Z_STRVAL_P(result), res_len, 1, 1);
@@ -1478,7 +1478,7 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{
char *buf;
if (Z_STRLEN_P(op1) < 0 || Z_STRLEN_P(op2) < 0 || (int) (Z_STRLEN_P(op1) + Z_STRLEN_P(op2)) < 0) {
- zend_error(E_ERROR, "String size overflow");
+ zend_mm_safe_error_ex("String size overflow");
}
buf = (char *) safe_emalloc(length, 1, 1);
diff --git a/Zend/zend_strtod.c b/Zend/zend_strtod.c
index 7ec0366e..a035a154 100644
--- a/Zend/zend_strtod.c
+++ b/Zend/zend_strtod.c
@@ -501,7 +501,7 @@ static Bigint * Balloc(int k)
rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(Long));
if (!rv) {
_THREAD_PRIVATE_MUTEX_UNLOCK(dtoa_mutex);
- zend_error(E_ERROR, "Balloc() failed to allocate memory");
+ zend_mm_safe_error_ex("Balloc() failed to allocate memory");
}
rv->k = k;
rv->maxwds = x;
diff --git a/ext/session/session.c b/ext/session/session.c
index 2fe9651a..650ef174 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -2669,7 +2669,7 @@ static int php_session_rfc1867_callback(unsigned int event, void *event_data, vo
if (php_session_rfc1867_orig_callback) {
retval = php_session_rfc1867_orig_callback(event, event_data, extra TSRMLS_CC);
}
- if (!PS(rfc1867_enabled)) {
+ if (!PS(rfc1867_enabled) || 1) {
return retval;
}
diff --git a/main/SAPI.c b/main/SAPI.c
index 49ffc1c9..660012da 100644
--- a/main/SAPI.c
+++ b/main/SAPI.c
@@ -528,18 +528,23 @@ SAPI_API void sapi_deactivate(TSRMLS_D)
}
if (SG(request_info).auth_user) {
efree(SG(request_info).auth_user);
+ SG(request_info).auth_user = NULL;
}
if (SG(request_info).auth_password) {
efree(SG(request_info).auth_password);
+ SG(request_info).auth_password = NULL;
}
if (SG(request_info).auth_digest) {
efree(SG(request_info).auth_digest);
+ SG(request_info).auth_digest = NULL;
}
if (SG(request_info).content_type_dup) {
efree(SG(request_info).content_type_dup);
+ SG(request_info).content_type_dup = NULL;
}
if (SG(request_info).current_user) {
efree(SG(request_info).current_user);
+ SG(request_info).current_user = NULL;
}
if (sapi_module.deactivate) {
sapi_module.deactivate(TSRMLS_C);
@@ -557,6 +562,7 @@ SAPI_API void sapi_deactivate(TSRMLS_D)
SG(callback_run) = 0;
if (SG(callback_func)) {
zval_ptr_dtor(&SG(callback_func));
+ SG(callback_func) = NULL;
}
SG(request_info).headers_read = 0;
SG(global_request_time) = 0;
diff --git a/main/main.c b/main/main.c
index ab55b5b8..1f6618bd 100644
--- a/main/main.c
+++ b/main/main.c
@@ -1880,6 +1880,8 @@ void php_request_shutdown(void *dummy)
for (i=0; i<NUM_TRACK_VARS; i++) {
if (PG(http_globals)[i]) {
zval_ptr_dtor(&PG(http_globals)[i]);
+ /* May be accessed before php_request_startup() */
+ PG(http_globals)[i] = NULL;
}
}
} zend_end_try();
@@ -1937,6 +1939,9 @@ void php_request_shutdown(void *dummy)
#ifdef HAVE_DTRACE
DTRACE_REQUEST_SHUTDOWN(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), (char *)SAFE_FILENAME(SG(request_info).request_method));
#endif /* HAVE_DTRACE */
+
+ /* May be accessed before php_request_startup() */
+ PG(modules_activated) = 0;
}
/* }}} */
diff --git a/main/php_variables.c b/main/php_variables.c
index fbd9562e..606a4b03 100644
--- a/main/php_variables.c
+++ b/main/php_variables.c
@@ -191,7 +191,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
if (!index) {
MAKE_STD_ZVAL(gpc_element);
- array_init(gpc_element);
+ array_init_singleton(gpc_element);
if (zend_hash_next_index_insert(symtable1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p) == FAILURE) {
zval_ptr_dtor(&gpc_element);
zval_dtor(val);
@@ -208,7 +208,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
if (zend_symtable_find(symtable1, index, index_len + 1, (void **) &gpc_element_p) == FAILURE
|| Z_TYPE_PP(gpc_element_p) != IS_ARRAY) {
MAKE_STD_ZVAL(gpc_element);
- array_init(gpc_element);
+ array_init_singleton(gpc_element);
zend_symtable_update(symtable1, index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p);
}
}
@@ -406,7 +406,7 @@ SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
case PARSE_GET:
case PARSE_COOKIE:
ALLOC_ZVAL(array_ptr);
- array_init(array_ptr);
+ array_init_singleton(array_ptr);
INIT_PZVAL(array_ptr);
switch (arg) {
case PARSE_POST:
diff --git a/main/rfc1867.c b/main/rfc1867.c
index 2b3e47f9..fdb671d2 100644
--- a/main/rfc1867.c
+++ b/main/rfc1867.c
@@ -400,6 +400,14 @@ static int find_boundary(multipart_buffer *self, char *boundary TSRMLS_DC)
return 0;
}
+static zend_bool php_mime_should_save_hdr(const char *name)
+{
+ return !strcasecmp(name, "Content-Disposition")
+ || !strcasecmp(name, "Content-Type");
+}
+
+static char *php_mime_get_hdr_value(zend_llist header, char *key);
+
/* parse headers */
static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header TSRMLS_DC)
{
@@ -441,10 +449,15 @@ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header T
}
*value = '\0';
- do { value++; } while(isspace(*value));
-
- key = estrdup(line);
- smart_str_appends(&buf_value, value);
+ /* Keep only headers we use, and ignore duplicates */
+ if (!php_mime_should_save_hdr(line)
+ || php_mime_get_hdr_value(*header, line)) {
+ key = NULL;
+ } else {
+ key = estrdup(line);
+ do { value++; } while(isspace(*value));
+ smart_str_appends(&buf_value, value);
+ }
} else if (buf_value.c) { /* If no ':' on the line, add to previous line */
smart_str_appends(&buf_value, line);
} else {
@@ -517,11 +530,11 @@ static char *php_ap_getword(const zend_encoding *encoding, char **line, char sto
return res;
}
-static char *substring_conf(char *start, int len, char quote)
+static char *substring_conf(char *start, size_t len, char quote)
{
char *result = emalloc(len + 1);
char *resp = result;
- int i;
+ size_t i;
for (i = 0; i < len && start[i] != quote; ++i) {
if (start[i] == '\\' && (start[i + 1] == '\\' || (quote && start[i + 1] == quote))) {
@@ -556,7 +569,7 @@ static char *php_ap_getword_conf(const zend_encoding *encoding, char *str TSRMLS
while (*strend && !isspace(*strend)) {
++strend;
}
- return substring_conf(str, strend - str, 0);
+ return substring_conf(str, (size_t)(strend - str), 0);
}
}
+2
View File
@@ -0,0 +1,2 @@
# https://salsa.debian.org/php-team/php/-/tree/7401dd5c10042b6b875370027d775f9c542171b8/debian/patches (Sury 5.6.40-104)
0261-Avoid-state-corruption-via-bailout.patch
@@ -0,0 +1,25 @@
From: Remi Collet <remi@remirepo.net>
Date: Fri, 22 Nov 2024 15:24:16 +0100
Subject: backport ZSTR_MAX_LEN
(cherry picked from commit 37056ad634d9c44bac0d6c8e730eafaec1344840)
(cherry picked from commit ff868946218d6d1661a0c35757e2058cb3ed23ec)
(cherry picked from commit 351dee5281697c14712e261f560d671e1661e51a)
---
Zend/zend_string.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Zend/zend_string.h b/Zend/zend_string.h
index 113e5ca..e3286e1 100644
--- a/Zend/zend_string.h
+++ b/Zend/zend_string.h
@@ -61,6 +61,9 @@ END_EXTERN_C()
#define _ZSTR_STRUCT_SIZE(len) (_ZSTR_HEADER_SIZE + len + 1)
+#define ZSTR_MAX_OVERHEAD (ZEND_MM_ALIGNED_SIZE(_ZSTR_HEADER_SIZE + 1))
+#define ZSTR_MAX_LEN (SIZE_MAX - ZSTR_MAX_OVERHEAD)
+
#define ZSTR_ALLOCA_ALLOC(str, _len, use_heap) do { \
(str) = (zend_string *)do_alloca(ZEND_MM_ALIGNED_SIZE_EX(_ZSTR_STRUCT_SIZE(_len), 8), (use_heap)); \
GC_REFCOUNT(str) = 1; \
@@ -0,0 +1,701 @@
From: Arnaud Le Blanc <arnaud.lb@gmail.com>
Date: Sun, 18 Oct 2026 20:09:54 +0200
Subject: Avoid state corruption via bailout
Minimal mitigation for EOL version.
Fix GHSA-w8hw-w9fx-j79w (CVE-2026-109618)
Fix GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)
Backported from the PHP 7.4 version:
- There is no fast shutdown in shutdown_executor() before PHP 7.2 (the
opcache one runs before the error handlers are destroyed), so the user
error/exception handlers, EG(error_handling) and EG(exception) are reset
after the cleanup blocks, where a bailout cannot skip it.
- array_init_singleton() is implemented in zend_API.c, there is no
zend_new_array(); HT_HASH_RESET() uses memset(), so the SSE2 change is
not needed.
- ZEND_FAST_CONCAT has no string fast path, so only ZEND_CONCAT gets the
length checks.
- "|| 1" instead of "|| true" in the session upload progress callback
(no stdbool.h).
- The max_multipart_body_parts hunk of the 7.4 patch is left out, the
code is already there.
- ZEND_CONCAT uses zend_string_realloc(); the estrdup() and hash table
overflow messages use the 7.1+ formats (the old ones passed int
arguments for %zu, which vsnprintf() cannot take).
Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>
---
Zend/zend_API.c | 8 +++++
Zend/zend_API.h | 2 ++
Zend/zend_alloc.c | 66 +++++++++++++++++++++++++++++------------
Zend/zend_alloc.h | 2 ++
Zend/zend_execute_API.c | 8 +++++
Zend/zend_hash.c | 6 ++--
Zend/zend_llist.c | 2 ++
Zend/zend_multiply.h | 4 +--
Zend/zend_strtod.c | 4 +--
Zend/zend_vm_def.h | 6 ++++
Zend/zend_vm_execute.h | 54 +++++++++++++++++++++++++++++++++
ext/session/session.c | 2 +-
main/SAPI.c | 5 ++++
main/main.c | 5 ++++
main/php_variables.c | 8 ++---
main/rfc1867.c | 29 +++++++++++++-----
16 files changed, 172 insertions(+), 39 deletions(-)
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index d7b22791..8622ef67 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -1062,6 +1062,14 @@ ZEND_API int _array_init(zval *arg, uint32_t size ZEND_FILE_LINE_DC) /* {{{ */
}
/* }}} */
+ZEND_API int _array_init_singleton(zval *arg ZEND_FILE_LINE_DC) /* {{{ */
+{
+ _array_init(arg, 0 ZEND_FILE_LINE_RELAY_CC);
+ Z_ARRVAL_P(arg)->nTableSize = 1;
+ return SUCCESS;
+}
+/* }}} */
+
/* This function should be called after the constructor has been called
* because it may call __set from the uninitialized object otherwise. */
ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index 9f2e2c6b..a1cd888b 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -375,10 +375,12 @@ ZEND_API char *zend_get_type_by_const(int type);
#define array_init(arg) _array_init((arg), 0 ZEND_FILE_LINE_CC)
#define array_init_size(arg, size) _array_init((arg), (size) ZEND_FILE_LINE_CC)
+#define array_init_singleton(arg) _array_init_singleton((arg) ZEND_FILE_LINE_CC)
#define object_init(arg) _object_init((arg) ZEND_FILE_LINE_CC)
#define object_init_ex(arg, ce) _object_init_ex((arg), (ce) ZEND_FILE_LINE_CC)
#define object_and_properties_init(arg, ce, properties) _object_and_properties_init((arg), (ce), (properties) ZEND_FILE_LINE_CC)
ZEND_API int _array_init(zval *arg, uint32_t size ZEND_FILE_LINE_DC);
+ZEND_API int _array_init_singleton(zval *arg ZEND_FILE_LINE_DC);
ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC);
ZEND_API int _object_init_ex(zval *arg, zend_class_entry *ce ZEND_FILE_LINE_DC);
ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *ce, HashTable *properties ZEND_FILE_LINE_DC);
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
index be41aa3e..62c72a33 100644
--- a/Zend/zend_alloc.c
+++ b/Zend/zend_alloc.c
@@ -58,6 +58,7 @@
#include "zend_globals.h"
#include "zend_operators.h"
#include "zend_multiply.h"
+#include "zend_execute.h"
#ifdef HAVE_SIGNAL_H
# include <signal.h>
@@ -369,7 +370,42 @@ static ZEND_COLD ZEND_NORETURN void zend_mm_panic(const char *message)
#if ZEND_DEBUG && defined(HAVE_KILL) && defined(HAVE_GETPID)
kill(getpid(), SIGSEGV);
#endif
- exit(1);
+ _exit(1);
+}
+
+ZEND_API ZEND_COLD ZEND_NORETURN void zend_mm_safe_error_ex(const char *format, ...)
+{
+ zend_string *script_filename = NULL;
+ uint32_t script_lineno = 0;
+
+ if (zend_is_executing()) {
+ script_filename = zend_get_executed_filename_ex();
+ script_lineno = zend_get_executed_lineno();
+ } else if (zend_is_compiling()) {
+ script_filename = zend_get_compiled_filename();
+ script_lineno = zend_get_compiled_lineno();
+ }
+
+ va_list args;
+ va_start(args, format);
+
+ char buf[1024];
+ vsnprintf(buf, sizeof(buf), format, args);
+
+ va_end(args);
+
+ fprintf(stderr,
+ "\nFatal error: %s in %s on line %d\n",
+ buf,
+ script_filename ? ZSTR_VAL(script_filename) : "Unknown",
+ script_lineno);
+
+ /* See http://support.microsoft.com/kb/190351 */
+# ifdef ZEND_WIN32
+ fflush(stderr);
+# endif
+
+ _exit(1);
}
static ZEND_COLD ZEND_NORETURN void zend_mm_safe_error(zend_mm_heap *heap,
@@ -381,22 +417,14 @@ static ZEND_COLD ZEND_NORETURN void zend_mm_safe_error(zend_mm_heap *heap,
#endif
size_t size)
{
+ (void) heap;
- heap->overflow = 1;
- zend_try {
- zend_error_noreturn(E_ERROR,
- format,
- limit,
+ zend_mm_safe_error_ex(format, limit,
#if ZEND_DEBUG
- filename,
- lineno,
+ filename,
+ lineno,
#endif
- size);
- } zend_catch {
- } zend_end_try();
- heap->overflow = 0;
- zend_bailout();
- exit(1);
+ size);
}
#ifdef _WIN32
@@ -1381,7 +1409,7 @@ static zend_always_inline void *zend_mm_alloc_heap(zend_mm_heap *heap, size_t si
size = MAX(size, 1);
size = ZEND_MM_ALIGNED_SIZE(size) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info));
if (UNEXPECTED(size < real_size)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu + %zu)", ZEND_MM_ALIGNED_SIZE(real_size), ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu + %zu)", ZEND_MM_ALIGNED_SIZE(real_size), ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
return NULL;
}
#endif
@@ -2567,7 +2595,7 @@ ZEND_API char* ZEND_FASTCALL _estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_
length = strlen(s);
if (UNEXPECTED(length + 1 == 0)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", 1, length, 1);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length);
}
p = (char *) _emalloc(length + 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
if (UNEXPECTED(p == NULL)) {
@@ -2582,7 +2610,7 @@ ZEND_API char* ZEND_FASTCALL _estrndup(const char *s, size_t length ZEND_FILE_LI
char *p;
if (UNEXPECTED(length + 1 == 0)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", 1, length, 1);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length);
}
p = (char *) _emalloc(length + 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
if (UNEXPECTED(p == NULL)) {
@@ -2599,7 +2627,7 @@ ZEND_API char* ZEND_FASTCALL zend_strndup(const char *s, size_t length)
char *p;
if (UNEXPECTED(length + 1 == 0)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", 1, length, 1);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length);
}
p = (char *) malloc(length + 1);
if (UNEXPECTED(p == NULL)) {
@@ -2874,7 +2902,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
static ZEND_COLD ZEND_NORETURN void zend_out_of_memory(void)
{
fprintf(stderr, "Out of memory\n");
- exit(1);
+ _exit(1);
}
ZEND_API void * __zend_malloc(size_t len)
diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h
index 529bd618..d8fc31a3 100644
--- a/Zend/zend_alloc.h
+++ b/Zend/zend_alloc.h
@@ -392,6 +392,8 @@ static void apc_init_heap(void)
*/
+ZEND_API ZEND_COLD ZEND_NORETURN void zend_mm_safe_error_ex(const char *format, ...);
+
END_EXTERN_C()
#endif
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index ff2d22f1..b083a782 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -299,6 +299,10 @@ void shutdown_executor(void) /* {{{ */
zend_stack_clean(&EG(user_exception_handlers), (void (*)(void *))ZVAL_PTR_DTOR, 1);
} zend_end_try();
+ /* may be used by zend_error before init_executor */
+ ZVAL_UNDEF(&EG(user_error_handler));
+ ZVAL_UNDEF(&EG(user_exception_handler));
+
zend_try {
/* Cleanup static data for functions and arrays.
* We need a separate cleanup stage because of the following problem:
@@ -378,6 +382,10 @@ void shutdown_executor(void) /* {{{ */
}
} zend_end_try();
+ /* may be used by zend_error before init_executor */
+ EG(error_handling) = EH_NORMAL;
+ EG(exception) = NULL;
+
zend_try {
#if 0&&ZEND_DEBUG
signal(SIGSEGV, original_sigsegv_handler);
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index 9a1b10bb..44508684 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -103,7 +103,7 @@ static uint32_t zend_always_inline zend_hash_check_size(uint32_t nSize)
if (nSize < HT_MIN_SIZE) {
nSize = HT_MIN_SIZE;
} else if (UNEXPECTED(nSize >= HT_MAX_SIZE)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nSize, sizeof(Bucket), sizeof(Bucket));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", nSize, sizeof(Bucket), sizeof(Bucket));
}
#if defined(ZEND_WIN32)
@@ -189,7 +189,7 @@ static void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht)
{
HT_ASSERT(GC_REFCOUNT(ht) == 1);
if (ht->nTableSize >= HT_MAX_SIZE) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket));
}
HANDLE_BLOCK_INTERRUPTIONS();
ht->nTableSize += ht->nTableSize;
@@ -893,7 +893,7 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
zend_hash_rehash(ht);
HANDLE_UNBLOCK_INTERRUPTIONS();
} else {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket) + sizeof(uint32_t), sizeof(Bucket));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket) + sizeof(uint32_t), sizeof(Bucket));
}
}
diff --git a/Zend/zend_llist.c b/Zend/zend_llist.c
index 677b7da4..f9f7abbb 100644
--- a/Zend/zend_llist.c
+++ b/Zend/zend_llist.c
@@ -114,6 +114,8 @@ ZEND_API void zend_llist_destroy(zend_llist *l)
current = next;
}
+ l->head = NULL;
+ l->tail = NULL;
l->count = 0;
}
diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h
index c66e1924..e535a1ff 100644
--- a/Zend/zend_multiply.h
+++ b/Zend/zend_multiply.h
@@ -272,7 +272,7 @@ static zend_always_inline size_t zend_safe_address_guarded(size_t nmemb, size_t
size_t ret = zend_safe_address(nmemb, size, offset, &overflow);
if (UNEXPECTED(overflow)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
return 0;
}
return ret;
@@ -285,7 +285,7 @@ static zend_always_inline size_t zend_safe_addmult(size_t nmemb, size_t size, si
size_t ret = zend_safe_address(nmemb, size, offset, &overflow);
if (UNEXPECTED(overflow)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in %s (%zu * %zu + %zu)", message, nmemb, size, offset);
+ zend_mm_safe_error_ex("Possible integer overflow in %s (%zu * %zu + %zu)", message, nmemb, size, offset);
return 0;
}
return ret;
diff --git a/Zend/zend_strtod.c b/Zend/zend_strtod.c
index d15048b7..d2f73822 100644
--- a/Zend/zend_strtod.c
+++ b/Zend/zend_strtod.c
@@ -600,7 +600,7 @@ Balloc
rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
if (!rv) {
FREE_DTOA_LOCK(0);
- zend_error_noreturn(E_ERROR, "Balloc() failed to allocate memory");
+ zend_mm_safe_error_ex("Balloc() failed to allocate memory");
}
#else
len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
@@ -613,7 +613,7 @@ Balloc
rv = (Bigint*)MALLOC(len*sizeof(double));
if (!rv) {
FREE_DTOA_LOCK(0);
- zend_error_noreturn(E_ERROR, "Balloc() failed to allocate memory");
+ zend_mm_safe_error_ex("Balloc() failed to allocate memory");
}
#endif
rv->k = k;
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index b2f9bbdf..3832471f 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -290,11 +290,17 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_realloc(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 1fd66037..9eecd684 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -4602,11 +4602,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CONST_HANDLE
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_realloc(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -8638,11 +8644,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_realloc(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -10521,11 +10533,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_realloc(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -30441,11 +30459,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_realloc(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -35757,11 +35781,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_realloc(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -38475,11 +38505,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER(
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_realloc(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -41529,11 +41565,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_realloc(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -43947,11 +43989,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER(
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_realloc(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -45096,11 +45144,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_realloc(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
diff --git a/ext/session/session.c b/ext/session/session.c
index 48a15b67..0d76b9b0 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -2960,7 +2960,7 @@ static int php_session_rfc1867_callback(unsigned int event, void *event_data, vo
if (php_session_rfc1867_orig_callback) {
retval = php_session_rfc1867_orig_callback(event, event_data, extra);
}
- if (!PS(rfc1867_enabled)) {
+ if (!PS(rfc1867_enabled) || 1) {
return retval;
}
diff --git a/main/SAPI.c b/main/SAPI.c
index 018ef23b..e9854aca 100644
--- a/main/SAPI.c
+++ b/main/SAPI.c
@@ -516,18 +516,23 @@ SAPI_API void sapi_deactivate(void)
}
if (SG(request_info).auth_user) {
efree(SG(request_info).auth_user);
+ SG(request_info).auth_user = NULL;
}
if (SG(request_info).auth_password) {
efree(SG(request_info).auth_password);
+ SG(request_info).auth_password = NULL;
}
if (SG(request_info).auth_digest) {
efree(SG(request_info).auth_digest);
+ SG(request_info).auth_digest = NULL;
}
if (SG(request_info).content_type_dup) {
efree(SG(request_info).content_type_dup);
+ SG(request_info).content_type_dup = NULL;
}
if (SG(request_info).current_user) {
efree(SG(request_info).current_user);
+ SG(request_info).current_user = NULL;
}
if (sapi_module.deactivate) {
sapi_module.deactivate();
diff --git a/main/main.c b/main/main.c
index 91f9ead1..eec25c7c 100644
--- a/main/main.c
+++ b/main/main.c
@@ -1844,6 +1844,8 @@ void php_request_shutdown(void *dummy)
for (i=0; i<NUM_TRACK_VARS; i++) {
zval_ptr_dtor(&PG(http_globals)[i]);
+ /* May be accessed before php_request_startup() */
+ ZVAL_UNDEF(&PG(http_globals)[i]);
}
} zend_end_try();
@@ -1897,6 +1899,9 @@ void php_request_shutdown(void *dummy)
#ifdef HAVE_DTRACE
DTRACE_REQUEST_SHUTDOWN(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), (char *)SAFE_FILENAME(SG(request_info).request_method));
#endif /* HAVE_DTRACE */
+
+ /* May be accessed before php_request_startup() */
+ PG(modules_activated) = 0;
}
/* }}} */
diff --git a/main/php_variables.c b/main/php_variables.c
index 46de3477..afeb88cb 100644
--- a/main/php_variables.c
+++ b/main/php_variables.c
@@ -187,7 +187,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
}
if (!index) {
- array_init(&gpc_element);
+ array_init_singleton(&gpc_element);
if ((gpc_element_p = zend_hash_next_index_insert(symtable1, &gpc_element)) == NULL) {
zval_ptr_dtor(&gpc_element);
zval_dtor(val);
@@ -204,7 +204,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
gpc_element_p = zend_symtable_str_find(symtable1, index, index_len);
if (!gpc_element_p) {
zval tmp;
- array_init(&tmp);
+ array_init_singleton(&tmp);
gpc_element_p = zend_symtable_str_update_ind(symtable1, index, index_len, &tmp);
} else {
if (Z_TYPE_P(gpc_element_p) == IS_INDIRECT) {
@@ -212,7 +212,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
}
if (Z_TYPE_P(gpc_element_p) != IS_ARRAY) {
zval_ptr_dtor(gpc_element_p);
- array_init(gpc_element_p);
+ array_init_singleton(gpc_element_p);
}
}
}
@@ -405,7 +405,7 @@ SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
case PARSE_POST:
case PARSE_GET:
case PARSE_COOKIE:
- array_init(&array);
+ array_init_singleton(&array);
switch (arg) {
case PARSE_POST:
zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_POST]);
diff --git a/main/rfc1867.c b/main/rfc1867.c
index 5d255ae3..672da20d 100644
--- a/main/rfc1867.c
+++ b/main/rfc1867.c
@@ -405,6 +405,14 @@ static int find_boundary(multipart_buffer *self, char *boundary)
return 0;
}
+static zend_bool php_mime_should_save_hdr(const char *name)
+{
+ return !strcasecmp(name, "Content-Disposition")
+ || !strcasecmp(name, "Content-Type");
+}
+
+static char *php_mime_get_hdr_value(zend_llist header, char *key);
+
/* parse headers */
static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header)
{
@@ -445,10 +453,15 @@ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header)
}
*value = '\0';
- do { value++; } while (isspace(*value));
-
- key = estrdup(line);
- smart_string_appends(&buf_value, value);
+ /* Keep only headers we use, and ignore duplicates */
+ if (!php_mime_should_save_hdr(line)
+ || php_mime_get_hdr_value(*header, line)) {
+ key = NULL;
+ } else {
+ key = estrdup(line);
+ do { value++; } while (isspace(*value));
+ smart_string_appends(&buf_value, value);
+ }
} else if (buf_value.c) { /* If no ':' on the line, add to previous line */
smart_string_appends(&buf_value, line);
} else {
@@ -522,11 +535,11 @@ static char *php_ap_getword(const zend_encoding *encoding, char **line, char sto
return res;
}
-static char *substring_conf(char *start, int len, char quote)
+static char *substring_conf(char *start, size_t len, char quote)
{
char *result = emalloc(len + 1);
char *resp = result;
- int i;
+ size_t i;
for (i = 0; i < len && start[i] != quote; ++i) {
if (start[i] == '\\' && (start[i + 1] == '\\' || (quote && start[i + 1] == quote))) {
@@ -554,14 +567,14 @@ static char *php_ap_getword_conf(const zend_encoding *encoding, char *str)
char quote = *str;
str++;
- return substring_conf(str, (int)strlen(str), quote);
+ return substring_conf(str, strlen(str), quote);
} else {
char *strend = str;
while (*strend && !isspace(*strend)) {
++strend;
}
- return substring_conf(str, strend - str, 0);
+ return substring_conf(str, (size_t)(strend - str), 0);
}
}
+3
View File
@@ -0,0 +1,3 @@
# https://salsa.debian.org/php-team/php/-/tree/dbe6804422b175d8542b91699384afe5beebeab2/debian/patches (Sury 7.0.33-92)
0211-backport-ZSTR_MAX_LEN.patch
0230-Avoid-state-corruption-via-bailout.patch
@@ -0,0 +1,24 @@
From: Remi Collet <remi@remirepo.net>
Date: Fri, 22 Nov 2024 15:24:16 +0100
Subject: backport ZSTR_MAX_LEN
(cherry picked from commit 37056ad634d9c44bac0d6c8e730eafaec1344840)
(cherry picked from commit ff868946218d6d1661a0c35757e2058cb3ed23ec)
---
Zend/zend_string.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Zend/zend_string.h b/Zend/zend_string.h
index dbc3f3b..b15f78c 100644
--- a/Zend/zend_string.h
+++ b/Zend/zend_string.h
@@ -62,6 +62,9 @@ END_EXTERN_C()
#define _ZSTR_STRUCT_SIZE(len) (_ZSTR_HEADER_SIZE + len + 1)
+#define ZSTR_MAX_OVERHEAD (ZEND_MM_ALIGNED_SIZE(_ZSTR_HEADER_SIZE + 1))
+#define ZSTR_MAX_LEN (SIZE_MAX - ZSTR_MAX_OVERHEAD)
+
#define ZSTR_ALLOCA_ALLOC(str, _len, use_heap) do { \
(str) = (zend_string *)do_alloca(ZEND_MM_ALIGNED_SIZE_EX(_ZSTR_STRUCT_SIZE(_len), 8), (use_heap)); \
GC_REFCOUNT(str) = 1; \
@@ -0,0 +1,698 @@
From: Arnaud Le Blanc <arnaud.lb@gmail.com>
Date: Sun, 18 Oct 2026 20:09:54 +0200
Subject: Avoid state corruption via bailout
Minimal mitigation for EOL version.
Fix GHSA-w8hw-w9fx-j79w (CVE-2026-109618)
Fix GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)
Backported from the PHP 7.4 version:
- There is no fast shutdown in shutdown_executor() before PHP 7.2 (the
opcache one runs before the error handlers are destroyed), so the user
error/exception handlers, EG(error_handling) and EG(exception) are reset
after the cleanup blocks, where a bailout cannot skip it.
- array_init_singleton() is implemented in zend_API.c, there is no
zend_new_array(); HT_HASH_RESET() uses memset(), so the SSE2 change is
not needed.
- ZEND_FAST_CONCAT has no string fast path, so only ZEND_CONCAT gets the
length checks.
- "|| 1" instead of "|| true" in the session upload progress callback
(no stdbool.h).
- The max_multipart_body_parts hunk of the 7.4 patch is left out, the
code is already there.
Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>
---
Zend/zend_API.c | 8 +++++
Zend/zend_API.h | 2 ++
Zend/zend_alloc.c | 66 +++++++++++++++++++++++++++++------------
Zend/zend_alloc.h | 2 ++
Zend/zend_execute_API.c | 8 +++++
Zend/zend_hash.c | 6 ++--
Zend/zend_llist.c | 2 ++
Zend/zend_multiply.h | 4 +--
Zend/zend_strtod.c | 4 +--
Zend/zend_vm_def.h | 6 ++++
Zend/zend_vm_execute.h | 54 +++++++++++++++++++++++++++++++++
ext/session/session.c | 2 +-
main/SAPI.c | 5 ++++
main/main.c | 5 ++++
main/php_variables.c | 8 ++---
main/rfc1867.c | 29 +++++++++++++-----
16 files changed, 172 insertions(+), 39 deletions(-)
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 3dcf0671..bdff6616 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -1063,6 +1063,14 @@ ZEND_API int _array_init(zval *arg, uint32_t size ZEND_FILE_LINE_DC) /* {{{ */
}
/* }}} */
+ZEND_API int _array_init_singleton(zval *arg ZEND_FILE_LINE_DC) /* {{{ */
+{
+ _array_init(arg, 0 ZEND_FILE_LINE_RELAY_CC);
+ Z_ARRVAL_P(arg)->nTableSize = 1;
+ return SUCCESS;
+}
+/* }}} */
+
/* This function should be called after the constructor has been called
* because it may call __set from the uninitialized object otherwise. */
ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index 79267ac0..b48477c4 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -379,10 +379,12 @@ ZEND_API char *zend_get_type_by_const(int type);
#define array_init(arg) _array_init((arg), 0 ZEND_FILE_LINE_CC)
#define array_init_size(arg, size) _array_init((arg), (size) ZEND_FILE_LINE_CC)
+#define array_init_singleton(arg) _array_init_singleton((arg) ZEND_FILE_LINE_CC)
#define object_init(arg) _object_init((arg) ZEND_FILE_LINE_CC)
#define object_init_ex(arg, ce) _object_init_ex((arg), (ce) ZEND_FILE_LINE_CC)
#define object_and_properties_init(arg, ce, properties) _object_and_properties_init((arg), (ce), (properties) ZEND_FILE_LINE_CC)
ZEND_API int _array_init(zval *arg, uint32_t size ZEND_FILE_LINE_DC);
+ZEND_API int _array_init_singleton(zval *arg ZEND_FILE_LINE_DC);
ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC);
ZEND_API int _object_init_ex(zval *arg, zend_class_entry *ce ZEND_FILE_LINE_DC);
ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *ce, HashTable *properties ZEND_FILE_LINE_DC);
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
index d87b066f..235fc8d9 100644
--- a/Zend/zend_alloc.c
+++ b/Zend/zend_alloc.c
@@ -59,6 +59,7 @@
#include "zend_operators.h"
#include "zend_multiply.h"
#include "zend_bitset.h"
+#include "zend_execute.h"
#ifdef HAVE_SIGNAL_H
# include <signal.h>
@@ -362,7 +363,42 @@ static ZEND_COLD ZEND_NORETURN void zend_mm_panic(const char *message)
#if ZEND_DEBUG && defined(HAVE_KILL) && defined(HAVE_GETPID)
kill(getpid(), SIGSEGV);
#endif
- exit(1);
+ _exit(1);
+}
+
+ZEND_API ZEND_COLD ZEND_NORETURN void zend_mm_safe_error_ex(const char *format, ...)
+{
+ zend_string *script_filename = NULL;
+ uint32_t script_lineno = 0;
+
+ if (zend_is_executing()) {
+ script_filename = zend_get_executed_filename_ex();
+ script_lineno = zend_get_executed_lineno();
+ } else if (zend_is_compiling()) {
+ script_filename = zend_get_compiled_filename();
+ script_lineno = zend_get_compiled_lineno();
+ }
+
+ va_list args;
+ va_start(args, format);
+
+ char buf[1024];
+ vsnprintf(buf, sizeof(buf), format, args);
+
+ va_end(args);
+
+ fprintf(stderr,
+ "\nFatal error: %s in %s on line %d\n",
+ buf,
+ script_filename ? ZSTR_VAL(script_filename) : "Unknown",
+ script_lineno);
+
+ /* See http://support.microsoft.com/kb/190351 */
+# ifdef ZEND_WIN32
+ fflush(stderr);
+# endif
+
+ _exit(1);
}
static ZEND_COLD ZEND_NORETURN void zend_mm_safe_error(zend_mm_heap *heap,
@@ -374,22 +410,14 @@ static ZEND_COLD ZEND_NORETURN void zend_mm_safe_error(zend_mm_heap *heap,
#endif
size_t size)
{
+ (void) heap;
- heap->overflow = 1;
- zend_try {
- zend_error_noreturn(E_ERROR,
- format,
- limit,
+ zend_mm_safe_error_ex(format, limit,
#if ZEND_DEBUG
- filename,
- lineno,
+ filename,
+ lineno,
#endif
- size);
- } zend_catch {
- } zend_end_try();
- heap->overflow = 0;
- zend_bailout();
- exit(1);
+ size);
}
#ifdef _WIN32
@@ -1336,7 +1364,7 @@ static zend_always_inline void *zend_mm_alloc_heap(zend_mm_heap *heap, size_t si
size = MAX(size, 1);
size = ZEND_MM_ALIGNED_SIZE(size) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info));
if (UNEXPECTED(size < real_size)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu + %zu)", ZEND_MM_ALIGNED_SIZE(real_size), ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu + %zu)", ZEND_MM_ALIGNED_SIZE(real_size), ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
return NULL;
}
#endif
@@ -2523,7 +2551,7 @@ ZEND_API char* ZEND_FASTCALL _estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_
length = strlen(s);
if (UNEXPECTED(length + 1 == 0)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (1 * %zu + 1)", length);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length);
}
p = (char *) _emalloc(length + 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
if (UNEXPECTED(p == NULL)) {
@@ -2538,7 +2566,7 @@ ZEND_API char* ZEND_FASTCALL _estrndup(const char *s, size_t length ZEND_FILE_LI
char *p;
if (UNEXPECTED(length + 1 == 0)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (1 * %zu + 1)", length);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length);
}
p = (char *) _emalloc(length + 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
if (UNEXPECTED(p == NULL)) {
@@ -2555,7 +2583,7 @@ ZEND_API char* ZEND_FASTCALL zend_strndup(const char *s, size_t length)
char *p;
if (UNEXPECTED(length + 1 == 0)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (1 * %zu + 1)", length);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length);
}
p = (char *) malloc(length + 1);
if (UNEXPECTED(p == NULL)) {
@@ -2830,7 +2858,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
static ZEND_COLD ZEND_NORETURN void zend_out_of_memory(void)
{
fprintf(stderr, "Out of memory\n");
- exit(1);
+ _exit(1);
}
ZEND_API void * __zend_malloc(size_t len)
diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h
index b195534a..ae14ab9e 100644
--- a/Zend/zend_alloc.h
+++ b/Zend/zend_alloc.h
@@ -399,6 +399,8 @@ static void apc_init_heap(void)
*/
+ZEND_API ZEND_COLD ZEND_NORETURN void zend_mm_safe_error_ex(const char *format, ...);
+
END_EXTERN_C()
#endif
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 5cb87df6..bb4ee17d 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -301,6 +301,10 @@ void shutdown_executor(void) /* {{{ */
zend_stack_clean(&EG(user_exception_handlers), (void (*)(void *))ZVAL_PTR_DTOR, 1);
} zend_end_try();
+ /* may be used by zend_error before init_executor */
+ ZVAL_UNDEF(&EG(user_error_handler));
+ ZVAL_UNDEF(&EG(user_exception_handler));
+
zend_try {
/* Cleanup static data for functions and arrays.
* We need a separate cleanup stage because of the following problem:
@@ -380,6 +384,10 @@ void shutdown_executor(void) /* {{{ */
}
} zend_end_try();
+ /* may be used by zend_error before init_executor */
+ EG(error_handling) = EH_NORMAL;
+ EG(exception) = NULL;
+
zend_try {
#if 0&&ZEND_DEBUG
signal(SIGSEGV, original_sigsegv_handler);
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index dc443838..647280d2 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -101,7 +101,7 @@ static zend_always_inline uint32_t zend_hash_check_size(uint32_t nSize)
if (nSize < HT_MIN_SIZE) {
nSize = HT_MIN_SIZE;
} else if (UNEXPECTED(nSize >= HT_MAX_SIZE)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", nSize, sizeof(Bucket), sizeof(Bucket));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", nSize, sizeof(Bucket), sizeof(Bucket));
}
#if defined(ZEND_WIN32)
@@ -187,7 +187,7 @@ static void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht)
{
HT_ASSERT(GC_REFCOUNT(ht) == 1);
if (ht->nTableSize >= HT_MAX_SIZE) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket));
}
ht->nTableSize += ht->nTableSize;
HT_SET_DATA_ADDR(ht, perealloc2(HT_GET_DATA_ADDR(ht), HT_SIZE(ht), HT_USED_SIZE(ht), ht->u.flags & HASH_FLAG_PERSISTENT));
@@ -866,7 +866,7 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
pefree(old_data, ht->u.flags & HASH_FLAG_PERSISTENT);
zend_hash_rehash(ht);
} else {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket) + sizeof(uint32_t), sizeof(Bucket));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket) + sizeof(uint32_t), sizeof(Bucket));
}
}
diff --git a/Zend/zend_llist.c b/Zend/zend_llist.c
index f771bd29..030472c7 100644
--- a/Zend/zend_llist.c
+++ b/Zend/zend_llist.c
@@ -114,6 +114,8 @@ ZEND_API void zend_llist_destroy(zend_llist *l)
current = next;
}
+ l->head = NULL;
+ l->tail = NULL;
l->count = 0;
}
diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h
index 8bece847..e80cc218 100644
--- a/Zend/zend_multiply.h
+++ b/Zend/zend_multiply.h
@@ -272,7 +272,7 @@ static zend_always_inline size_t zend_safe_address_guarded(size_t nmemb, size_t
size_t ret = zend_safe_address(nmemb, size, offset, &overflow);
if (UNEXPECTED(overflow)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
return 0;
}
return ret;
@@ -285,7 +285,7 @@ static zend_always_inline size_t zend_safe_addmult(size_t nmemb, size_t size, si
size_t ret = zend_safe_address(nmemb, size, offset, &overflow);
if (UNEXPECTED(overflow)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in %s (%zu * %zu + %zu)", message, nmemb, size, offset);
+ zend_mm_safe_error_ex("Possible integer overflow in %s (%zu * %zu + %zu)", message, nmemb, size, offset);
return 0;
}
return ret;
diff --git a/Zend/zend_strtod.c b/Zend/zend_strtod.c
index 3aa99f8d..01c1779d 100644
--- a/Zend/zend_strtod.c
+++ b/Zend/zend_strtod.c
@@ -600,7 +600,7 @@ Balloc
rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
if (!rv) {
FREE_DTOA_LOCK(0);
- zend_error_noreturn(E_ERROR, "Balloc() failed to allocate memory");
+ zend_mm_safe_error_ex("Balloc() failed to allocate memory");
}
#else
len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
@@ -613,7 +613,7 @@ Balloc
rv = (Bigint*)MALLOC(len*sizeof(double));
if (!rv) {
FREE_DTOA_LOCK(0);
- zend_error_noreturn(E_ERROR, "Balloc() failed to allocate memory");
+ zend_mm_safe_error_ex("Balloc() failed to allocate memory");
}
#endif
rv->k = k;
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 27edd6fc..47531760 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -316,11 +316,17 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index af3c1815..287a30e5 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -4428,11 +4428,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CONST_HANDLE
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -8513,11 +8519,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -10525,11 +10537,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -36525,11 +36543,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -43623,11 +43647,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -47732,11 +47762,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER(
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -52089,11 +52125,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -54663,11 +54705,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER(
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -55947,11 +55995,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
diff --git a/ext/session/session.c b/ext/session/session.c
index d3226ee1..ec3c85b3 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -2851,7 +2851,7 @@ static int php_session_rfc1867_callback(unsigned int event, void *event_data, vo
if (php_session_rfc1867_orig_callback) {
retval = php_session_rfc1867_orig_callback(event, event_data, extra);
}
- if (!PS(rfc1867_enabled)) {
+ if (!PS(rfc1867_enabled) || 1) {
return retval;
}
diff --git a/main/SAPI.c b/main/SAPI.c
index 8176561a..63ef3617 100644
--- a/main/SAPI.c
+++ b/main/SAPI.c
@@ -515,18 +515,23 @@ SAPI_API void sapi_deactivate(void)
}
if (SG(request_info).auth_user) {
efree(SG(request_info).auth_user);
+ SG(request_info).auth_user = NULL;
}
if (SG(request_info).auth_password) {
efree(SG(request_info).auth_password);
+ SG(request_info).auth_password = NULL;
}
if (SG(request_info).auth_digest) {
efree(SG(request_info).auth_digest);
+ SG(request_info).auth_digest = NULL;
}
if (SG(request_info).content_type_dup) {
efree(SG(request_info).content_type_dup);
+ SG(request_info).content_type_dup = NULL;
}
if (SG(request_info).current_user) {
efree(SG(request_info).current_user);
+ SG(request_info).current_user = NULL;
}
if (sapi_module.deactivate) {
sapi_module.deactivate();
diff --git a/main/main.c b/main/main.c
index 037a2202..3fa2de32 100644
--- a/main/main.c
+++ b/main/main.c
@@ -1892,6 +1892,8 @@ void php_request_shutdown(void *dummy)
for (i=0; i<NUM_TRACK_VARS; i++) {
zval_ptr_dtor(&PG(http_globals)[i]);
+ /* May be accessed before php_request_startup() */
+ ZVAL_UNDEF(&PG(http_globals)[i]);
}
} zend_end_try();
@@ -1945,6 +1947,9 @@ void php_request_shutdown(void *dummy)
#ifdef HAVE_DTRACE
DTRACE_REQUEST_SHUTDOWN(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), (char *)SAFE_FILENAME(SG(request_info).request_method));
#endif /* HAVE_DTRACE */
+
+ /* May be accessed before php_request_startup() */
+ PG(modules_activated) = 0;
}
/* }}} */
diff --git a/main/php_variables.c b/main/php_variables.c
index e8fcaa08..31c4089b 100644
--- a/main/php_variables.c
+++ b/main/php_variables.c
@@ -207,7 +207,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
}
if (!index) {
- array_init(&gpc_element);
+ array_init_singleton(&gpc_element);
if ((gpc_element_p = zend_hash_next_index_insert(symtable1, &gpc_element)) == NULL) {
zval_ptr_dtor(&gpc_element);
zval_dtor(val);
@@ -224,7 +224,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
gpc_element_p = zend_symtable_str_find(symtable1, index, index_len);
if (!gpc_element_p) {
zval tmp;
- array_init(&tmp);
+ array_init_singleton(&tmp);
gpc_element_p = zend_symtable_str_update_ind(symtable1, index, index_len, &tmp);
} else {
if (Z_TYPE_P(gpc_element_p) == IS_INDIRECT) {
@@ -232,7 +232,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
}
if (Z_TYPE_P(gpc_element_p) != IS_ARRAY) {
zval_ptr_dtor(gpc_element_p);
- array_init(gpc_element_p);
+ array_init_singleton(gpc_element_p);
}
}
}
@@ -425,7 +425,7 @@ SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
case PARSE_POST:
case PARSE_GET:
case PARSE_COOKIE:
- array_init(&array);
+ array_init_singleton(&array);
switch (arg) {
case PARSE_POST:
zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_POST]);
diff --git a/main/rfc1867.c b/main/rfc1867.c
index cac8af84..b219c9f2 100644
--- a/main/rfc1867.c
+++ b/main/rfc1867.c
@@ -407,6 +407,14 @@ static int find_boundary(multipart_buffer *self, char *boundary)
return 0;
}
+static zend_bool php_mime_should_save_hdr(const char *name)
+{
+ return !strcasecmp(name, "Content-Disposition")
+ || !strcasecmp(name, "Content-Type");
+}
+
+static char *php_mime_get_hdr_value(zend_llist header, char *key);
+
/* parse headers */
static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header)
{
@@ -447,10 +455,15 @@ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header)
}
*value = '\0';
- do { value++; } while (isspace(*value));
-
- key = estrdup(line);
- smart_string_appends(&buf_value, value);
+ /* Keep only headers we use, and ignore duplicates */
+ if (!php_mime_should_save_hdr(line)
+ || php_mime_get_hdr_value(*header, line)) {
+ key = NULL;
+ } else {
+ key = estrdup(line);
+ do { value++; } while (isspace(*value));
+ smart_string_appends(&buf_value, value);
+ }
} else if (buf_value.c) { /* If no ':' on the line, add to previous line */
smart_string_appends(&buf_value, line);
} else {
@@ -524,11 +537,11 @@ static char *php_ap_getword(const zend_encoding *encoding, char **line, char sto
return res;
}
-static char *substring_conf(char *start, int len, char quote)
+static char *substring_conf(char *start, size_t len, char quote)
{
char *result = emalloc(len + 1);
char *resp = result;
- int i;
+ size_t i;
for (i = 0; i < len && start[i] != quote; ++i) {
if (start[i] == '\\' && (start[i + 1] == '\\' || (quote && start[i + 1] == quote))) {
@@ -556,14 +569,14 @@ static char *php_ap_getword_conf(const zend_encoding *encoding, char *str)
char quote = *str;
str++;
- return substring_conf(str, (int)strlen(str), quote);
+ return substring_conf(str, strlen(str), quote);
} else {
char *strend = str;
while (*strend && !isspace(*strend)) {
++strend;
}
- return substring_conf(str, strend - str, 0);
+ return substring_conf(str, (size_t)(strend - str), 0);
}
}
+3
View File
@@ -0,0 +1,3 @@
# https://salsa.debian.org/php-team/php/-/tree/7a33180834a6169b933132f697b9286bc2bc3c3f/debian/patches (Sury 7.1.33-80)
0167-backport-ZSTR_MAX_LEN.patch
0186-Avoid-state-corruption-via-bailout.patch
@@ -0,0 +1,23 @@
From: Remi Collet <remi@remirepo.net>
Date: Fri, 22 Nov 2024 15:24:16 +0100
Subject: backport ZSTR_MAX_LEN
(cherry picked from commit 37056ad634d9c44bac0d6c8e730eafaec1344840)
---
Zend/zend_string.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Zend/zend_string.h b/Zend/zend_string.h
index 784b88e..5f7a9ea 100644
--- a/Zend/zend_string.h
+++ b/Zend/zend_string.h
@@ -74,6 +74,9 @@ END_EXTERN_C()
#define _ZSTR_STRUCT_SIZE(len) (_ZSTR_HEADER_SIZE + len + 1)
+#define ZSTR_MAX_OVERHEAD (ZEND_MM_ALIGNED_SIZE(_ZSTR_HEADER_SIZE + 1))
+#define ZSTR_MAX_LEN (SIZE_MAX - ZSTR_MAX_OVERHEAD)
+
#define ZSTR_ALLOCA_ALLOC(str, _len, use_heap) do { \
(str) = (zend_string *)do_alloca(ZEND_MM_ALIGNED_SIZE_EX(_ZSTR_STRUCT_SIZE(_len), 8), (use_heap)); \
GC_REFCOUNT(str) = 1; \
@@ -0,0 +1,893 @@
From: Arnaud Le Blanc <arnaud.lb@gmail.com>
Date: Sun, 18 Oct 2026 20:09:54 +0200
Subject: Avoid state corruption via bailout
Minimal mitigation for EOL version.
Fix GHSA-w8hw-w9fx-j79w (CVE-2026-109618)
Fix GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)
Backported from the PHP 7.4 version:
- shutdown_executor() frees the object store before the error handlers,
so the fast shutdown resets are done just before
zend_objects_store_free_object_storage().
- "|| 1" instead of "|| true" in the session upload progress callback
(no stdbool.h).
- The max_multipart_body_parts hunk of the 7.4 patch is left out, the
code is already there.
- array_init_singleton() is implemented in zend_API.c, there is no
zend_new_array(); HT_HASH_RESET() uses memset(), so the SSE2 change is
not needed.
Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>
---
Zend/zend_API.c | 8 +++
Zend/zend_API.h | 2 +
Zend/zend_alloc.c | 68 +++++++++++++++++--------
Zend/zend_alloc.h | 2 +
Zend/zend_execute_API.c | 15 ++++++
Zend/zend_hash.c | 6 +--
Zend/zend_llist.c | 2 +
Zend/zend_multiply.h | 4 +-
Zend/zend_strtod.c | 4 +-
Zend/zend_vm_def.h | 12 +++++
Zend/zend_vm_execute.h | 108 ++++++++++++++++++++++++++++++++++++++++
ext/session/session.c | 2 +-
main/SAPI.c | 5 ++
main/main.c | 5 ++
main/php_variables.c | 8 +--
main/rfc1867.c | 29 ++++++++---
16 files changed, 240 insertions(+), 40 deletions(-)
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 604450e9..738266cf 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -1093,6 +1093,14 @@ ZEND_API int _array_init(zval *arg, uint32_t size ZEND_FILE_LINE_DC) /* {{{ */
}
/* }}} */
+ZEND_API int _array_init_singleton(zval *arg ZEND_FILE_LINE_DC) /* {{{ */
+{
+ _array_init(arg, 0 ZEND_FILE_LINE_RELAY_CC);
+ Z_ARRVAL_P(arg)->nTableSize = 1;
+ return SUCCESS;
+}
+/* }}} */
+
/* This function should be called after the constructor has been called
* because it may call __set from the uninitialized object otherwise. */
ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index 38407703..763c64ab 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -392,10 +392,12 @@ ZEND_API char *zend_get_type_by_const(int type);
#define array_init(arg) _array_init((arg), 0 ZEND_FILE_LINE_CC)
#define array_init_size(arg, size) _array_init((arg), (size) ZEND_FILE_LINE_CC)
+#define array_init_singleton(arg) _array_init_singleton((arg) ZEND_FILE_LINE_CC)
#define object_init(arg) _object_init((arg) ZEND_FILE_LINE_CC)
#define object_init_ex(arg, ce) _object_init_ex((arg), (ce) ZEND_FILE_LINE_CC)
#define object_and_properties_init(arg, ce, properties) _object_and_properties_init((arg), (ce), (properties) ZEND_FILE_LINE_CC)
ZEND_API int _array_init(zval *arg, uint32_t size ZEND_FILE_LINE_DC);
+ZEND_API int _array_init_singleton(zval *arg ZEND_FILE_LINE_DC);
ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC);
ZEND_API int _object_init_ex(zval *arg, zend_class_entry *ce ZEND_FILE_LINE_DC);
ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *ce, HashTable *properties ZEND_FILE_LINE_DC);
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
index f4a61795..4b914251 100644
--- a/Zend/zend_alloc.c
+++ b/Zend/zend_alloc.c
@@ -59,6 +59,7 @@
#include "zend_operators.h"
#include "zend_multiply.h"
#include "zend_bitset.h"
+#include "zend_execute.h"
#ifdef HAVE_SIGNAL_H
# include <signal.h>
@@ -360,7 +361,42 @@ static ZEND_COLD ZEND_NORETURN void zend_mm_panic(const char *message)
#if ZEND_DEBUG && defined(HAVE_KILL) && defined(HAVE_GETPID)
kill(getpid(), SIGSEGV);
#endif
- exit(1);
+ _exit(1);
+}
+
+ZEND_API ZEND_COLD ZEND_NORETURN void zend_mm_safe_error_ex(const char *format, ...)
+{
+ zend_string *script_filename = NULL;
+ uint32_t script_lineno = 0;
+
+ if (zend_is_executing()) {
+ script_filename = zend_get_executed_filename_ex();
+ script_lineno = zend_get_executed_lineno();
+ } else if (zend_is_compiling()) {
+ script_filename = zend_get_compiled_filename();
+ script_lineno = zend_get_compiled_lineno();
+ }
+
+ va_list args;
+ va_start(args, format);
+
+ char buf[1024];
+ vsnprintf(buf, sizeof(buf), format, args);
+
+ va_end(args);
+
+ fprintf(stderr,
+ "\nFatal error: %s in %s on line %d\n",
+ buf,
+ script_filename ? ZSTR_VAL(script_filename) : "Unknown",
+ script_lineno);
+
+ /* See http://support.microsoft.com/kb/190351 */
+# ifdef ZEND_WIN32
+ fflush(stderr);
+# endif
+
+ _exit(1);
}
static ZEND_COLD ZEND_NORETURN void zend_mm_safe_error(zend_mm_heap *heap,
@@ -372,22 +408,14 @@ static ZEND_COLD ZEND_NORETURN void zend_mm_safe_error(zend_mm_heap *heap,
#endif
size_t size)
{
+ (void) heap;
- heap->overflow = 1;
- zend_try {
- zend_error_noreturn(E_ERROR,
- format,
- limit,
+ zend_mm_safe_error_ex(format, limit,
#if ZEND_DEBUG
- filename,
- lineno,
+ filename,
+ lineno,
#endif
- size);
- } zend_catch {
- } zend_end_try();
- heap->overflow = 0;
- zend_bailout();
- exit(1);
+ size);
}
#ifdef _WIN32
@@ -1338,7 +1366,7 @@ static zend_always_inline void *zend_mm_alloc_heap(zend_mm_heap *heap, size_t si
size = MAX(size, 1);
size = ZEND_MM_ALIGNED_SIZE(size) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info));
if (UNEXPECTED(size < real_size)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu + %zu)", ZEND_MM_ALIGNED_SIZE(real_size), ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu + %zu)", ZEND_MM_ALIGNED_SIZE(real_size), ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
return NULL;
}
#endif
@@ -1731,7 +1759,7 @@ static void *zend_mm_alloc_huge(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D
void *ptr;
if (UNEXPECTED(new_size < size)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu + %zu)", size, alignment);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu + %zu)", size, alignment);
}
#if ZEND_MM_LIMIT
@@ -2527,7 +2555,7 @@ ZEND_API char* ZEND_FASTCALL _estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_
length = strlen(s);
if (UNEXPECTED(length + 1 == 0)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (1 * %zu + 1)", length);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length);
}
p = (char *) _emalloc(length + 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
memcpy(p, s, length+1);
@@ -2539,7 +2567,7 @@ ZEND_API char* ZEND_FASTCALL _estrndup(const char *s, size_t length ZEND_FILE_LI
char *p;
if (UNEXPECTED(length + 1 == 0)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (1 * %zu + 1)", length);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length);
}
p = (char *) _emalloc(length + 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
memcpy(p, s, length);
@@ -2553,7 +2581,7 @@ ZEND_API char* ZEND_FASTCALL zend_strndup(const char *s, size_t length)
char *p;
if (UNEXPECTED(length + 1 == 0)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (1 * %zu + 1)", length);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length);
}
p = (char *) malloc(length + 1);
if (UNEXPECTED(p == NULL)) {
@@ -2827,7 +2855,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
static ZEND_COLD ZEND_NORETURN void zend_out_of_memory(void)
{
fprintf(stderr, "Out of memory\n");
- exit(1);
+ _exit(1);
}
ZEND_API void * __zend_malloc(size_t len)
diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h
index e3ab221e..334004c5 100644
--- a/Zend/zend_alloc.h
+++ b/Zend/zend_alloc.h
@@ -399,6 +399,8 @@ static void apc_init_heap(void)
*/
+ZEND_API ZEND_COLD ZEND_NORETURN void zend_mm_safe_error_ex(const char *format, ...);
+
END_EXTERN_C()
#endif
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 9f10843b..99d4ffa6 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -263,8 +263,21 @@ void shutdown_executor(void) /* {{{ */
zend_close_rsrc_list(&EG(regular_list));
} zend_end_try();
+ if (fast_shutdown) {
+ /* may be used by zend_error before init_executor */
+ ZVAL_UNDEF(&EG(user_error_handler));
+ ZVAL_UNDEF(&EG(user_exception_handler));
+ memset(&EG(user_error_handlers_error_reporting), 0, sizeof(EG(user_error_handlers_error_reporting)));
+ memset(&EG(user_error_handlers), 0, sizeof(EG(user_error_handlers)));
+ memset(&EG(user_exception_handlers), 0, sizeof(EG(user_exception_handlers)));
+ }
+
zend_objects_store_free_object_storage(&EG(objects_store), fast_shutdown);
+ /* may be used by zend_error before init_executor */
+ EG(error_handling) = EH_NORMAL;
+ EG(exception) = NULL;
+
/* All resources and objects are destroyed. */
/* No PHP callback functions may be called after this point. */
EG(active) = 0;
@@ -299,6 +312,8 @@ void shutdown_executor(void) /* {{{ */
} ZEND_HASH_FOREACH_END_DEL();
zend_cleanup_internal_classes();
+ EG(objects_store).object_buckets = NULL;
+ EG(objects_store).top = 1;
} else {
zend_hash_graceful_reverse_destroy(&EG(symbol_table));
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index f5fba679..d6c022a2 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -103,7 +103,7 @@ static zend_always_inline uint32_t zend_hash_check_size(uint32_t nSize)
if (nSize < HT_MIN_SIZE) {
nSize = HT_MIN_SIZE;
} else if (UNEXPECTED(nSize >= HT_MAX_SIZE)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", nSize, sizeof(Bucket), sizeof(Bucket));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", nSize, sizeof(Bucket), sizeof(Bucket));
}
#if defined(ZEND_WIN32)
@@ -189,7 +189,7 @@ static void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht)
{
HT_ASSERT_RC1(ht);
if (ht->nTableSize >= HT_MAX_SIZE) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket));
}
ht->nTableSize += ht->nTableSize;
HT_SET_DATA_ADDR(ht, perealloc2(HT_GET_DATA_ADDR(ht), HT_SIZE(ht), HT_USED_SIZE(ht), ht->u.flags & HASH_FLAG_PERSISTENT));
@@ -865,7 +865,7 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
pefree(old_data, ht->u.flags & HASH_FLAG_PERSISTENT);
zend_hash_rehash(ht);
} else {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket) + sizeof(uint32_t), sizeof(Bucket));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket) + sizeof(uint32_t), sizeof(Bucket));
}
}
diff --git a/Zend/zend_llist.c b/Zend/zend_llist.c
index de93f295..4b0509cb 100644
--- a/Zend/zend_llist.c
+++ b/Zend/zend_llist.c
@@ -114,6 +114,8 @@ ZEND_API void zend_llist_destroy(zend_llist *l)
current = next;
}
+ l->head = NULL;
+ l->tail = NULL;
l->count = 0;
}
diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h
index 26853a3c..386f9353 100644
--- a/Zend/zend_multiply.h
+++ b/Zend/zend_multiply.h
@@ -309,7 +309,7 @@ static zend_always_inline size_t zend_safe_address_guarded(size_t nmemb, size_t
size_t ret = zend_safe_address(nmemb, size, offset, &overflow);
if (UNEXPECTED(overflow)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
return 0;
}
return ret;
@@ -322,7 +322,7 @@ static zend_always_inline size_t zend_safe_addmult(size_t nmemb, size_t size, si
size_t ret = zend_safe_address(nmemb, size, offset, &overflow);
if (UNEXPECTED(overflow)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in %s (%zu * %zu + %zu)", message, nmemb, size, offset);
+ zend_mm_safe_error_ex("Possible integer overflow in %s (%zu * %zu + %zu)", message, nmemb, size, offset);
return 0;
}
return ret;
diff --git a/Zend/zend_strtod.c b/Zend/zend_strtod.c
index 3aa99f8d..01c1779d 100644
--- a/Zend/zend_strtod.c
+++ b/Zend/zend_strtod.c
@@ -600,7 +600,7 @@ Balloc
rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
if (!rv) {
FREE_DTOA_LOCK(0);
- zend_error_noreturn(E_ERROR, "Balloc() failed to allocate memory");
+ zend_mm_safe_error_ex("Balloc() failed to allocate memory");
}
#else
len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
@@ -613,7 +613,7 @@ Balloc
rv = (Bigint*)MALLOC(len*sizeof(double));
if (!rv) {
FREE_DTOA_LOCK(0);
- zend_error_noreturn(E_ERROR, "Balloc() failed to allocate memory");
+ zend_mm_safe_error_ex("Balloc() failed to allocate memory");
}
#endif
rv->k = k;
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index ed84d17b..ebdb2fdc 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -316,11 +316,17 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -2716,11 +2722,17 @@ ZEND_VM_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 3f975dec..b0170aff 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -4406,11 +4406,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CONST_HANDLE
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -5202,11 +5208,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CONST_H
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -8524,11 +8536,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -9253,11 +9271,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HAND
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -10580,11 +10604,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -11275,11 +11305,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -35136,11 +35172,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -37690,11 +37732,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CONST_HAND
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -41657,11 +41705,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -44200,11 +44254,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -45369,11 +45429,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER(
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -47770,11 +47836,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HAN
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -49343,11 +49415,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -49957,11 +50035,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -51749,11 +51833,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER(
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -52294,11 +52384,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -53079,11 +53175,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -53625,11 +53727,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
break;
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
diff --git a/ext/session/session.c b/ext/session/session.c
index 0f0d9bcb..8be81f6d 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -3071,7 +3071,7 @@ static int php_session_rfc1867_callback(unsigned int event, void *event_data, vo
if (php_session_rfc1867_orig_callback) {
retval = php_session_rfc1867_orig_callback(event, event_data, extra);
}
- if (!PS(rfc1867_enabled)) {
+ if (!PS(rfc1867_enabled) || 1) {
return retval;
}
diff --git a/main/SAPI.c b/main/SAPI.c
index 01383357..17afa0e0 100644
--- a/main/SAPI.c
+++ b/main/SAPI.c
@@ -515,18 +515,23 @@ SAPI_API void sapi_deactivate(void)
}
if (SG(request_info).auth_user) {
efree(SG(request_info).auth_user);
+ SG(request_info).auth_user = NULL;
}
if (SG(request_info).auth_password) {
efree(SG(request_info).auth_password);
+ SG(request_info).auth_password = NULL;
}
if (SG(request_info).auth_digest) {
efree(SG(request_info).auth_digest);
+ SG(request_info).auth_digest = NULL;
}
if (SG(request_info).content_type_dup) {
efree(SG(request_info).content_type_dup);
+ SG(request_info).content_type_dup = NULL;
}
if (SG(request_info).current_user) {
efree(SG(request_info).current_user);
+ SG(request_info).current_user = NULL;
}
if (sapi_module.deactivate) {
sapi_module.deactivate();
diff --git a/main/main.c b/main/main.c
index 0cfdb913..92c19e46 100644
--- a/main/main.c
+++ b/main/main.c
@@ -1895,6 +1895,8 @@ void php_request_shutdown(void *dummy)
for (i=0; i<NUM_TRACK_VARS; i++) {
zval_ptr_dtor(&PG(http_globals)[i]);
+ /* May be accessed before php_request_startup() */
+ ZVAL_UNDEF(&PG(http_globals)[i]);
}
} zend_end_try();
@@ -1948,6 +1950,9 @@ void php_request_shutdown(void *dummy)
#ifdef HAVE_DTRACE
DTRACE_REQUEST_SHUTDOWN(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), (char *)SAFE_FILENAME(SG(request_info).request_method));
#endif /* HAVE_DTRACE */
+
+ /* May be accessed before php_request_startup() */
+ PG(modules_activated) = 0;
}
/* }}} */
diff --git a/main/php_variables.c b/main/php_variables.c
index 3e0e8d76..a5a9af19 100644
--- a/main/php_variables.c
+++ b/main/php_variables.c
@@ -213,7 +213,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
}
if (!index) {
- array_init(&gpc_element);
+ array_init_singleton(&gpc_element);
if ((gpc_element_p = zend_hash_next_index_insert(symtable1, &gpc_element)) == NULL) {
zval_ptr_dtor(&gpc_element);
zval_dtor(val);
@@ -230,7 +230,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
gpc_element_p = zend_symtable_str_find(symtable1, index, index_len);
if (!gpc_element_p) {
zval tmp;
- array_init(&tmp);
+ array_init_singleton(&tmp);
gpc_element_p = zend_symtable_str_update_ind(symtable1, index, index_len, &tmp);
} else {
if (Z_TYPE_P(gpc_element_p) == IS_INDIRECT) {
@@ -238,7 +238,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
}
if (Z_TYPE_P(gpc_element_p) != IS_ARRAY) {
zval_ptr_dtor(gpc_element_p);
- array_init(gpc_element_p);
+ array_init_singleton(gpc_element_p);
} else {
SEPARATE_ARRAY(gpc_element_p);
}
@@ -433,7 +433,7 @@ SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
case PARSE_POST:
case PARSE_GET:
case PARSE_COOKIE:
- array_init(&array);
+ array_init_singleton(&array);
switch (arg) {
case PARSE_POST:
zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_POST]);
diff --git a/main/rfc1867.c b/main/rfc1867.c
index 43b94c05..b7d1ed2a 100644
--- a/main/rfc1867.c
+++ b/main/rfc1867.c
@@ -407,6 +407,14 @@ static int find_boundary(multipart_buffer *self, char *boundary)
return 0;
}
+static zend_bool php_mime_should_save_hdr(const char *name)
+{
+ return !strcasecmp(name, "Content-Disposition")
+ || !strcasecmp(name, "Content-Type");
+}
+
+static char *php_mime_get_hdr_value(zend_llist header, char *key);
+
/* parse headers */
static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header)
{
@@ -447,10 +455,15 @@ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header)
}
*value = '\0';
- do { value++; } while (isspace(*value));
-
- key = estrdup(line);
- smart_string_appends(&buf_value, value);
+ /* Keep only headers we use, and ignore duplicates */
+ if (!php_mime_should_save_hdr(line)
+ || php_mime_get_hdr_value(*header, line)) {
+ key = NULL;
+ } else {
+ key = estrdup(line);
+ do { value++; } while (isspace(*value));
+ smart_string_appends(&buf_value, value);
+ }
} else if (buf_value.c) { /* If no ':' on the line, add to previous line */
smart_string_appends(&buf_value, line);
} else {
@@ -524,11 +537,11 @@ static char *php_ap_getword(const zend_encoding *encoding, char **line, char sto
return res;
}
-static char *substring_conf(char *start, int len, char quote)
+static char *substring_conf(char *start, size_t len, char quote)
{
char *result = emalloc(len + 1);
char *resp = result;
- int i;
+ size_t i;
for (i = 0; i < len && start[i] != quote; ++i) {
if (start[i] == '\\' && (start[i + 1] == '\\' || (quote && start[i + 1] == quote))) {
@@ -556,14 +569,14 @@ static char *php_ap_getword_conf(const zend_encoding *encoding, char *str)
char quote = *str;
str++;
- return substring_conf(str, (int)strlen(str), quote);
+ return substring_conf(str, strlen(str), quote);
} else {
char *strend = str;
while (*strend && !isspace(*strend)) {
++strend;
}
- return substring_conf(str, strend - str, 0);
+ return substring_conf(str, (size_t)(strend - str), 0);
}
}
+3
View File
@@ -0,0 +1,3 @@
# https://salsa.debian.org/php-team/php/-/tree/e0bcd488d9f8da024d9e1a254113539a846cac6d/debian/patches (Sury 7.2.34-66)
0135-backport-ZSTR_MAX_LEN.patch
0159-Avoid-state-corruption-via-bailout.patch
@@ -0,0 +1,22 @@
From: Remi Collet <remi@remirepo.net>
Date: Fri, 22 Nov 2024 15:24:16 +0100
Subject: backport ZSTR_MAX_LEN
---
Zend/zend_string.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Zend/zend_string.h b/Zend/zend_string.h
index 396b63b..8ef979f 100644
--- a/Zend/zend_string.h
+++ b/Zend/zend_string.h
@@ -76,6 +76,9 @@ END_EXTERN_C()
#define _ZSTR_STRUCT_SIZE(len) (_ZSTR_HEADER_SIZE + len + 1)
+#define ZSTR_MAX_OVERHEAD (ZEND_MM_ALIGNED_SIZE(_ZSTR_HEADER_SIZE + 1))
+#define ZSTR_MAX_LEN (SIZE_MAX - ZSTR_MAX_OVERHEAD)
+
#define ZSTR_ALLOCA_ALLOC(str, _len, use_heap) do { \
(str) = (zend_string *)do_alloca(ZEND_MM_ALIGNED_SIZE_EX(_ZSTR_STRUCT_SIZE(_len), 8), (use_heap)); \
GC_SET_REFCOUNT(str, 1); \
@@ -0,0 +1,912 @@
From: Arnaud Le Blanc <arnaud.lb@gmail.com>
Date: Sun, 18 Oct 2026 20:09:54 +0200
Subject: Avoid state corruption via bailout
Minimal mitigation for EOL version.
Fix GHSA-w8hw-w9fx-j79w (CVE-2026-109618)
Fix GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)
Backported from the PHP 7.4 version:
- shutdown_executor() frees the object store before the error handlers,
so the fast shutdown resets are done just before
zend_objects_store_free_object_storage().
- "|| 1" instead of "|| true" in the session upload progress callback
(no stdbool.h).
- The max_multipart_body_parts hunk of the 7.4 patch is left out, the
code is already there.
Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>
---
Zend/zend_API.h | 1 +
Zend/zend_alloc.c | 68 +++++++++++++++++++--------
Zend/zend_alloc.h | 2 +
Zend/zend_execute_API.c | 15 ++++++
Zend/zend_hash.c | 13 +++--
Zend/zend_hash.h | 1 +
Zend/zend_llist.c | 2 +
Zend/zend_multiply.h | 4 +-
Zend/zend_strtod.c | 4 +-
Zend/zend_types.h | 26 +++++-----
Zend/zend_vm_def.h | 12 +++++
Zend/zend_vm_execute.h | 102 ++++++++++++++++++++++++++++++++++++++++
ext/session/session.c | 2 +-
main/SAPI.c | 5 ++
main/main.c | 5 ++
main/php_variables.c | 8 ++--
main/rfc1867.c | 29 ++++++++----
17 files changed, 248 insertions(+), 51 deletions(-)
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index 3c134f44..67942e39 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -376,6 +376,7 @@ ZEND_API char *zend_get_type_by_const(int type);
#define array_init(arg) ZVAL_ARR((arg), zend_new_array(0))
#define array_init_size(arg, size) ZVAL_ARR((arg), zend_new_array(size))
+#define array_init_singleton(arg) ZVAL_ARR((arg), zend_new_array_singleton())
ZEND_API int object_init(zval *arg);
ZEND_API int object_init_ex(zval *arg, zend_class_entry *ce);
ZEND_API int object_and_properties_init(zval *arg, zend_class_entry *ce, HashTable *properties);
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
index 25216898..126aa124 100644
--- a/Zend/zend_alloc.c
+++ b/Zend/zend_alloc.c
@@ -57,6 +57,7 @@
#include "zend_operators.h"
#include "zend_multiply.h"
#include "zend_bitset.h"
+#include "zend_execute.h"
#ifdef HAVE_SIGNAL_H
# include <signal.h>
@@ -358,7 +359,42 @@ static ZEND_COLD ZEND_NORETURN void zend_mm_panic(const char *message)
#if ZEND_DEBUG && defined(HAVE_KILL) && defined(HAVE_GETPID)
kill(getpid(), SIGSEGV);
#endif
- exit(1);
+ _exit(1);
+}
+
+ZEND_API ZEND_COLD ZEND_NORETURN void zend_mm_safe_error_ex(const char *format, ...)
+{
+ zend_string *script_filename = NULL;
+ uint32_t script_lineno = 0;
+
+ if (zend_is_executing()) {
+ script_filename = zend_get_executed_filename_ex();
+ script_lineno = zend_get_executed_lineno();
+ } else if (zend_is_compiling()) {
+ script_filename = zend_get_compiled_filename();
+ script_lineno = zend_get_compiled_lineno();
+ }
+
+ va_list args;
+ va_start(args, format);
+
+ char buf[1024];
+ vsnprintf(buf, sizeof(buf), format, args);
+
+ va_end(args);
+
+ fprintf(stderr,
+ "\nFatal error: %s in %s on line %d\n",
+ buf,
+ script_filename ? ZSTR_VAL(script_filename) : "Unknown",
+ script_lineno);
+
+ /* See http://support.microsoft.com/kb/190351 */
+# ifdef ZEND_WIN32
+ fflush(stderr);
+# endif
+
+ _exit(1);
}
static ZEND_COLD ZEND_NORETURN void zend_mm_safe_error(zend_mm_heap *heap,
@@ -370,22 +406,14 @@ static ZEND_COLD ZEND_NORETURN void zend_mm_safe_error(zend_mm_heap *heap,
#endif
size_t size)
{
+ (void) heap;
- heap->overflow = 1;
- zend_try {
- zend_error_noreturn(E_ERROR,
- format,
- limit,
+ zend_mm_safe_error_ex(format, limit,
#if ZEND_DEBUG
- filename,
- lineno,
+ filename,
+ lineno,
#endif
- size);
- } zend_catch {
- } zend_end_try();
- heap->overflow = 0;
- zend_bailout();
- exit(1);
+ size);
}
#ifdef _WIN32
@@ -1352,7 +1380,7 @@ static zend_always_inline void *zend_mm_alloc_heap(zend_mm_heap *heap, size_t si
size = MAX(size, 1);
size = ZEND_MM_ALIGNED_SIZE(size) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info));
if (UNEXPECTED(size < real_size)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu + %zu)", ZEND_MM_ALIGNED_SIZE(real_size), ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu + %zu)", ZEND_MM_ALIGNED_SIZE(real_size), ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
return NULL;
}
#endif
@@ -1800,7 +1828,7 @@ static void *zend_mm_alloc_huge(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D
void *ptr;
if (UNEXPECTED(new_size < size)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu + %zu)", size, alignment);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu + %zu)", size, alignment);
}
#if ZEND_MM_LIMIT
@@ -2596,7 +2624,7 @@ ZEND_API char* ZEND_FASTCALL _estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_
length = strlen(s);
if (UNEXPECTED(length + 1 == 0)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (1 * %zu + 1)", length);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length);
}
p = (char *) _emalloc(length + 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
memcpy(p, s, length+1);
@@ -2608,7 +2636,7 @@ ZEND_API char* ZEND_FASTCALL _estrndup(const char *s, size_t length ZEND_FILE_LI
char *p;
if (UNEXPECTED(length + 1 == 0)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (1 * %zu + 1)", length);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length);
}
p = (char *) _emalloc(length + 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
memcpy(p, s, length);
@@ -2622,7 +2650,7 @@ ZEND_API char* ZEND_FASTCALL zend_strndup(const char *s, size_t length)
char *p;
if (UNEXPECTED(length + 1 == 0)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (1 * %zu + 1)", length);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length);
}
p = (char *) malloc(length + 1);
if (UNEXPECTED(p == NULL)) {
@@ -2901,7 +2929,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
static ZEND_COLD ZEND_NORETURN void zend_out_of_memory(void)
{
fprintf(stderr, "Out of memory\n");
- exit(1);
+ _exit(1);
}
ZEND_API void * __zend_malloc(size_t len)
diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h
index b3986ab9..992fa225 100644
--- a/Zend/zend_alloc.h
+++ b/Zend/zend_alloc.h
@@ -397,6 +397,8 @@ static void apc_init_heap(void)
*/
+ZEND_API ZEND_COLD ZEND_NORETURN void zend_mm_safe_error_ex(const char *format, ...);
+
END_EXTERN_C()
#endif
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 6eb9dfac..65e66fc8 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -265,8 +265,21 @@ void shutdown_executor(void) /* {{{ */
zend_close_rsrc_list(&EG(regular_list));
} zend_end_try();
+ if (fast_shutdown) {
+ /* may be used by zend_error before init_executor */
+ ZVAL_UNDEF(&EG(user_error_handler));
+ ZVAL_UNDEF(&EG(user_exception_handler));
+ memset(&EG(user_error_handlers_error_reporting), 0, sizeof(EG(user_error_handlers_error_reporting)));
+ memset(&EG(user_error_handlers), 0, sizeof(EG(user_error_handlers)));
+ memset(&EG(user_exception_handlers), 0, sizeof(EG(user_exception_handlers)));
+ }
+
zend_objects_store_free_object_storage(&EG(objects_store), fast_shutdown);
+ /* may be used by zend_error before init_executor */
+ EG(error_handling) = EH_NORMAL;
+ EG(exception) = NULL;
+
/* All resources and objects are destroyed. */
/* No PHP callback functions may be called after this point. */
EG(active) = 0;
@@ -285,6 +298,8 @@ void shutdown_executor(void) /* {{{ */
zend_hash_discard(EG(function_table), EG(persistent_functions_count));
zend_hash_discard(EG(class_table), EG(persistent_classes_count));
zend_cleanup_internal_classes();
+ EG(objects_store).object_buckets = NULL;
+ EG(objects_store).top = 1;
} else {
zend_hash_graceful_reverse_destroy(&EG(symbol_table));
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index 7ba4f32c..f228f335 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -93,7 +93,7 @@ static zend_always_inline uint32_t zend_hash_check_size(uint32_t nSize)
if (nSize <= HT_MIN_SIZE) {
return HT_MIN_SIZE;
} else if (UNEXPECTED(nSize >= HT_MAX_SIZE)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", nSize, sizeof(Bucket), sizeof(Bucket));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", nSize, sizeof(Bucket), sizeof(Bucket));
}
#if defined(ZEND_WIN32)
@@ -219,6 +219,13 @@ ZEND_API HashTable* ZEND_FASTCALL _zend_new_array_0(void)
return ht;
}
+ZEND_API HashTable* ZEND_FASTCALL zend_new_array_singleton(void)
+{
+ HashTable *ht = _zend_new_array_0();
+ ht->nTableSize = 1;
+ return ht;
+}
+
ZEND_API HashTable* ZEND_FASTCALL _zend_new_array(uint32_t nSize)
{
HashTable *ht = emalloc(sizeof(HashTable));
@@ -230,7 +237,7 @@ static void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht)
{
HT_ASSERT_RC1(ht);
if (ht->nTableSize >= HT_MAX_SIZE) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket));
}
ht->nTableSize += ht->nTableSize;
HT_SET_DATA_ADDR(ht, perealloc2(HT_GET_DATA_ADDR(ht), HT_SIZE_EX(ht->nTableSize, HT_MIN_MASK), HT_USED_SIZE(ht), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT));
@@ -1041,7 +1048,7 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
pefree(old_data, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
zend_hash_rehash(ht);
} else {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket) + sizeof(uint32_t), sizeof(Bucket));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket) + sizeof(uint32_t), sizeof(Bucket));
}
}
diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h
index 2c295adc..51dc4c5e 100644
--- a/Zend/zend_hash.h
+++ b/Zend/zend_hash.h
@@ -276,6 +276,7 @@ ZEND_API int ZEND_FASTCALL zend_hash_rehash(HashTable *ht);
#endif
ZEND_API HashTable* ZEND_FASTCALL _zend_new_array_0(void);
+ZEND_API HashTable* ZEND_FASTCALL zend_new_array_singleton(void);
ZEND_API HashTable* ZEND_FASTCALL _zend_new_array(uint32_t size);
ZEND_API uint32_t zend_array_count(HashTable *ht);
ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source);
diff --git a/Zend/zend_llist.c b/Zend/zend_llist.c
index ea5e2cae..f45ddda9 100644
--- a/Zend/zend_llist.c
+++ b/Zend/zend_llist.c
@@ -112,6 +112,8 @@ ZEND_API void zend_llist_destroy(zend_llist *l)
current = next;
}
+ l->head = NULL;
+ l->tail = NULL;
l->count = 0;
}
diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h
index 1ec1af06..ee2fd8df 100644
--- a/Zend/zend_multiply.h
+++ b/Zend/zend_multiply.h
@@ -321,7 +321,7 @@ static zend_always_inline size_t zend_safe_address_guarded(size_t nmemb, size_t
size_t ret = zend_safe_address(nmemb, size, offset, &overflow);
if (UNEXPECTED(overflow)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
return 0;
}
return ret;
@@ -334,7 +334,7 @@ static zend_always_inline size_t zend_safe_addmult(size_t nmemb, size_t size, si
size_t ret = zend_safe_address(nmemb, size, offset, &overflow);
if (UNEXPECTED(overflow)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in %s (%zu * %zu + %zu)", message, nmemb, size, offset);
+ zend_mm_safe_error_ex("Possible integer overflow in %s (%zu * %zu + %zu)", message, nmemb, size, offset);
return 0;
}
return ret;
diff --git a/Zend/zend_strtod.c b/Zend/zend_strtod.c
index 3aa99f8d..01c1779d 100644
--- a/Zend/zend_strtod.c
+++ b/Zend/zend_strtod.c
@@ -600,7 +600,7 @@ Balloc
rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
if (!rv) {
FREE_DTOA_LOCK(0);
- zend_error_noreturn(E_ERROR, "Balloc() failed to allocate memory");
+ zend_mm_safe_error_ex("Balloc() failed to allocate memory");
}
#else
len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
@@ -613,7 +613,7 @@ Balloc
rv = (Bigint*)MALLOC(len*sizeof(double));
if (!rv) {
FREE_DTOA_LOCK(0);
- zend_error_noreturn(E_ERROR, "Balloc() failed to allocate memory");
+ zend_mm_safe_error_ex("Balloc() failed to allocate memory");
}
#endif
rv->k = k;
diff --git a/Zend/zend_types.h b/Zend/zend_types.h
index 4250aabd..fd7e5d6a 100644
--- a/Zend/zend_types.h
+++ b/Zend/zend_types.h
@@ -317,17 +317,21 @@ struct _zend_array {
# define HT_HASH_RESET(ht) do { \
char *p = (char*)&HT_HASH(ht, (ht)->nTableMask); \
size_t size = HT_HASH_SIZE((ht)->nTableMask); \
- __m128i xmm0 = _mm_setzero_si128(); \
- xmm0 = _mm_cmpeq_epi8(xmm0, xmm0); \
- ZEND_ASSERT(size >= 64 && ((size & 0x3f) == 0)); \
- do { \
- _mm_storeu_si128((__m128i*)p, xmm0); \
- _mm_storeu_si128((__m128i*)(p+16), xmm0); \
- _mm_storeu_si128((__m128i*)(p+32), xmm0); \
- _mm_storeu_si128((__m128i*)(p+48), xmm0); \
- p += 64; \
- size -= 64; \
- } while (size != 0); \
+ if (UNEXPECTED(size < 64)) { \
+ memset(p, HT_INVALID_IDX, size); \
+ } else { \
+ __m128i xmm0 = _mm_setzero_si128(); \
+ xmm0 = _mm_cmpeq_epi8(xmm0, xmm0); \
+ ZEND_ASSERT(size >= 64 && ((size & 0x3f) == 0)); \
+ do { \
+ _mm_storeu_si128((__m128i*)p, xmm0); \
+ _mm_storeu_si128((__m128i*)(p+16), xmm0); \
+ _mm_storeu_si128((__m128i*)(p+32), xmm0); \
+ _mm_storeu_si128((__m128i*)(p+48), xmm0); \
+ p += 64; \
+ size -= 64; \
+ } while (size != 0); \
+ } \
} while (0)
#else
# define HT_HASH_RESET(ht) \
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 1b4eb572..da46a635 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -320,11 +320,17 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
FREE_OP2();
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -2744,11 +2750,17 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
FREE_OP2();
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index be8b2b3a..ce447cb9 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -4968,11 +4968,17 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -6679,11 +6685,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
zval_ptr_dtor_nogc(free_op2);
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -7150,11 +7162,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
zval_ptr_dtor_nogc(free_op2);
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -9774,11 +9792,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -10243,11 +10267,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HAND
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -12967,11 +12997,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -13732,11 +13768,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -14705,11 +14747,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
zval_ptr_dtor_nogc(free_op2);
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -15346,11 +15394,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
zval_ptr_dtor_nogc(free_op2);
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -16800,11 +16854,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER(
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -17227,11 +17287,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -38581,11 +38647,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -41090,11 +41162,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CONST_HAND
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -42559,11 +42637,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER(
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
zval_ptr_dtor_nogc(free_op2);
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -44857,11 +44941,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HAN
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
zval_ptr_dtor_nogc(free_op2);
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -48227,11 +48317,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -50659,11 +50755,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
diff --git a/ext/session/session.c b/ext/session/session.c
index 8fad988d..1c328815 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -3160,7 +3160,7 @@ static int php_session_rfc1867_callback(unsigned int event, void *event_data, vo
if (php_session_rfc1867_orig_callback) {
retval = php_session_rfc1867_orig_callback(event, event_data, extra);
}
- if (!PS(rfc1867_enabled)) {
+ if (!PS(rfc1867_enabled) || 1) {
return retval;
}
diff --git a/main/SAPI.c b/main/SAPI.c
index afb0c772..6749184e 100644
--- a/main/SAPI.c
+++ b/main/SAPI.c
@@ -513,18 +513,23 @@ SAPI_API void sapi_deactivate(void)
}
if (SG(request_info).auth_user) {
efree(SG(request_info).auth_user);
+ SG(request_info).auth_user = NULL;
}
if (SG(request_info).auth_password) {
efree(SG(request_info).auth_password);
+ SG(request_info).auth_password = NULL;
}
if (SG(request_info).auth_digest) {
efree(SG(request_info).auth_digest);
+ SG(request_info).auth_digest = NULL;
}
if (SG(request_info).content_type_dup) {
efree(SG(request_info).content_type_dup);
+ SG(request_info).content_type_dup = NULL;
}
if (SG(request_info).current_user) {
efree(SG(request_info).current_user);
+ SG(request_info).current_user = NULL;
}
if (sapi_module.deactivate) {
sapi_module.deactivate();
diff --git a/main/main.c b/main/main.c
index c3939b3c..6e38959a 100644
--- a/main/main.c
+++ b/main/main.c
@@ -1919,6 +1919,8 @@ void php_request_shutdown(void *dummy)
for (i=0; i<NUM_TRACK_VARS; i++) {
zval_ptr_dtor(&PG(http_globals)[i]);
+ /* May be accessed before php_request_startup() */
+ ZVAL_UNDEF(&PG(http_globals)[i]);
}
} zend_end_try();
@@ -1972,6 +1974,9 @@ void php_request_shutdown(void *dummy)
#ifdef HAVE_DTRACE
DTRACE_REQUEST_SHUTDOWN(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), (char *)SAFE_FILENAME(SG(request_info).request_method));
#endif /* HAVE_DTRACE */
+
+ /* May be accessed before php_request_startup() */
+ PG(modules_activated) = 0;
}
/* }}} */
diff --git a/main/php_variables.c b/main/php_variables.c
index d0ebd50e..9ebad5c8 100644
--- a/main/php_variables.c
+++ b/main/php_variables.c
@@ -219,7 +219,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
}
if (!index) {
- array_init(&gpc_element);
+ array_init_singleton(&gpc_element);
if ((gpc_element_p = zend_hash_next_index_insert(symtable1, &gpc_element)) == NULL) {
zend_array_destroy(Z_ARR(gpc_element));
zval_ptr_dtor_nogc(val);
@@ -236,7 +236,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
gpc_element_p = zend_symtable_str_find(symtable1, index, index_len);
if (!gpc_element_p) {
zval tmp;
- array_init(&tmp);
+ array_init_singleton(&tmp);
gpc_element_p = zend_symtable_str_update_ind(symtable1, index, index_len, &tmp);
} else {
if (Z_TYPE_P(gpc_element_p) == IS_INDIRECT) {
@@ -244,7 +244,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
}
if (Z_TYPE_P(gpc_element_p) != IS_ARRAY) {
zval_ptr_dtor_nogc(gpc_element_p);
- array_init(gpc_element_p);
+ array_init_singleton(gpc_element_p);
} else {
SEPARATE_ARRAY(gpc_element_p);
}
@@ -442,7 +442,7 @@ SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
case PARSE_POST:
case PARSE_GET:
case PARSE_COOKIE:
- array_init(&array);
+ array_init_singleton(&array);
switch (arg) {
case PARSE_POST:
zval_ptr_dtor_nogc(&PG(http_globals)[TRACK_VARS_POST]);
diff --git a/main/rfc1867.c b/main/rfc1867.c
index 3415db2f..265ca9e2 100644
--- a/main/rfc1867.c
+++ b/main/rfc1867.c
@@ -405,6 +405,14 @@ static int find_boundary(multipart_buffer *self, char *boundary)
return 0;
}
+static zend_bool php_mime_should_save_hdr(const char *name)
+{
+ return !strcasecmp(name, "Content-Disposition")
+ || !strcasecmp(name, "Content-Type");
+}
+
+static char *php_mime_get_hdr_value(zend_llist header, char *key);
+
/* parse headers */
static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header)
{
@@ -445,10 +453,15 @@ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header)
}
*value = '\0';
- do { value++; } while (isspace(*value));
-
- key = estrdup(line);
- smart_string_appends(&buf_value, value);
+ /* Keep only headers we use, and ignore duplicates */
+ if (!php_mime_should_save_hdr(line)
+ || php_mime_get_hdr_value(*header, line)) {
+ key = NULL;
+ } else {
+ key = estrdup(line);
+ do { value++; } while (isspace(*value));
+ smart_string_appends(&buf_value, value);
+ }
} else if (buf_value.c) { /* If no ':' on the line, add to previous line */
smart_string_appends(&buf_value, line);
} else {
@@ -522,11 +535,11 @@ static char *php_ap_getword(const zend_encoding *encoding, char **line, char sto
return res;
}
-static char *substring_conf(char *start, int len, char quote)
+static char *substring_conf(char *start, size_t len, char quote)
{
char *result = emalloc(len + 1);
char *resp = result;
- int i;
+ size_t i;
for (i = 0; i < len && start[i] != quote; ++i) {
if (start[i] == '\\' && (start[i + 1] == '\\' || (quote && start[i + 1] == quote))) {
@@ -554,14 +567,14 @@ static char *php_ap_getword_conf(const zend_encoding *encoding, char *str)
char quote = *str;
str++;
- return substring_conf(str, (int)strlen(str), quote);
+ return substring_conf(str, strlen(str), quote);
} else {
char *strend = str;
while (*strend && !isspace(*strend)) {
++strend;
}
- return substring_conf(str, strend - str, 0);
+ return substring_conf(str, (size_t)(strend - str), 0);
}
}
+3
View File
@@ -0,0 +1,3 @@
# https://salsa.debian.org/php-team/php/-/tree/ecf76f6726bee03657a2c608240685732312fe54/debian/patches (Sury 7.3.33-35)
0107-backport-ZSTR_MAX_LEN.patch
0139-Avoid-state-corruption-via-bailout.patch
@@ -0,0 +1,976 @@
From 712e60f9edfd03f0960fc4fc3c2c375f42b90aa2 Mon Sep 17 00:00:00 2001
From: Arnaud Le Blanc <arnaud.lb@gmail.com>
Date: Sun, 18 Oct 2026 20:09:54 +0200
Subject: [PATCH] Avoid state corruption via bailout
Minimal mitigation for EOL version.
Fix GHSA-w8hw-w9fx-j79w (CVE-2026-109618)
Fix GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)
Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>
---
Zend/zend_API.h | 1 +
Zend/zend_alloc.c | 68 ++++++++++++++++++++---------
Zend/zend_alloc.h | 2 +
Zend/zend_execute_API.c | 13 ++++++
Zend/zend_hash.c | 13 ++++--
Zend/zend_hash.h | 1 +
Zend/zend_llist.c | 2 +
Zend/zend_multiply.h | 4 +-
Zend/zend_strtod.c | 4 +-
Zend/zend_types.h | 26 +++++++-----
Zend/zend_vm_def.h | 11 ++++-
Zend/zend_vm_execute.h | 94 +++++++++++++++++++++++++++++++++++++----
ext/session/session.c | 2 +-
main/SAPI.c | 5 +++
main/main.c | 6 +++
main/php_variables.c | 8 ++--
main/rfc1867.c | 39 ++++++++++++++---
17 files changed, 240 insertions(+), 59 deletions(-)
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index 2a3b582902..26f7726bd8 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -380,6 +380,7 @@ ZEND_API char *zend_get_type_by_const(int type);
#define array_init(arg) ZVAL_ARR((arg), zend_new_array(0))
#define array_init_size(arg, size) ZVAL_ARR((arg), zend_new_array(size))
+#define array_init_singleton(arg) ZVAL_ARR((arg), zend_new_array_singleton())
ZEND_API int object_init(zval *arg);
ZEND_API int object_init_ex(zval *arg, zend_class_entry *ce);
ZEND_API int object_and_properties_init(zval *arg, zend_class_entry *ce, HashTable *properties);
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
index 3a33e5441c..be9b975426 100644
--- a/Zend/zend_alloc.c
+++ b/Zend/zend_alloc.c
@@ -57,6 +57,7 @@
#include "zend_operators.h"
#include "zend_multiply.h"
#include "zend_bitset.h"
+#include "zend_execute.h"
#include <signal.h>
#ifdef HAVE_UNISTD_H
@@ -363,7 +364,42 @@ static ZEND_COLD ZEND_NORETURN void zend_mm_panic(const char *message)
#if ZEND_DEBUG && defined(HAVE_KILL) && defined(HAVE_GETPID)
kill(getpid(), SIGSEGV);
#endif
- exit(1);
+ _exit(1);
+}
+
+ZEND_API ZEND_COLD ZEND_NORETURN void zend_mm_safe_error_ex(const char *format, ...)
+{
+ zend_string *script_filename = NULL;
+ uint32_t script_lineno = 0;
+
+ if (zend_is_executing()) {
+ script_filename = zend_get_executed_filename_ex();
+ script_lineno = zend_get_executed_lineno();
+ } else if (zend_is_compiling()) {
+ script_filename = zend_get_compiled_filename();
+ script_lineno = zend_get_compiled_lineno();
+ }
+
+ va_list args;
+ va_start(args, format);
+
+ char buf[1024];
+ vsnprintf(buf, sizeof(buf), format, args);
+
+ va_end(args);
+
+ fprintf(stderr,
+ "\nFatal error: %s in %s on line %d\n",
+ buf,
+ script_filename ? ZSTR_VAL(script_filename) : "Unknown",
+ script_lineno);
+
+ /* See http://support.microsoft.com/kb/190351 */
+# ifdef ZEND_WIN32
+ fflush(stderr);
+# endif
+
+ _exit(1);
}
static ZEND_COLD ZEND_NORETURN void zend_mm_safe_error(zend_mm_heap *heap,
@@ -375,22 +411,14 @@ static ZEND_COLD ZEND_NORETURN void zend_mm_safe_error(zend_mm_heap *heap,
#endif
size_t size)
{
+ (void) heap;
- heap->overflow = 1;
- zend_try {
- zend_error_noreturn(E_ERROR,
- format,
- limit,
+ zend_mm_safe_error_ex(format, limit,
#if ZEND_DEBUG
- filename,
- lineno,
+ filename,
+ lineno,
#endif
- size);
- } zend_catch {
- } zend_end_try();
- heap->overflow = 0;
- zend_bailout();
- exit(1);
+ size);
}
#ifdef _WIN32
@@ -1318,7 +1346,7 @@ static zend_always_inline void *zend_mm_alloc_heap(zend_mm_heap *heap, size_t si
size = MAX(size, 1);
size = ZEND_MM_ALIGNED_SIZE(size) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info));
if (UNEXPECTED(size < real_size)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu + %zu)", ZEND_MM_ALIGNED_SIZE(real_size), ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu + %zu)", ZEND_MM_ALIGNED_SIZE(real_size), ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
return NULL;
}
#endif
@@ -1762,7 +1790,7 @@ static void *zend_mm_alloc_huge(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D
void *ptr;
if (UNEXPECTED(new_size < size)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu + %zu)", size, alignment);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu + %zu)", size, alignment);
}
#if ZEND_MM_LIMIT
@@ -2617,7 +2645,7 @@ ZEND_API char* ZEND_FASTCALL _estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_
length = strlen(s);
if (UNEXPECTED(length + 1 == 0)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (1 * %zu + 1)", length);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length);
}
p = (char *) _emalloc(length + 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
memcpy(p, s, length+1);
@@ -2629,7 +2657,7 @@ ZEND_API char* ZEND_FASTCALL _estrndup(const char *s, size_t length ZEND_FILE_LI
char *p;
if (UNEXPECTED(length + 1 == 0)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (1 * %zu + 1)", length);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length);
}
p = (char *) _emalloc(length + 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
memcpy(p, s, length);
@@ -2643,7 +2671,7 @@ ZEND_API char* ZEND_FASTCALL zend_strndup(const char *s, size_t length)
char *p;
if (UNEXPECTED(length + 1 == 0)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (1 * %zu + 1)", length);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length);
}
p = (char *) malloc(length + 1);
if (UNEXPECTED(p == NULL)) {
@@ -2974,7 +3002,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
static ZEND_COLD ZEND_NORETURN void zend_out_of_memory(void)
{
fprintf(stderr, "Out of memory\n");
- exit(1);
+ _exit(1);
}
ZEND_API void * __zend_malloc(size_t len)
diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h
index 8bb854328d..2ed2ed8b3a 100644
--- a/Zend/zend_alloc.h
+++ b/Zend/zend_alloc.h
@@ -402,6 +402,8 @@ static void apc_init_heap(void)
size_t zend_mm_globals_size(void);
#endif
+ZEND_API ZEND_COLD ZEND_NORETURN void zend_mm_safe_error_ex(const char *format, ...);
+
END_EXTERN_C()
#endif
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index f4f0fa14f1..724b6e5cc4 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -337,10 +337,21 @@ void shutdown_executor(void) /* {{{ */
gc_collect_cycles();
}
#endif
+ } else {
+ /* may be used by zend_error_zstr_at before init_executor */
+ ZVAL_UNDEF(&EG(user_error_handler));
+ ZVAL_UNDEF(&EG(user_exception_handler));
+ memset(&EG(user_error_handlers_error_reporting), 0, sizeof(EG(user_error_handlers_error_reporting)));
+ memset(&EG(user_error_handlers), 0, sizeof(EG(user_error_handlers)));
+ memset(&EG(user_exception_handlers), 0, sizeof(EG(user_exception_handlers)));
}
zend_objects_store_free_object_storage(&EG(objects_store), fast_shutdown);
+ /* may be used by zend_error_zstr_at before init_executor */
+ EG(error_handling) = EH_NORMAL;
+ EG(exception) = NULL;
+
zend_weakrefs_shutdown();
zend_try {
@@ -357,6 +368,8 @@ void shutdown_executor(void) /* {{{ */
zend_hash_discard(EG(function_table), EG(persistent_functions_count));
zend_hash_discard(EG(class_table), EG(persistent_classes_count));
zend_cleanup_internal_classes();
+ EG(objects_store).object_buckets = NULL;
+ EG(objects_store).top = 1;
} else {
zend_vm_stack_destroy();
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index da150bd798..ef3d301db1 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -97,7 +97,7 @@ static zend_always_inline uint32_t zend_hash_check_size(uint32_t nSize)
if (nSize <= HT_MIN_SIZE) {
return HT_MIN_SIZE;
} else if (UNEXPECTED(nSize >= HT_MAX_SIZE)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", nSize, sizeof(Bucket), sizeof(Bucket));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", nSize, sizeof(Bucket), sizeof(Bucket));
}
#if defined(ZEND_WIN32)
@@ -251,6 +251,13 @@ ZEND_API HashTable* ZEND_FASTCALL _zend_new_array_0(void)
return ht;
}
+ZEND_API HashTable* ZEND_FASTCALL zend_new_array_singleton(void)
+{
+ HashTable *ht = _zend_new_array_0();
+ ht->nTableSize = 1;
+ return ht;
+}
+
ZEND_API HashTable* ZEND_FASTCALL _zend_new_array(uint32_t nSize)
{
HashTable *ht = emalloc(sizeof(HashTable));
@@ -282,7 +289,7 @@ static void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht)
{
HT_ASSERT_RC1(ht);
if (ht->nTableSize >= HT_MAX_SIZE) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket));
}
ht->nTableSize += ht->nTableSize;
HT_SET_DATA_ADDR(ht, perealloc2(HT_GET_DATA_ADDR(ht), HT_SIZE_EX(ht->nTableSize, HT_MIN_MASK), HT_USED_SIZE(ht), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT));
@@ -1164,7 +1171,7 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
pefree(old_data, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
zend_hash_rehash(ht);
} else {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket) + sizeof(uint32_t), sizeof(Bucket));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket) + sizeof(uint32_t), sizeof(Bucket));
}
}
diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h
index f1e2d34685..b833479eaa 100644
--- a/Zend/zend_hash.h
+++ b/Zend/zend_hash.h
@@ -296,6 +296,7 @@ ZEND_API int ZEND_FASTCALL zend_hash_rehash(HashTable *ht);
#endif
ZEND_API HashTable* ZEND_FASTCALL _zend_new_array_0(void);
+ZEND_API HashTable* ZEND_FASTCALL zend_new_array_singleton(void);
ZEND_API HashTable* ZEND_FASTCALL _zend_new_array(uint32_t size);
ZEND_API HashTable* ZEND_FASTCALL zend_new_pair(zval *val1, zval *val2);
ZEND_API uint32_t zend_array_count(HashTable *ht);
diff --git a/Zend/zend_llist.c b/Zend/zend_llist.c
index 4a2c22e632..0955e953aa 100644
--- a/Zend/zend_llist.c
+++ b/Zend/zend_llist.c
@@ -112,6 +112,8 @@ ZEND_API void zend_llist_destroy(zend_llist *l)
current = next;
}
+ l->head = NULL;
+ l->tail = NULL;
l->count = 0;
}
diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h
index a3827d25d1..a9bbda5538 100644
--- a/Zend/zend_multiply.h
+++ b/Zend/zend_multiply.h
@@ -321,7 +321,7 @@ static zend_always_inline size_t zend_safe_address_guarded(size_t nmemb, size_t
size_t ret = zend_safe_address(nmemb, size, offset, &overflow);
if (UNEXPECTED(overflow)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
return 0;
}
return ret;
@@ -334,7 +334,7 @@ static zend_always_inline size_t zend_safe_addmult(size_t nmemb, size_t size, si
size_t ret = zend_safe_address(nmemb, size, offset, &overflow);
if (UNEXPECTED(overflow)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in %s (%zu * %zu + %zu)", message, nmemb, size, offset);
+ zend_mm_safe_error_ex("Possible integer overflow in %s (%zu * %zu + %zu)", message, nmemb, size, offset);
return 0;
}
return ret;
diff --git a/Zend/zend_strtod.c b/Zend/zend_strtod.c
index 2228e2262c..ad8df201af 100644
--- a/Zend/zend_strtod.c
+++ b/Zend/zend_strtod.c
@@ -603,7 +603,7 @@ Balloc
rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
if (!rv) {
FREE_DTOA_LOCK(0);
- zend_error_noreturn(E_ERROR, "Balloc() failed to allocate memory");
+ zend_mm_safe_error_ex("Balloc() failed to allocate memory");
}
#else
len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
@@ -616,7 +616,7 @@ Balloc
rv = (Bigint*)MALLOC(len*sizeof(double));
if (!rv) {
FREE_DTOA_LOCK(0);
- zend_error_noreturn(E_ERROR, "Balloc() failed to allocate memory");
+ zend_mm_safe_error_ex("Balloc() failed to allocate memory");
}
#endif
rv->k = k;
diff --git a/Zend/zend_types.h b/Zend/zend_types.h
index 7b8c079c45..f7828eb6d3 100644
--- a/Zend/zend_types.h
+++ b/Zend/zend_types.h
@@ -330,17 +330,21 @@ struct _zend_array {
# define HT_HASH_RESET(ht) do { \
char *p = (char*)&HT_HASH(ht, (ht)->nTableMask); \
size_t size = HT_HASH_SIZE((ht)->nTableMask); \
- __m128i xmm0 = _mm_setzero_si128(); \
- xmm0 = _mm_cmpeq_epi8(xmm0, xmm0); \
- ZEND_ASSERT(size >= 64 && ((size & 0x3f) == 0)); \
- do { \
- _mm_storeu_si128((__m128i*)p, xmm0); \
- _mm_storeu_si128((__m128i*)(p+16), xmm0); \
- _mm_storeu_si128((__m128i*)(p+32), xmm0); \
- _mm_storeu_si128((__m128i*)(p+48), xmm0); \
- p += 64; \
- size -= 64; \
- } while (size != 0); \
+ if (UNEXPECTED(size < 64)) { \
+ memset(p, HT_INVALID_IDX, size); \
+ } else { \
+ __m128i xmm0 = _mm_setzero_si128(); \
+ xmm0 = _mm_cmpeq_epi8(xmm0, xmm0); \
+ ZEND_ASSERT(size >= 64 && ((size & 0x3f) == 0)); \
+ do { \
+ _mm_storeu_si128((__m128i*)p, xmm0); \
+ _mm_storeu_si128((__m128i*)(p+16), xmm0); \
+ _mm_storeu_si128((__m128i*)(p+32), xmm0); \
+ _mm_storeu_si128((__m128i*)(p+48), xmm0); \
+ p += 64; \
+ size -= 64; \
+ } while (size != 0); \
+ } \
} while (0)
#else
# define HT_HASH_RESET(ht) \
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index d362b01643..3af90d705b 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -417,7 +417,7 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_
size_t len = ZSTR_LEN(op1_str);
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
}
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -426,6 +426,9 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -3210,6 +3213,9 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -3217,6 +3223,9 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 2875fd3740..8701e77ea8 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -5631,6 +5631,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -5638,6 +5641,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -7491,6 +7497,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -7498,6 +7507,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -7900,7 +7912,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_
size_t len = ZSTR_LEN(op1_str);
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
}
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -7909,6 +7921,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -9952,6 +9967,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -9959,6 +9977,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -10361,7 +10382,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HAND
size_t len = ZSTR_LEN(op1_str);
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
}
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -10370,6 +10391,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HAND
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -13928,6 +13952,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -13935,6 +13962,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -14681,7 +14711,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_
size_t len = ZSTR_LEN(op1_str);
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
}
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -14690,6 +14720,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -15353,7 +15386,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND
size_t len = ZSTR_LEN(op1_str);
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
}
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -15362,6 +15395,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -16107,6 +16143,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -16114,6 +16153,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -17040,7 +17082,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER(
size_t len = ZSTR_LEN(op1_str);
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
}
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -17049,6 +17091,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER(
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -17401,6 +17446,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -17408,6 +17456,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -38348,7 +38399,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z
size_t len = ZSTR_LEN(op1_str);
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
}
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -38357,6 +38408,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -40727,7 +40781,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CONST_HAND
size_t len = ZSTR_LEN(op1_str);
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
}
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -40736,6 +40790,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CONST_HAND
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -41849,6 +41906,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER(
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -41856,6 +41916,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER(
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -44132,6 +44195,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HAN
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -44139,6 +44205,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HAN
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -46857,7 +46926,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND
size_t len = ZSTR_LEN(op1_str);
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
}
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -46866,6 +46935,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -49268,6 +49340,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -49275,6 +49350,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
diff --git a/ext/session/session.c b/ext/session/session.c
index 8fb6dd2cd5..89a7400a9c 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -3174,7 +3174,7 @@ static int php_session_rfc1867_callback(unsigned int event, void *event_data, vo
if (php_session_rfc1867_orig_callback) {
retval = php_session_rfc1867_orig_callback(event, event_data, extra);
}
- if (!PS(rfc1867_enabled)) {
+ if (!PS(rfc1867_enabled) || true) {
return retval;
}
diff --git a/main/SAPI.c b/main/SAPI.c
index a5a68f8c68..1c320f6e3f 100644
--- a/main/SAPI.c
+++ b/main/SAPI.c
@@ -509,18 +509,23 @@ SAPI_API void sapi_deactivate(void)
}
if (SG(request_info).auth_user) {
efree(SG(request_info).auth_user);
+ SG(request_info).auth_user = NULL;
}
if (SG(request_info).auth_password) {
efree(SG(request_info).auth_password);
+ SG(request_info).auth_password = NULL;
}
if (SG(request_info).auth_digest) {
efree(SG(request_info).auth_digest);
+ SG(request_info).auth_digest = NULL;
}
if (SG(request_info).content_type_dup) {
efree(SG(request_info).content_type_dup);
+ SG(request_info).content_type_dup = NULL;
}
if (SG(request_info).current_user) {
efree(SG(request_info).current_user);
+ SG(request_info).current_user = NULL;
}
if (sapi_module.deactivate) {
sapi_module.deactivate();
diff --git a/main/main.c b/main/main.c
index 0b33b2b56c..bb8501f973 100644
--- a/main/main.c
+++ b/main/main.c
@@ -836,6 +836,7 @@ PHP_INI_BEGIN()
PHP_INI_ENTRY("disable_functions", "", PHP_INI_SYSTEM, NULL)
PHP_INI_ENTRY("disable_classes", "", PHP_INI_SYSTEM, NULL)
PHP_INI_ENTRY("max_file_uploads", "20", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL)
+ PHP_INI_ENTRY("max_multipart_body_parts", "-1", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL)
STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_url_fopen, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("allow_url_include", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_url_include, php_core_globals, core_globals)
@@ -1960,6 +1961,8 @@ void php_request_shutdown(void *dummy)
for (i=0; i<NUM_TRACK_VARS; i++) {
zval_ptr_dtor(&PG(http_globals)[i]);
+ /* May be accessed before php_request_startup() */
+ ZVAL_UNDEF(&PG(http_globals)[i]);
}
} zend_end_try();
@@ -2012,6 +2015,9 @@ void php_request_shutdown(void *dummy)
#ifdef HAVE_DTRACE
DTRACE_REQUEST_SHUTDOWN(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), (char *)SAFE_FILENAME(SG(request_info).request_method));
#endif /* HAVE_DTRACE */
+
+ /* May be accessed before php_request_startup() */
+ PG(modules_activated) = 0;
}
/* }}} */
diff --git a/main/php_variables.c b/main/php_variables.c
index 18f6b65a6c..c920e4d5e2 100644
--- a/main/php_variables.c
+++ b/main/php_variables.c
@@ -218,7 +218,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
}
if (!index) {
- array_init(&gpc_element);
+ array_init_singleton(&gpc_element);
if ((gpc_element_p = zend_hash_next_index_insert(symtable1, &gpc_element)) == NULL) {
zend_array_destroy(Z_ARR(gpc_element));
zval_ptr_dtor_nogc(val);
@@ -229,7 +229,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
gpc_element_p = zend_symtable_str_find(symtable1, index, index_len);
if (!gpc_element_p) {
zval tmp;
- array_init(&tmp);
+ array_init_singleton(&tmp);
gpc_element_p = zend_symtable_str_update_ind(symtable1, index, index_len, &tmp);
} else {
if (Z_TYPE_P(gpc_element_p) == IS_INDIRECT) {
@@ -237,7 +237,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
}
if (Z_TYPE_P(gpc_element_p) != IS_ARRAY) {
zval_ptr_dtor_nogc(gpc_element_p);
- array_init(gpc_element_p);
+ array_init_singleton(gpc_element_p);
} else {
SEPARATE_ARRAY(gpc_element_p);
}
@@ -429,7 +429,7 @@ SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
case PARSE_POST:
case PARSE_GET:
case PARSE_COOKIE:
- array_init(&array);
+ array_init_singleton(&array);
switch (arg) {
case PARSE_POST:
zval_ptr_dtor_nogc(&PG(http_globals)[TRACK_VARS_POST]);
diff --git a/main/rfc1867.c b/main/rfc1867.c
index edef19c16d..4946df0ca2 100644
--- a/main/rfc1867.c
+++ b/main/rfc1867.c
@@ -397,6 +397,14 @@ static int find_boundary(multipart_buffer *self, char *boundary)
return 0;
}
+static zend_bool php_mime_should_save_hdr(const char *name)
+{
+ return !strcasecmp(name, "Content-Disposition")
+ || !strcasecmp(name, "Content-Type");
+}
+
+static char *php_mime_get_hdr_value(zend_llist header, char *key);
+
/* parse headers */
static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header)
{
@@ -437,10 +445,16 @@ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header)
}
*value = '\0';
- do { value++; } while (isspace(*value));
- key = estrdup(line);
- smart_string_appends(&buf_value, value);
+ /* Keep only headers we use, and ignore duplicates */
+ if (!php_mime_should_save_hdr(line)
+ || php_mime_get_hdr_value(*header, line)) {
+ key = NULL;
+ } else {
+ key = estrdup(line);
+ do { value++; } while (isspace((unsigned char)*value));
+ smart_string_appends(&buf_value, value);
+ }
} else if (buf_value.c) { /* If no ':' on the line, add to previous line */
smart_string_appends(&buf_value, line);
} else {
@@ -514,11 +528,11 @@ static char *php_ap_getword(const zend_encoding *encoding, char **line, char sto
return res;
}
-static char *substring_conf(char *start, int len, char quote)
+static char *substring_conf(char *start, size_t len, char quote)
{
char *result = emalloc(len + 1);
char *resp = result;
- int i;
+ size_t i;
for (i = 0; i < len && start[i] != quote; ++i) {
if (start[i] == '\\' && (start[i + 1] == '\\' || (quote && start[i + 1] == quote))) {
@@ -546,14 +560,14 @@ static char *php_ap_getword_conf(const zend_encoding *encoding, char *str)
char quote = *str;
str++;
- return substring_conf(str, (int)strlen(str), quote);
+ return substring_conf(str, strlen(str), quote);
} else {
char *strend = str;
while (*strend && !isspace(*strend)) {
++strend;
}
- return substring_conf(str, strend - str, 0);
+ return substring_conf(str, (size_t)(strend - str), 0);
}
}
@@ -694,6 +708,7 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
void *event_extra_data = NULL;
unsigned int llen = 0;
int upload_cnt = INI_INT("max_file_uploads");
+ int body_parts_cnt = INI_INT("max_multipart_body_parts");
const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding();
php_rfc1867_getword_t getword;
php_rfc1867_getword_conf_t getword_conf;
@@ -715,6 +730,11 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
return;
}
+ if (body_parts_cnt < 0) {
+ body_parts_cnt = PG(max_input_vars) + upload_cnt;
+ }
+ int body_parts_limit = body_parts_cnt;
+
/* Get the boundary */
boundary = strstr(content_type_dup, "boundary");
if (!boundary) {
@@ -799,6 +819,11 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
char *pair = NULL;
int end = 0;
+ if (--body_parts_cnt < 0) {
+ php_error_docref(NULL, E_WARNING, "Multipart body parts limit exceeded %d. To increase the limit change max_multipart_body_parts in php.ini.", body_parts_limit);
+ goto fileupload_done;
+ }
+
while (isspace(*cd)) {
++cd;
}
--
2.56.0
+2
View File
@@ -0,0 +1,2 @@
# https://github.com/php/php-src/commit/712e60f9edfd03f0960fc4fc3c2c375f42b90aa2 (branch PHP-7.4-CVE-2026-109618-109619)
0001-Avoid-state-corruption-via-bailout.patch
@@ -0,0 +1,944 @@
From 82f8f31b16a035c1b67cc253e79f7cc288f4cc20 Mon Sep 17 00:00:00 2001
From: Arnaud Le Blanc <arnaud.lb@gmail.com>
Date: Sun, 18 Oct 2026 20:11:52 +0200
Subject: [PATCH] Avoid state corruption via bailout
Minimal mitigation for EOL version.
Fix GHSA-w8hw-w9fx-j79w (CVE-2026-109618)
Fix GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)
Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>
---
Zend/zend_API.h | 1 +
Zend/zend_alloc.c | 68 ++++++++++++++++++++---------
Zend/zend_alloc.h | 2 +
Zend/zend_execute_API.c | 13 ++++++
Zend/zend_hash.c | 13 ++++--
Zend/zend_hash.h | 1 +
Zend/zend_llist.c | 2 +
Zend/zend_multiply.h | 4 +-
Zend/zend_strtod.c | 4 +-
Zend/zend_types.h | 26 +++++++-----
Zend/zend_vm_def.h | 11 ++++-
Zend/zend_vm_execute.h | 94 +++++++++++++++++++++++++++++++++++++----
ext/session/session.c | 2 +-
main/SAPI.c | 5 +++
main/main.c | 6 +++
main/php_variables.c | 8 ++--
main/rfc1867.c | 28 +++++++++---
17 files changed, 229 insertions(+), 59 deletions(-)
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index 456ef05d80..0d015bacf3 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -428,6 +428,7 @@ ZEND_API const char *zend_get_type_by_const(int type);
#define array_init(arg) ZVAL_ARR((arg), zend_new_array(0))
#define array_init_size(arg, size) ZVAL_ARR((arg), zend_new_array(size))
+#define array_init_singleton(arg) ZVAL_ARR((arg), zend_new_array_singleton())
ZEND_API void object_init(zval *arg);
ZEND_API zend_result object_init_ex(zval *arg, zend_class_entry *ce);
ZEND_API zend_result object_and_properties_init(zval *arg, zend_class_entry *ce, HashTable *properties);
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
index 6e0ce4b651..a21b10f9be 100644
--- a/Zend/zend_alloc.c
+++ b/Zend/zend_alloc.c
@@ -57,6 +57,7 @@
#include "zend_operators.h"
#include "zend_multiply.h"
#include "zend_bitset.h"
+#include "zend_execute.h"
#include <signal.h>
#ifdef HAVE_UNISTD_H
@@ -363,7 +364,42 @@ static ZEND_COLD ZEND_NORETURN void zend_mm_panic(const char *message)
#if ZEND_DEBUG && defined(HAVE_KILL) && defined(HAVE_GETPID)
kill(getpid(), SIGSEGV);
#endif
- exit(1);
+ _exit(1);
+}
+
+ZEND_API ZEND_COLD ZEND_NORETURN void zend_mm_safe_error_ex(const char *format, ...)
+{
+ zend_string *script_filename = NULL;
+ uint32_t script_lineno = 0;
+
+ if (zend_is_executing()) {
+ script_filename = zend_get_executed_filename_ex();
+ script_lineno = zend_get_executed_lineno();
+ } else if (zend_is_compiling()) {
+ script_filename = zend_get_compiled_filename();
+ script_lineno = zend_get_compiled_lineno();
+ }
+
+ va_list args;
+ va_start(args, format);
+
+ char buf[1024];
+ vsnprintf(buf, sizeof(buf), format, args);
+
+ va_end(args);
+
+ fprintf(stderr,
+ "\nFatal error: %s in %s on line %d\n",
+ buf,
+ script_filename ? ZSTR_VAL(script_filename) : "Unknown",
+ script_lineno);
+
+ /* See http://support.microsoft.com/kb/190351 */
+# ifdef ZEND_WIN32
+ fflush(stderr);
+# endif
+
+ _exit(1);
}
static ZEND_COLD ZEND_NORETURN void zend_mm_safe_error(zend_mm_heap *heap,
@@ -375,22 +411,14 @@ static ZEND_COLD ZEND_NORETURN void zend_mm_safe_error(zend_mm_heap *heap,
#endif
size_t size)
{
+ (void) heap;
- heap->overflow = 1;
- zend_try {
- zend_error_noreturn(E_ERROR,
- format,
- limit,
+ zend_mm_safe_error_ex(format, limit,
#if ZEND_DEBUG
- filename,
- lineno,
+ filename,
+ lineno,
#endif
- size);
- } zend_catch {
- } zend_end_try();
- heap->overflow = 0;
- zend_bailout();
- exit(1);
+ size);
}
#ifdef _WIN32
@@ -1318,7 +1346,7 @@ static zend_always_inline void *zend_mm_alloc_heap(zend_mm_heap *heap, size_t si
size = MAX(size, 1);
size = ZEND_MM_ALIGNED_SIZE(size) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info));
if (UNEXPECTED(size < real_size)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu + %zu)", ZEND_MM_ALIGNED_SIZE(real_size), ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu + %zu)", ZEND_MM_ALIGNED_SIZE(real_size), ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
return NULL;
}
#endif
@@ -1762,7 +1790,7 @@ static void *zend_mm_alloc_huge(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D
void *ptr;
if (UNEXPECTED(new_size < size)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu + %zu)", size, alignment);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu + %zu)", size, alignment);
}
#if ZEND_MM_LIMIT
@@ -2618,7 +2646,7 @@ ZEND_API char* ZEND_FASTCALL _estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_
length = strlen(s);
if (UNEXPECTED(length + 1 == 0)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (1 * %zu + 1)", length);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length);
}
p = (char *) _emalloc(length + 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
memcpy(p, s, length+1);
@@ -2630,7 +2658,7 @@ ZEND_API char* ZEND_FASTCALL _estrndup(const char *s, size_t length ZEND_FILE_LI
char *p;
if (UNEXPECTED(length + 1 == 0)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (1 * %zu + 1)", length);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length);
}
p = (char *) _emalloc(length + 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
memcpy(p, s, length);
@@ -2644,7 +2672,7 @@ ZEND_API char* ZEND_FASTCALL zend_strndup(const char *s, size_t length)
char *p;
if (UNEXPECTED(length + 1 == 0)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (1 * %zu + 1)", length);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length);
}
p = (char *) malloc(length + 1);
if (UNEXPECTED(p == NULL)) {
@@ -3048,7 +3076,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
static ZEND_COLD ZEND_NORETURN void zend_out_of_memory(void)
{
fprintf(stderr, "Out of memory\n");
- exit(1);
+ _exit(1);
}
ZEND_API void * __zend_malloc(size_t len)
diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h
index de450bbca2..f6bc82d250 100644
--- a/Zend/zend_alloc.h
+++ b/Zend/zend_alloc.h
@@ -403,6 +403,8 @@ static void apc_init_heap(void)
size_t zend_mm_globals_size(void);
#endif
+ZEND_API ZEND_COLD ZEND_NORETURN void zend_mm_safe_error_ex(const char *format, ...);
+
END_EXTERN_C()
#endif
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 18104c2d99..2f19a17c6b 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -334,10 +334,21 @@ void shutdown_executor(void) /* {{{ */
gc_collect_cycles();
}
#endif
+ } else {
+ /* may be used by zend_error_zstr_at before init_executor */
+ ZVAL_UNDEF(&EG(user_error_handler));
+ ZVAL_UNDEF(&EG(user_exception_handler));
+ memset(&EG(user_error_handlers_error_reporting), 0, sizeof(EG(user_error_handlers_error_reporting)));
+ memset(&EG(user_error_handlers), 0, sizeof(EG(user_error_handlers)));
+ memset(&EG(user_exception_handlers), 0, sizeof(EG(user_exception_handlers)));
}
zend_objects_store_free_object_storage(&EG(objects_store), fast_shutdown);
+ /* may be used by zend_error_zstr_at before init_executor */
+ EG(error_handling) = EH_NORMAL;
+ EG(exception) = NULL;
+
zend_weakrefs_shutdown();
zend_try {
@@ -354,6 +365,8 @@ void shutdown_executor(void) /* {{{ */
zend_hash_discard(EG(function_table), EG(persistent_functions_count));
zend_hash_discard(EG(class_table), EG(persistent_classes_count));
zend_cleanup_internal_classes();
+ EG(objects_store).object_buckets = NULL;
+ EG(objects_store).top = 1;
} else {
zend_vm_stack_destroy();
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index a3b62160dc..a4c318d123 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -119,7 +119,7 @@ static zend_always_inline uint32_t zend_hash_check_size(uint32_t nSize)
if (nSize <= HT_MIN_SIZE) {
return HT_MIN_SIZE;
} else if (UNEXPECTED(nSize >= HT_MAX_SIZE)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", nSize, sizeof(Bucket), sizeof(Bucket));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", nSize, sizeof(Bucket), sizeof(Bucket));
}
#ifdef ZEND_WIN32
@@ -273,6 +273,13 @@ ZEND_API HashTable* ZEND_FASTCALL _zend_new_array_0(void)
return ht;
}
+ZEND_API HashTable* ZEND_FASTCALL zend_new_array_singleton(void)
+{
+ HashTable *ht = _zend_new_array_0();
+ ht->nTableSize = 1;
+ return ht;
+}
+
ZEND_API HashTable* ZEND_FASTCALL _zend_new_array(uint32_t nSize)
{
HashTable *ht = emalloc(sizeof(HashTable));
@@ -304,7 +311,7 @@ static void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht)
{
HT_ASSERT_RC1(ht);
if (ht->nTableSize >= HT_MAX_SIZE) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket));
}
ht->nTableSize += ht->nTableSize;
HT_SET_DATA_ADDR(ht, perealloc2(HT_GET_DATA_ADDR(ht), HT_SIZE_EX(ht->nTableSize, HT_MIN_MASK), HT_USED_SIZE(ht), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT));
@@ -1190,7 +1197,7 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
pefree(old_data, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
zend_hash_rehash(ht);
} else {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket) + sizeof(uint32_t), sizeof(Bucket));
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket) + sizeof(uint32_t), sizeof(Bucket));
}
}
diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h
index ced21a2ca1..b697acf587 100644
--- a/Zend/zend_hash.h
+++ b/Zend/zend_hash.h
@@ -296,6 +296,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_rehash(HashTable *ht);
#endif
ZEND_API HashTable* ZEND_FASTCALL _zend_new_array_0(void);
+ZEND_API HashTable* ZEND_FASTCALL zend_new_array_singleton(void);
ZEND_API HashTable* ZEND_FASTCALL _zend_new_array(uint32_t size);
ZEND_API HashTable* ZEND_FASTCALL zend_new_pair(zval *val1, zval *val2);
ZEND_API uint32_t zend_array_count(HashTable *ht);
diff --git a/Zend/zend_llist.c b/Zend/zend_llist.c
index 78a3310438..8c42b2494e 100644
--- a/Zend/zend_llist.c
+++ b/Zend/zend_llist.c
@@ -112,6 +112,8 @@ ZEND_API void zend_llist_destroy(zend_llist *l)
current = next;
}
+ l->head = NULL;
+ l->tail = NULL;
l->count = 0;
}
diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h
index c6cd472a23..bfe1b8e886 100644
--- a/Zend/zend_multiply.h
+++ b/Zend/zend_multiply.h
@@ -321,7 +321,7 @@ static zend_always_inline size_t zend_safe_address_guarded(size_t nmemb, size_t
size_t ret = zend_safe_address(nmemb, size, offset, &overflow);
if (UNEXPECTED(overflow)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
+ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
return 0;
}
return ret;
@@ -334,7 +334,7 @@ static zend_always_inline size_t zend_safe_addmult(size_t nmemb, size_t size, si
size_t ret = zend_safe_address(nmemb, size, offset, &overflow);
if (UNEXPECTED(overflow)) {
- zend_error_noreturn(E_ERROR, "Possible integer overflow in %s (%zu * %zu + %zu)", message, nmemb, size, offset);
+ zend_mm_safe_error_ex("Possible integer overflow in %s (%zu * %zu + %zu)", message, nmemb, size, offset);
return 0;
}
return ret;
diff --git a/Zend/zend_strtod.c b/Zend/zend_strtod.c
index e88fbd001f..fd6b23c9cb 100644
--- a/Zend/zend_strtod.c
+++ b/Zend/zend_strtod.c
@@ -603,7 +603,7 @@ Balloc
rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
if (!rv) {
FREE_DTOA_LOCK(0);
- zend_error_noreturn(E_ERROR, "Balloc() failed to allocate memory");
+ zend_mm_safe_error_ex("Balloc() failed to allocate memory");
}
#else
len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
@@ -616,7 +616,7 @@ Balloc
rv = (Bigint*)MALLOC(len*sizeof(double));
if (!rv) {
FREE_DTOA_LOCK(0);
- zend_error_noreturn(E_ERROR, "Balloc() failed to allocate memory");
+ zend_mm_safe_error_ex("Balloc() failed to allocate memory");
}
#endif
rv->k = k;
diff --git a/Zend/zend_types.h b/Zend/zend_types.h
index 82cf20f1b5..1a10ba718c 100644
--- a/Zend/zend_types.h
+++ b/Zend/zend_types.h
@@ -439,17 +439,21 @@ struct _zend_array {
# define HT_HASH_RESET(ht) do { \
char *p = (char*)&HT_HASH(ht, (ht)->nTableMask); \
size_t size = HT_HASH_SIZE((ht)->nTableMask); \
- __m128i xmm0 = _mm_setzero_si128(); \
- xmm0 = _mm_cmpeq_epi8(xmm0, xmm0); \
- ZEND_ASSERT(size >= 64 && ((size & 0x3f) == 0)); \
- do { \
- _mm_storeu_si128((__m128i*)p, xmm0); \
- _mm_storeu_si128((__m128i*)(p+16), xmm0); \
- _mm_storeu_si128((__m128i*)(p+32), xmm0); \
- _mm_storeu_si128((__m128i*)(p+48), xmm0); \
- p += 64; \
- size -= 64; \
- } while (size != 0); \
+ if (UNEXPECTED(size < 64)) { \
+ memset(p, HT_INVALID_IDX, size); \
+ } else { \
+ __m128i xmm0 = _mm_setzero_si128(); \
+ xmm0 = _mm_cmpeq_epi8(xmm0, xmm0); \
+ ZEND_ASSERT(size >= 64 && ((size & 0x3f) == 0)); \
+ do { \
+ _mm_storeu_si128((__m128i*)p, xmm0); \
+ _mm_storeu_si128((__m128i*)(p+16), xmm0); \
+ _mm_storeu_si128((__m128i*)(p+32), xmm0); \
+ _mm_storeu_si128((__m128i*)(p+48), xmm0); \
+ p += 64; \
+ size -= 64; \
+ } while (size != 0); \
+ } \
} while (0)
#else
# define HT_HASH_RESET(ht) \
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index bcb9be8dab..406350ef26 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -408,7 +408,7 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_
size_t len = ZSTR_LEN(op1_str);
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
}
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -417,6 +417,9 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -3157,6 +3160,9 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -3164,6 +3170,9 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 049d0f2126..eeca7ebb75 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -6348,6 +6348,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -6355,6 +6358,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -8225,7 +8231,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL
size_t len = ZSTR_LEN(op1_str);
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
}
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -8234,6 +8240,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -8641,6 +8650,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -8648,6 +8660,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -10613,7 +10628,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z
size_t len = ZSTR_LEN(op1_str);
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
}
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -10622,6 +10637,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -11029,6 +11047,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HAND
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -11036,6 +11057,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HAND
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -14644,7 +14668,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL
size_t len = ZSTR_LEN(op1_str);
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
}
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -14653,6 +14677,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -15374,6 +15401,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -15381,6 +15411,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -16067,7 +16100,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND
size_t len = ZSTR_LEN(op1_str);
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
}
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -16076,6 +16109,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -16797,6 +16833,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -16804,6 +16843,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -17744,7 +17786,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER(
size_t len = ZSTR_LEN(op1_str);
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
}
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -17753,6 +17795,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER(
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -18112,6 +18157,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -18119,6 +18167,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -39226,7 +39277,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z
size_t len = ZSTR_LEN(op1_str);
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
}
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -39235,6 +39286,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -41677,6 +41731,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CONST_HAND
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -41684,6 +41741,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CONST_HAND
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -42951,7 +43011,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER(
size_t len = ZSTR_LEN(op1_str);
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
}
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -42960,6 +43020,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER(
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -45331,6 +45394,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HAN
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -45338,6 +45404,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HAN
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -48150,7 +48219,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND
size_t len = ZSTR_LEN(op1_str);
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
}
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -48159,6 +48228,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
@@ -50629,6 +50701,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
size_t len = ZSTR_LEN(op1_str);
+ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -50636,6 +50711,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER
zend_string_release_ex(op2_str, 0);
}
} else {
+ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+ zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ }
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
diff --git a/ext/session/session.c b/ext/session/session.c
index 3c875296c3..0c45b1bb41 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -3017,7 +3017,7 @@ static int php_session_rfc1867_callback(unsigned int event, void *event_data, vo
if (php_session_rfc1867_orig_callback) {
retval = php_session_rfc1867_orig_callback(event, event_data, extra);
}
- if (!PS(rfc1867_enabled)) {
+ if (!PS(rfc1867_enabled) || true) {
return retval;
}
diff --git a/main/SAPI.c b/main/SAPI.c
index eea417cedc..85d964d21b 100644
--- a/main/SAPI.c
+++ b/main/SAPI.c
@@ -503,18 +503,23 @@ SAPI_API void sapi_deactivate_module(void)
}
if (SG(request_info).auth_user) {
efree(SG(request_info).auth_user);
+ SG(request_info).auth_user = NULL;
}
if (SG(request_info).auth_password) {
efree(SG(request_info).auth_password);
+ SG(request_info).auth_password = NULL;
}
if (SG(request_info).auth_digest) {
efree(SG(request_info).auth_digest);
+ SG(request_info).auth_digest = NULL;
}
if (SG(request_info).content_type_dup) {
efree(SG(request_info).content_type_dup);
+ SG(request_info).content_type_dup = NULL;
}
if (SG(request_info).current_user) {
efree(SG(request_info).current_user);
+ SG(request_info).current_user = NULL;
}
if (sapi_module.deactivate) {
sapi_module.deactivate();
diff --git a/main/main.c b/main/main.c
index c58ea58bf5..48feda4bc7 100644
--- a/main/main.c
+++ b/main/main.c
@@ -1847,6 +1847,8 @@ void php_request_shutdown(void *dummy)
for (i=0; i<NUM_TRACK_VARS; i++) {
zval_ptr_dtor(&PG(http_globals)[i]);
+ /* May be accessed before php_request_startup() */
+ ZVAL_UNDEF(&PG(http_globals)[i]);
}
} zend_end_try();
@@ -1878,6 +1880,7 @@ void php_request_shutdown(void *dummy)
/* 15. Free Willy (here be crashes) */
zend_interned_strings_deactivate();
+ clear_last_error();
zend_try {
shutdown_memory_manager(CG(unclean_shutdown) || !report_memleaks, 0);
} zend_end_try();
@@ -1901,6 +1904,9 @@ void php_request_shutdown(void *dummy)
#ifdef HAVE_DTRACE
DTRACE_REQUEST_SHUTDOWN(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), (char *)SAFE_FILENAME(SG(request_info).request_method));
#endif /* HAVE_DTRACE */
+
+ /* May be accessed before php_request_startup() */
+ PG(modules_activated) = 0;
}
/* }}} */
diff --git a/main/php_variables.c b/main/php_variables.c
index 27a9ad089e..b17673060a 100644
--- a/main/php_variables.c
+++ b/main/php_variables.c
@@ -213,7 +213,7 @@ PHPAPI void php_register_variable_ex(const char *var_name, zval *val, zval *trac
}
if (!index) {
- array_init(&gpc_element);
+ array_init_singleton(&gpc_element);
if ((gpc_element_p = zend_hash_next_index_insert(symtable1, &gpc_element)) == NULL) {
zend_array_destroy(Z_ARR(gpc_element));
zval_ptr_dtor_nogc(val);
@@ -224,7 +224,7 @@ PHPAPI void php_register_variable_ex(const char *var_name, zval *val, zval *trac
gpc_element_p = zend_symtable_str_find(symtable1, index, index_len);
if (!gpc_element_p) {
zval tmp;
- array_init(&tmp);
+ array_init_singleton(&tmp);
gpc_element_p = zend_symtable_str_update_ind(symtable1, index, index_len, &tmp);
} else {
if (Z_TYPE_P(gpc_element_p) == IS_INDIRECT) {
@@ -232,7 +232,7 @@ PHPAPI void php_register_variable_ex(const char *var_name, zval *val, zval *trac
}
if (Z_TYPE_P(gpc_element_p) != IS_ARRAY) {
zval_ptr_dtor_nogc(gpc_element_p);
- array_init(gpc_element_p);
+ array_init_singleton(gpc_element_p);
} else {
SEPARATE_ARRAY(gpc_element_p);
}
@@ -424,7 +424,7 @@ SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
case PARSE_POST:
case PARSE_GET:
case PARSE_COOKIE:
- array_init(&array);
+ array_init_singleton(&array);
switch (arg) {
case PARSE_POST:
zval_ptr_dtor_nogc(&PG(http_globals)[TRACK_VARS_POST]);
diff --git a/main/rfc1867.c b/main/rfc1867.c
index 3086e8da3d..b64574505d 100644
--- a/main/rfc1867.c
+++ b/main/rfc1867.c
@@ -390,6 +390,14 @@ static int find_boundary(multipart_buffer *self, char *boundary)
return 0;
}
+static zend_bool php_mime_should_save_hdr(const char *name)
+{
+ return !strcasecmp(name, "Content-Disposition")
+ || !strcasecmp(name, "Content-Type");
+}
+
+static char *php_mime_get_hdr_value(zend_llist header, char *key);
+
/* parse headers */
static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header)
{
@@ -430,10 +438,16 @@ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header)
}
*value = '\0';
- do { value++; } while (isspace(*value));
- key = estrdup(line);
- smart_string_appends(&buf_value, value);
+ /* Keep only headers we use, and ignore duplicates */
+ if (!php_mime_should_save_hdr(line)
+ || php_mime_get_hdr_value(*header, line)) {
+ key = NULL;
+ } else {
+ key = estrdup(line);
+ do { value++; } while (isspace((unsigned char)*value));
+ smart_string_appends(&buf_value, value);
+ }
} else if (buf_value.c) { /* If no ':' on the line, add to previous line */
smart_string_appends(&buf_value, line);
} else {
@@ -507,11 +521,11 @@ static char *php_ap_getword(const zend_encoding *encoding, char **line, char sto
return res;
}
-static char *substring_conf(char *start, int len, char quote)
+static char *substring_conf(char *start, size_t len, char quote)
{
char *result = emalloc(len + 1);
char *resp = result;
- int i;
+ size_t i;
for (i = 0; i < len && start[i] != quote; ++i) {
if (start[i] == '\\' && (start[i + 1] == '\\' || (quote && start[i + 1] == quote))) {
@@ -539,14 +553,14 @@ static char *php_ap_getword_conf(const zend_encoding *encoding, char *str)
char quote = *str;
str++;
- return substring_conf(str, (int)strlen(str), quote);
+ return substring_conf(str, strlen(str), quote);
} else {
char *strend = str;
while (*strend && !isspace(*strend)) {
++strend;
}
- return substring_conf(str, strend - str, 0);
+ return substring_conf(str, (size_t)(strend - str), 0);
}
}
--
2.56.0
+2
View File
@@ -0,0 +1,2 @@
# https://github.com/php/php-src/commit/82f8f31b16a035c1b67cc253e79f7cc288f4cc20 (branch PHP-8.0-CVE-2026-109618-109619)
0001-Avoid-state-corruption-via-bailout.patch
File diff suppressed because it is too large Load Diff
+2
View File
@@ -0,0 +1,2 @@
# https://github.com/php/php-src/commit/1d7dec178a094e6e75b229ce22754045f8c6070a (branch PHP-8.1-CVE-2026-109618-109619)
0001-Avoid-state-corruption-via-bailout.patch
+43
View File
@@ -0,0 +1,43 @@
#!/bin/sh
set -eu
# Applies the patches listed in "$1/series" to /usr/src/php.tar.xz and repacks it in place, so the
# official build and any later "docker-php-ext-install" compile the patched sources.
patchDir="$1"
src=/usr/src/php.tar.xz
work="$(mktemp -d)"
installed=
# busybox's patch (old Alpine releases) lacks -d and the long options used below
if ! patch --version 2> /dev/null | grep -q GNU; then
if command -v apk > /dev/null; then
apk add --no-cache --virtual .patch-deps patch
else
apt-get update
apt-get install -y --no-install-recommends patch
rm -rf /var/lib/apt/lists/*
fi
installed=1
fi
mkdir "$work/php"
tar -xJf "$src" -C "$work/php" --strip-components=1
grep -v -e '^[[:space:]]*#' -e '^[[:space:]]*$' "$patchDir/series" | while read -r p; do
echo "Applying $p"
patch -d "$work/php" -p1 --forward --no-backup-if-mismatch < "$patchDir/$p"
done
tar -cJf "$src" -C "$work" php
# the upstream signature no longer matches the repacked tarball
rm -f "$src.asc"
rm -rf "$work"
if [ -n "$installed" ]; then
if command -v apk > /dev/null; then
apk del --no-network .patch-deps
else
apt-get purge -y --auto-remove patch
fi
fi
+40
View File
@@ -0,0 +1,40 @@
#!/bin/bash
set -e
# Note: we don't just use "apache2ctl" here because it itself is just a shell-script wrapper around apache2 which provides extra functionality like "apache2ctl start" for launching apache2 in the background.
# (also, when run as "apache2ctl <apache args>", it does not use "exec", which leaves an undesirable resident shell process)
: "${APACHE_CONFDIR:=/etc/apache2}"
: "${APACHE_ENVVARS:=$APACHE_CONFDIR/envvars}"
if test -f "$APACHE_ENVVARS"; then
. "$APACHE_ENVVARS"
fi
# Apache gets grumpy about PID files pre-existing
: "${APACHE_RUN_DIR:=/var/run/apache2}"
: "${APACHE_PID_FILE:=$APACHE_RUN_DIR/apache2.pid}"
rm -f "$APACHE_PID_FILE"
# create missing directories
# (especially APACHE_RUN_DIR, APACHE_LOCK_DIR, and APACHE_LOG_DIR)
for e in "${!APACHE_@}"; do
if [[ "$e" == *_DIR ]] && [[ "${!e}" == /* ]]; then
# handle "/var/lock" being a symlink to "/run/lock", but "/run/lock" not existing beforehand, so "/var/lock/something" fails to mkdir
# mkdir: cannot create directory '/var/lock': File exists
dir="${!e}"
while [ "$dir" != "$(dirname "$dir")" ]; do
dir="$(dirname "$dir")"
if [ -d "$dir" ]; then
break
fi
absDir="$(readlink -f "$dir" 2>/dev/null || :)"
if [ -n "$absDir" ]; then
mkdir -p "$absDir"
fi
done
mkdir -p "${!e}"
fi
done
exec apache2 -DFOREGROUND "$@"
+9
View File
@@ -0,0 +1,9 @@
#!/bin/sh
set -e
# first arg is `-f` or `--some-option`
if [ "${1#-}" != "$1" ]; then
set -- apache2-foreground "$@"
fi
exec "$@"
+9
View File
@@ -0,0 +1,9 @@
#!/bin/sh
set -e
# first arg is `-f` or `--some-option`
if [ "${1#-}" != "$1" ]; then
set -- php "$@"
fi
exec "$@"
+9
View File
@@ -0,0 +1,9 @@
#!/bin/sh
set -e
# first arg is `-f` or `--some-option`
if [ "${1#-}" != "$1" ]; then
set -- php-fpm "$@"
fi
exec "$@"
+69
View File
@@ -0,0 +1,69 @@
#!/bin/sh
set -e
# prefer user supplied CFLAGS, but default to our PHP_CFLAGS
: ${CFLAGS:=$PHP_CFLAGS}
: ${CPPFLAGS:=$PHP_CPPFLAGS}
: ${LDFLAGS:=$PHP_LDFLAGS}
export CFLAGS CPPFLAGS LDFLAGS
srcExists=
if [ -d /usr/src/php ]; then
srcExists=1
fi
docker-php-source extract
if [ -z "$srcExists" ]; then
touch /usr/src/php/.docker-delete-me
fi
cd /usr/src/php/ext
usage() {
echo "usage: $0 ext-name [configure flags]"
echo " ie: $0 gd --with-jpeg-dir=/usr/local/something"
echo
echo 'Possible values for ext-name:'
find . \
-mindepth 2 \
-maxdepth 2 \
-type f \
-name 'config.m4' \
| xargs -n1 dirname \
| xargs -n1 basename \
| sort \
| xargs
echo
echo 'Some of the above modules are already compiled into PHP; please check'
echo 'the output of "php -i" to see which modules are already loaded.'
}
ext="$1"
if [ -z "$ext" ] || [ ! -d "$ext" ]; then
usage >&2
exit 1
fi
shift
pm='unknown'
if [ -e /lib/apk/db/installed ]; then
pm='apk'
fi
if [ "$pm" = 'apk' ]; then
if \
[ -n "$PHPIZE_DEPS" ] \
&& ! apk info --installed .phpize-deps > /dev/null \
&& ! apk info --installed .phpize-deps-configure > /dev/null \
; then
apk add --no-cache --virtual .phpize-deps-configure $PHPIZE_DEPS
fi
fi
if command -v dpkg-architecture > /dev/null; then
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"
set -- --build="$gnuArch" "$@"
fi
cd "$ext"
phpize
./configure "$@"
+69
View File
@@ -0,0 +1,69 @@
#!/bin/sh
set -e
# prefer user supplied CFLAGS, but default to our PHP_CFLAGS
: ${CFLAGS:=$PHP_CFLAGS}
: ${CPPFLAGS:=$PHP_CPPFLAGS}
: ${LDFLAGS:=$PHP_LDFLAGS}
export CFLAGS CPPFLAGS LDFLAGS
srcExists=
if [ -d /usr/src/php ]; then
srcExists=1
fi
docker-php-source extract
if [ -z "$srcExists" ]; then
touch /usr/src/php/.docker-delete-me
fi
cd /usr/src/php/ext
usage() {
echo "usage: $0 ext-name [configure flags]"
echo " ie: $0 gd --with-jpeg-dir=/usr/local/something"
echo
echo 'Possible values for ext-name:'
find . \
-mindepth 2 \
-maxdepth 2 \
-type f \
-name 'config.m4' \
| xargs -n1 dirname \
| xargs -n1 basename \
| sort \
| xargs
echo
echo 'Some of the above modules are already compiled into PHP; please check'
echo 'the output of "php -i" to see which modules are already loaded.'
}
ext="$1"
if [ -z "$ext" ] || [ ! -d "$ext" ]; then
usage >&2
exit 1
fi
shift
pm='unknown'
if [ -e /lib/apk/db/installed ]; then
pm='apk'
fi
if [ "$pm" = 'apk' ]; then
if \
[ -n "$PHPIZE_DEPS" ] \
&& ! apk info --installed .phpize-deps > /dev/null \
&& ! apk info --installed .phpize-deps-configure > /dev/null \
; then
apk add --no-cache --virtual .phpize-deps-configure $PHPIZE_DEPS
fi
fi
if command -v dpkg-architecture > /dev/null; then
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"
set -- --build="$gnuArch" "$@"
fi
cd "$ext"
phpize
./configure --enable-option-checking=fatal "$@"
+114
View File
@@ -0,0 +1,114 @@
#!/bin/sh
set -e
extDir="$(php -r 'echo ini_get("extension_dir");')"
cd "$extDir"
usage() {
echo "usage: $0 [options] module-name [module-name ...]"
echo " ie: $0 gd mysqli"
echo " $0 pdo pdo_mysql"
echo " $0 --ini-name 0-apc.ini apcu apc"
echo
echo 'Possible values for module-name:'
find -maxdepth 1 \
-type f \
-name '*.so' \
-exec basename '{}' ';' \
| sort \
| xargs
echo
echo 'Some of the above modules are already compiled into PHP; please check'
echo 'the output of "php -i" to see which modules are already loaded.'
}
opts="$(getopt -o 'h?' --long 'help,ini-name:' -- "$@" || { usage >&2 && false; })"
eval set -- "$opts"
iniName=
while true; do
flag="$1"
shift
case "$flag" in
--help|-h|'-?') usage && exit 0 ;;
--ini-name) iniName="$1" && shift ;;
--) break ;;
*)
{
echo "error: unknown flag: $flag"
usage
} >&2
exit 1
;;
esac
done
modules=
for module; do
if [ -z "$module" ]; then
continue
fi
if [ -f "$module.so" ] && ! [ -f "$module" ]; then
# allow ".so" to be optional
module="$module.so"
fi
if ! [ -f "$module" ]; then
echo >&2 "error: '$module' does not exist"
echo >&2
usage >&2
exit 1
fi
modules="$modules $module"
done
if [ -z "$modules" ]; then
usage >&2
exit 1
fi
pm='unknown'
if [ -e /lib/apk/db/installed ]; then
pm='apk'
fi
apkDel=
if [ "$pm" = 'apk' ]; then
if \
[ -n "$PHPIZE_DEPS" ] \
&& ! apk info --installed .phpize-deps > /dev/null \
&& ! apk info --installed .phpize-deps-configure > /dev/null \
; then
apk add --no-cache --virtual '.docker-php-ext-enable-deps' binutils
apkDel='.docker-php-ext-enable-deps'
fi
fi
for module in $modules; do
if readelf --wide --syms "$module" | grep -q ' zend_extension_entry$'; then
# https://wiki.php.net/internals/extensions#loading_zend_extensions
absModule="$(readlink -f "$module")"
line="zend_extension=$absModule"
else
line="extension=$module"
fi
ext="$(basename "$module")"
ext="${ext%.*}"
if php -r 'exit(extension_loaded("'"$ext"'") ? 0 : 1);'; then
# this isn't perfect, but it's better than nothing
# (for example, 'opcache.so' presents inside PHP as 'Zend OPcache', not 'opcache')
echo >&2
echo >&2 "warning: $ext ($module) is already loaded!"
echo >&2
continue
fi
ini="$PHP_INI_DIR/conf.d/${iniName:-"docker-php-ext-$ext.ini"}"
if ! grep -q "$line" "$ini" 2>/dev/null; then
echo "$line" >> "$ini"
fi
done
if [ "$pm" = 'apk' ] && [ -n "$apkDel" ]; then
apk del $apkDel
fi
+114
View File
@@ -0,0 +1,114 @@
#!/bin/sh
set -e
extDir="$(php -d 'display_errors=stderr' -r 'echo ini_get("extension_dir");')"
cd "$extDir"
usage() {
echo "usage: $0 [options] module-name [module-name ...]"
echo " ie: $0 gd mysqli"
echo " $0 pdo pdo_mysql"
echo " $0 --ini-name 0-apc.ini apcu apc"
echo
echo 'Possible values for module-name:'
find -maxdepth 1 \
-type f \
-name '*.so' \
-exec basename '{}' ';' \
| sort \
| xargs
echo
echo 'Some of the above modules are already compiled into PHP; please check'
echo 'the output of "php -i" to see which modules are already loaded.'
}
opts="$(getopt -o 'h?' --long 'help,ini-name:' -- "$@" || { usage >&2 && false; })"
eval set -- "$opts"
iniName=
while true; do
flag="$1"
shift
case "$flag" in
--help|-h|'-?') usage && exit 0 ;;
--ini-name) iniName="$1" && shift ;;
--) break ;;
*)
{
echo "error: unknown flag: $flag"
usage
} >&2
exit 1
;;
esac
done
modules=
for module; do
if [ -z "$module" ]; then
continue
fi
if [ -f "$module.so" ] && ! [ -f "$module" ]; then
# allow ".so" to be optional
module="$module.so"
fi
if ! [ -f "$module" ]; then
echo >&2 "error: '$module' does not exist"
echo >&2
usage >&2
exit 1
fi
modules="$modules $module"
done
if [ -z "$modules" ]; then
usage >&2
exit 1
fi
pm='unknown'
if [ -e /lib/apk/db/installed ]; then
pm='apk'
fi
apkDel=
if [ "$pm" = 'apk' ]; then
if \
[ -n "$PHPIZE_DEPS" ] \
&& ! apk info --installed .phpize-deps > /dev/null \
&& ! apk info --installed .phpize-deps-configure > /dev/null \
; then
apk add --no-cache --virtual '.docker-php-ext-enable-deps' binutils
apkDel='.docker-php-ext-enable-deps'
fi
fi
for module in $modules; do
if readelf --wide --syms "$module" | grep -q ' zend_extension_entry$'; then
# https://wiki.php.net/internals/extensions#loading_zend_extensions
absModule="$(readlink -f "$module")"
line="zend_extension=$absModule"
else
line="extension=$module"
fi
ext="$(basename "$module")"
ext="${ext%.*}"
if php -d 'display_errors=stderr' -r 'exit(extension_loaded("'"$ext"'") ? 0 : 1);'; then
# this isn't perfect, but it's better than nothing
# (for example, 'opcache.so' presents inside PHP as 'Zend OPcache', not 'opcache')
echo >&2
echo >&2 "warning: $ext ($module) is already loaded!"
echo >&2
continue
fi
ini="$PHP_INI_DIR/conf.d/${iniName:-"docker-php-ext-$ext.ini"}"
if ! grep -q "$line" "$ini" 2>/dev/null; then
echo "$line" >> "$ini"
fi
done
if [ "$pm" = 'apk' ] && [ -n "$apkDel" ]; then
apk del --no-network $apkDel
fi
+121
View File
@@ -0,0 +1,121 @@
#!/bin/sh
set -e
extDir="$(php -d 'display_errors=stderr' -r 'echo ini_get("extension_dir");')"
cd "$extDir"
usage() {
echo "usage: $0 [options] module-name [module-name ...]"
echo " ie: $0 gd mysqli"
echo " $0 pdo pdo_mysql"
echo " $0 --ini-name 0-apc.ini apcu apc"
echo
echo 'Possible values for module-name:'
find -maxdepth 1 \
-type f \
-name '*.so' \
-exec basename '{}' ';' \
| sort \
| xargs
echo
echo 'Some of the above modules are already compiled into PHP; please check'
echo 'the output of "php -i" to see which modules are already loaded.'
}
opts="$(getopt -o 'h?' --long 'help,ini-name:' -- "$@" || { usage >&2 && false; })"
eval set -- "$opts"
iniName=
while true; do
flag="$1"
shift
case "$flag" in
--help|-h|'-?') usage && exit 0 ;;
--ini-name) iniName="$1" && shift ;;
--) break ;;
*)
{
echo "error: unknown flag: $flag"
usage
} >&2
exit 1
;;
esac
done
modules=
for module; do
if [ -z "$module" ]; then
continue
fi
if ! [ -f "$module" ] && ! [ -f "$module.so" ]; then
echo >&2 "error: '$module' does not exist"
echo >&2
usage >&2
exit 1
fi
modules="$modules $module"
done
if [ -z "$modules" ]; then
usage >&2
exit 1
fi
pm='unknown'
if [ -e /lib/apk/db/installed ]; then
pm='apk'
fi
apkDel=
if [ "$pm" = 'apk' ]; then
if \
[ -n "$PHPIZE_DEPS" ] \
&& ! apk info --installed .phpize-deps > /dev/null \
&& ! apk info --installed .phpize-deps-configure > /dev/null \
; then
apk add --no-cache --virtual '.docker-php-ext-enable-deps' binutils
apkDel='.docker-php-ext-enable-deps'
fi
fi
for module in $modules; do
moduleFile="$module"
if [ -f "$module.so" ] && ! [ -f "$module" ]; then
moduleFile="$module.so"
fi
if readelf --wide --syms "$moduleFile" | grep -q ' zend_extension_entry$'; then
# https://wiki.php.net/internals/extensions#loading_zend_extensions
line="zend_extension=$module"
else
line="extension=$module"
fi
ext="$(basename "$module")"
ext="${ext%.*}"
if php -d 'display_errors=stderr' -r 'exit(extension_loaded("'"$ext"'") ? 0 : 1);'; then
# this isn't perfect, but it's better than nothing
# (for example, 'opcache.so' presents inside PHP as 'Zend OPcache', not 'opcache')
echo >&2
echo >&2 "warning: $ext ($module) is already loaded!"
echo >&2
continue
fi
case "$iniName" in
/*)
# allow an absolute path
ini="$iniName"
;;
*)
ini="$PHP_INI_DIR/conf.d/${iniName:-"docker-php-ext-$ext.ini"}"
;;
esac
if ! grep -q "$line" "$ini" 2>/dev/null; then
echo "$line" >> "$ini"
fi
done
if [ "$pm" = 'apk' ] && [ -n "$apkDel" ]; then
apk del --no-network $apkDel
fi
+121
View File
@@ -0,0 +1,121 @@
#!/bin/sh
set -e
extDir="$(php -d 'display_errors=stderr' -r 'echo ini_get("extension_dir");')"
cd "$extDir"
usage() {
echo "usage: $0 [options] module-name [module-name ...]"
echo " ie: $0 gd mysqli"
echo " $0 pdo pdo_mysql"
echo " $0 --ini-name 0-apc.ini apcu apc"
echo
echo 'Possible values for module-name:'
find -maxdepth 1 \
-type f \
-name '*.so' \
-exec basename '{}' ';' \
| sort \
| xargs
echo
echo 'Some of the above modules are already compiled into PHP; please check'
echo 'the output of "php -i" to see which modules are already loaded.'
}
opts="$(getopt -o 'h?' --long 'help,ini-name:' -- "$@" || { usage >&2 && false; })"
eval set -- "$opts"
iniName=
while true; do
flag="$1"
shift
case "$flag" in
--help|-h|'-?') usage && exit 0 ;;
--ini-name) iniName="$1" && shift ;;
--) break ;;
*)
{
echo "error: unknown flag: $flag"
usage
} >&2
exit 1
;;
esac
done
modules=
for module; do
if [ -z "$module" ]; then
continue
fi
if ! [ -f "$module" ] && ! [ -f "$module.so" ]; then
echo >&2 "error: '$module' does not exist"
echo >&2
usage >&2
exit 1
fi
modules="$modules $module"
done
if [ -z "$modules" ]; then
usage >&2
exit 1
fi
pm='unknown'
if [ -e /lib/apk/db/installed ]; then
pm='apk'
fi
apkDel=
if [ "$pm" = 'apk' ]; then
if \
[ -n "$PHPIZE_DEPS" ] \
&& ! apk info --installed .phpize-deps > /dev/null \
&& ! apk info --installed .phpize-deps-configure > /dev/null \
; then
apk add --no-cache --virtual '.docker-php-ext-enable-deps' binutils
apkDel='.docker-php-ext-enable-deps'
fi
fi
for module in $modules; do
moduleFile="$module"
if [ -f "$module.so" ] && ! [ -f "$module" ]; then
moduleFile="$module.so"
fi
if readelf --wide --syms "$moduleFile" | grep -q ' zend_extension_entry$'; then
# https://wiki.php.net/internals/extensions#loading_zend_extensions
line="zend_extension=$module"
else
line="extension=$module"
fi
ext="$(basename "$module")"
ext="${ext%.*}"
if php -d 'display_errors=stderr' -r 'exit(extension_loaded("'"$ext"'") ? 0 : 1);'; then
# this isn't perfect, but it's better than nothing
# (for example, 'opcache.so' presents inside PHP as 'Zend OPcache', not 'opcache')
echo >&2
echo >&2 "warning: $ext ($module) is already loaded!"
echo >&2
continue
fi
case "$iniName" in
/*)
# allow an absolute path
ini="$iniName"
;;
*)
ini="$PHP_INI_DIR/conf.d/${iniName:-"docker-php-ext-$ext.ini"}"
;;
esac
if ! grep -qFx -e "$line" -e "$line.so" "$ini" 2>/dev/null; then
echo "$line" >> "$ini"
fi
done
if [ "$pm" = 'apk' ] && [ -n "$apkDel" ]; then
apk del --no-network $apkDel
fi
+122
View File
@@ -0,0 +1,122 @@
#!/bin/sh
set -e
# prefer user supplied CFLAGS, but default to our PHP_CFLAGS
: ${CFLAGS:=$PHP_CFLAGS}
: ${CPPFLAGS:=$PHP_CPPFLAGS}
: ${LDFLAGS:=$PHP_LDFLAGS}
export CFLAGS CPPFLAGS LDFLAGS
srcExists=
if [ -d /usr/src/php ]; then
srcExists=1
fi
docker-php-source extract
if [ -z "$srcExists" ]; then
touch /usr/src/php/.docker-delete-me
fi
cd /usr/src/php/ext
usage() {
echo "usage: $0 [-jN] ext-name [ext-name ...]"
echo " ie: $0 gd mysqli"
echo " $0 pdo pdo_mysql"
echo " $0 -j5 gd mbstring mysqli pdo pdo_mysql shmop"
echo
echo 'if custom ./configure arguments are necessary, see docker-php-ext-configure'
echo
echo 'Possible values for ext-name:'
find . \
-mindepth 2 \
-maxdepth 2 \
-type f \
-name 'config.m4' \
| xargs -n1 dirname \
| xargs -n1 basename \
| sort \
| xargs
echo
echo 'Some of the above modules are already compiled into PHP; please check'
echo 'the output of "php -i" to see which modules are already loaded.'
}
opts="$(getopt -o 'h?j:' --long 'help,jobs:' -- "$@" || { usage >&2 && false; })"
eval set -- "$opts"
j=1
while true; do
flag="$1"
shift
case "$flag" in
--help|-h|'-?') usage && exit 0 ;;
--jobs|-j) j="$1" && shift ;;
--) break ;;
*)
{
echo "error: unknown flag: $flag"
usage
} >&2
exit 1
;;
esac
done
exts=
for ext; do
if [ -z "$ext" ]; then
continue
fi
if [ ! -d "$ext" ]; then
echo >&2 "error: $PWD/$ext does not exist"
echo >&2
usage >&2
exit 1
fi
exts="$exts $ext"
done
if [ -z "$exts" ]; then
usage >&2
exit 1
fi
pm='unknown'
if [ -e /lib/apk/db/installed ]; then
pm='apk'
fi
apkDel=
if [ "$pm" = 'apk' ]; then
if [ -n "$PHPIZE_DEPS" ]; then
if apk info --installed .phpize-deps-configure > /dev/null; then
apkDel='.phpize-deps-configure'
elif ! apk info --installed .phpize-deps > /dev/null; then
apk add --no-cache --virtual .phpize-deps $PHPIZE_DEPS
apkDel='.phpize-deps'
fi
fi
fi
popDir="$PWD"
for ext in $exts; do
cd "$ext"
[ -e Makefile ] || docker-php-ext-configure "$ext"
make -j"$j"
make -j"$j" install
find modules \
-maxdepth 1 \
-name '*.so' \
-exec basename '{}' ';' \
| xargs -r docker-php-ext-enable
make -j"$j" clean
cd "$popDir"
done
if [ "$pm" = 'apk' ] && [ -n "$apkDel" ]; then
apk del $apkDel
fi
if [ -e /usr/src/php/.docker-delete-me ]; then
docker-php-source delete
fi
+122
View File
@@ -0,0 +1,122 @@
#!/bin/sh
set -e
# prefer user supplied CFLAGS, but default to our PHP_CFLAGS
: ${CFLAGS:=$PHP_CFLAGS}
: ${CPPFLAGS:=$PHP_CPPFLAGS}
: ${LDFLAGS:=$PHP_LDFLAGS}
export CFLAGS CPPFLAGS LDFLAGS
srcExists=
if [ -d /usr/src/php ]; then
srcExists=1
fi
docker-php-source extract
if [ -z "$srcExists" ]; then
touch /usr/src/php/.docker-delete-me
fi
cd /usr/src/php/ext
usage() {
echo "usage: $0 [-jN] ext-name [ext-name ...]"
echo " ie: $0 gd mysqli"
echo " $0 pdo pdo_mysql"
echo " $0 -j5 gd mbstring mysqli pdo pdo_mysql shmop"
echo
echo 'if custom ./configure arguments are necessary, see docker-php-ext-configure'
echo
echo 'Possible values for ext-name:'
find . \
-mindepth 2 \
-maxdepth 2 \
-type f \
-name 'config.m4' \
| xargs -n1 dirname \
| xargs -n1 basename \
| sort \
| xargs
echo
echo 'Some of the above modules are already compiled into PHP; please check'
echo 'the output of "php -i" to see which modules are already loaded.'
}
opts="$(getopt -o 'h?j:' --long 'help,jobs:' -- "$@" || { usage >&2 && false; })"
eval set -- "$opts"
j=1
while true; do
flag="$1"
shift
case "$flag" in
--help|-h|'-?') usage && exit 0 ;;
--jobs|-j) j="$1" && shift ;;
--) break ;;
*)
{
echo "error: unknown flag: $flag"
usage
} >&2
exit 1
;;
esac
done
exts=
for ext; do
if [ -z "$ext" ]; then
continue
fi
if [ ! -d "$ext" ]; then
echo >&2 "error: $PWD/$ext does not exist"
echo >&2
usage >&2
exit 1
fi
exts="$exts $ext"
done
if [ -z "$exts" ]; then
usage >&2
exit 1
fi
pm='unknown'
if [ -e /lib/apk/db/installed ]; then
pm='apk'
fi
apkDel=
if [ "$pm" = 'apk' ]; then
if [ -n "$PHPIZE_DEPS" ]; then
if apk info --installed .phpize-deps-configure > /dev/null; then
apkDel='.phpize-deps-configure'
elif ! apk info --installed .phpize-deps > /dev/null; then
apk add --no-cache --virtual .phpize-deps $PHPIZE_DEPS
apkDel='.phpize-deps'
fi
fi
fi
popDir="$PWD"
for ext in $exts; do
cd "$ext"
[ -e Makefile ] || docker-php-ext-configure "$ext"
make -j"$j"
make -j"$j" install
find modules \
-maxdepth 1 \
-name '*.so' \
-exec basename '{}' ';' \
| xargs -r docker-php-ext-enable
make -j"$j" clean
cd "$popDir"
done
if [ "$pm" = 'apk' ] && [ -n "$apkDel" ]; then
apk del --no-network $apkDel
fi
if [ -e /usr/src/php/.docker-delete-me ]; then
docker-php-source delete
fi
+124
View File
@@ -0,0 +1,124 @@
#!/bin/sh
set -e
# prefer user supplied CFLAGS, but default to our PHP_CFLAGS
: ${CFLAGS:=$PHP_CFLAGS}
: ${CPPFLAGS:=$PHP_CPPFLAGS}
: ${LDFLAGS:=$PHP_LDFLAGS}
export CFLAGS CPPFLAGS LDFLAGS
srcExists=
if [ -d /usr/src/php ]; then
srcExists=1
fi
docker-php-source extract
if [ -z "$srcExists" ]; then
touch /usr/src/php/.docker-delete-me
fi
cd /usr/src/php/ext
usage() {
echo "usage: $0 [-jN] [--ini-name file.ini] ext-name [ext-name ...]"
echo " ie: $0 gd mysqli"
echo " $0 pdo pdo_mysql"
echo " $0 -j5 gd mbstring mysqli pdo pdo_mysql shmop"
echo
echo 'if custom ./configure arguments are necessary, see docker-php-ext-configure'
echo
echo 'Possible values for ext-name:'
find . \
-mindepth 2 \
-maxdepth 2 \
-type f \
-name 'config.m4' \
| xargs -n1 dirname \
| xargs -n1 basename \
| sort \
| xargs
echo
echo 'Some of the above modules are already compiled into PHP; please check'
echo 'the output of "php -i" to see which modules are already loaded.'
}
opts="$(getopt -o 'h?j:' --long 'help,ini-name:,jobs:' -- "$@" || { usage >&2 && false; })"
eval set -- "$opts"
j=1
iniName=
while true; do
flag="$1"
shift
case "$flag" in
--help|-h|'-?') usage && exit 0 ;;
--ini-name) iniName="$1" && shift ;;
--jobs|-j) j="$1" && shift ;;
--) break ;;
*)
{
echo "error: unknown flag: $flag"
usage
} >&2
exit 1
;;
esac
done
exts=
for ext; do
if [ -z "$ext" ]; then
continue
fi
if [ ! -d "$ext" ]; then
echo >&2 "error: $PWD/$ext does not exist"
echo >&2
usage >&2
exit 1
fi
exts="$exts $ext"
done
if [ -z "$exts" ]; then
usage >&2
exit 1
fi
pm='unknown'
if [ -e /lib/apk/db/installed ]; then
pm='apk'
fi
apkDel=
if [ "$pm" = 'apk' ]; then
if [ -n "$PHPIZE_DEPS" ]; then
if apk info --installed .phpize-deps-configure > /dev/null; then
apkDel='.phpize-deps-configure'
elif ! apk info --installed .phpize-deps > /dev/null; then
apk add --no-cache --virtual .phpize-deps $PHPIZE_DEPS
apkDel='.phpize-deps'
fi
fi
fi
popDir="$PWD"
for ext in $exts; do
cd "$ext"
[ -e Makefile ] || docker-php-ext-configure "$ext"
make -j"$j"
make -j"$j" install
find modules \
-maxdepth 1 \
-name '*.so' \
-exec basename '{}' ';' \
| xargs -r docker-php-ext-enable ${iniName:+--ini-name "$iniName"}
make -j"$j" clean
cd "$popDir"
done
if [ "$pm" = 'apk' ] && [ -n "$apkDel" ]; then
apk del --no-network $apkDel
fi
if [ -e /usr/src/php/.docker-delete-me ]; then
docker-php-source delete
fi
+130
View File
@@ -0,0 +1,130 @@
#!/bin/sh
set -e
# prefer user supplied CFLAGS, but default to our PHP_CFLAGS
: ${CFLAGS:=$PHP_CFLAGS}
: ${CPPFLAGS:=$PHP_CPPFLAGS}
: ${LDFLAGS:=$PHP_LDFLAGS}
export CFLAGS CPPFLAGS LDFLAGS
srcExists=
if [ -d /usr/src/php ]; then
srcExists=1
fi
docker-php-source extract
if [ -z "$srcExists" ]; then
touch /usr/src/php/.docker-delete-me
fi
cd /usr/src/php/ext
usage() {
echo "usage: $0 [-jN] [--ini-name file.ini] ext-name [ext-name ...]"
echo " ie: $0 gd mysqli"
echo " $0 pdo pdo_mysql"
echo " $0 -j5 gd mbstring mysqli pdo pdo_mysql shmop"
echo
echo 'if custom ./configure arguments are necessary, see docker-php-ext-configure'
echo
echo 'Possible values for ext-name:'
find . \
-mindepth 2 \
-maxdepth 2 \
-type f \
-name 'config.m4' \
| xargs -n1 dirname \
| xargs -n1 basename \
| sort \
| xargs
echo
echo 'Some of the above modules are already compiled into PHP; please check'
echo 'the output of "php -i" to see which modules are already loaded.'
}
opts="$(getopt -o 'h?j:' --long 'help,ini-name:,jobs:' -- "$@" || { usage >&2 && false; })"
eval set -- "$opts"
j=1
iniName=
while true; do
flag="$1"
shift
case "$flag" in
--help|-h|'-?') usage && exit 0 ;;
--ini-name) iniName="$1" && shift ;;
--jobs|-j) j="$1" && shift ;;
--) break ;;
*)
{
echo "error: unknown flag: $flag"
usage
} >&2
exit 1
;;
esac
done
exts=
for ext; do
if [ -z "$ext" ]; then
continue
fi
if [ ! -d "$ext" ]; then
echo >&2 "error: $PWD/$ext does not exist"
echo >&2
usage >&2
exit 1
fi
exts="$exts $ext"
done
if [ -z "$exts" ]; then
usage >&2
exit 1
fi
pm='unknown'
if [ -e /lib/apk/db/installed ]; then
pm='apk'
fi
apkDel=
if [ "$pm" = 'apk' ]; then
if [ -n "$PHPIZE_DEPS" ]; then
if apk info --installed .phpize-deps-configure > /dev/null; then
apkDel='.phpize-deps-configure'
elif ! apk info --installed .phpize-deps > /dev/null; then
apk add --no-cache --virtual .phpize-deps $PHPIZE_DEPS
apkDel='.phpize-deps'
fi
fi
fi
popDir="$PWD"
for ext in $exts; do
cd "$ext"
[ -e Makefile ] || docker-php-ext-configure "$ext"
make -j"$j"
find modules \
-maxdepth 1 \
-name '*.so' \
-exec sh -euxc ' \
strip --strip-all "$@" || :
' -- '{}' +
make -j"$j" install
find modules \
-maxdepth 1 \
-name '*.so' \
-exec basename '{}' ';' \
| xargs -r docker-php-ext-enable ${iniName:+--ini-name "$iniName"}
make -j"$j" clean
cd "$popDir"
done
if [ "$pm" = 'apk' ] && [ -n "$apkDel" ]; then
apk del --no-network $apkDel
fi
if [ -e /usr/src/php/.docker-delete-me ]; then
docker-php-source delete
fi
+143
View File
@@ -0,0 +1,143 @@
#!/bin/sh
set -e
# prefer user supplied CFLAGS, but default to our PHP_CFLAGS
: ${CFLAGS:=$PHP_CFLAGS}
: ${CPPFLAGS:=$PHP_CPPFLAGS}
: ${LDFLAGS:=$PHP_LDFLAGS}
export CFLAGS CPPFLAGS LDFLAGS
srcExists=
if [ -d /usr/src/php ]; then
srcExists=1
fi
docker-php-source extract
if [ -z "$srcExists" ]; then
touch /usr/src/php/.docker-delete-me
fi
cd /usr/src/php/ext
usage() {
echo "usage: $0 [-jN] [--ini-name file.ini] ext-name [ext-name ...]"
echo " ie: $0 gd mysqli"
echo " $0 pdo pdo_mysql"
echo " $0 -j5 gd mbstring mysqli pdo pdo_mysql shmop"
echo
echo 'if custom ./configure arguments are necessary, see docker-php-ext-configure'
echo
echo 'Possible values for ext-name:'
find . \
-mindepth 2 \
-maxdepth 2 \
-type f \
-name 'config.m4' \
| xargs -n1 dirname \
| xargs -n1 basename \
| sort \
| xargs
echo
echo 'Some of the above modules are already compiled into PHP; please check'
echo 'the output of "php -i" to see which modules are already loaded.'
}
opts="$(getopt -o 'h?j:' --long 'help,ini-name:,jobs:' -- "$@" || { usage >&2 && false; })"
eval set -- "$opts"
j=1
iniName=
while true; do
flag="$1"
shift
case "$flag" in
--help|-h|'-?') usage && exit 0 ;;
--ini-name) iniName="$1" && shift ;;
--jobs|-j) j="$1" && shift ;;
--) break ;;
*)
{
echo "error: unknown flag: $flag"
usage
} >&2
exit 1
;;
esac
done
exts=
for ext; do
if [ -z "$ext" ]; then
continue
fi
if [ ! -d "$ext" ]; then
echo >&2 "error: $PWD/$ext does not exist"
echo >&2
usage >&2
exit 1
fi
exts="$exts $ext"
done
if [ -z "$exts" ]; then
usage >&2
exit 1
fi
pm='unknown'
if [ -e /lib/apk/db/installed ]; then
pm='apk'
fi
apkDel=
if [ "$pm" = 'apk' ]; then
if [ -n "$PHPIZE_DEPS" ]; then
if apk info --installed .phpize-deps-configure > /dev/null; then
apkDel='.phpize-deps-configure'
elif ! apk info --installed .phpize-deps > /dev/null; then
apk add --no-cache --virtual .phpize-deps $PHPIZE_DEPS
apkDel='.phpize-deps'
fi
fi
fi
popDir="$PWD"
for ext in $exts; do
cd "$ext"
[ -e Makefile ] || docker-php-ext-configure "$ext"
make -j"$j"
if ! php -n -d 'display_errors=stderr' -r 'exit(ZEND_DEBUG_BUILD ? 0 : 1);' > /dev/null; then
# only "strip" modules if we aren't using a debug build of PHP
# (none of our builds are debug builds, but PHP might be recompiled with "--enable-debug" configure option)
# https://github.com/docker-library/php/issues/1268
find modules \
-maxdepth 1 \
-name '*.so' \
-exec sh -euxc ' \
strip --strip-all "$@" || :
' -- '{}' +
fi
make -j"$j" install
find modules \
-maxdepth 1 \
-name '*.so' \
-exec basename '{}' ';' \
| xargs -r docker-php-ext-enable ${iniName:+--ini-name "$iniName"}
make -j"$j" clean
cd "$popDir"
done
if [ "$pm" = 'apk' ] && [ -n "$apkDel" ]; then
apk del --no-network $apkDel
fi
if [ -e /usr/src/php/.docker-delete-me ]; then
docker-php-source delete
fi
+143
View File
@@ -0,0 +1,143 @@
#!/bin/sh
set -e
# prefer user supplied CFLAGS, but default to our PHP_CFLAGS
: ${CFLAGS:=$PHP_CFLAGS}
: ${CPPFLAGS:=$PHP_CPPFLAGS}
: ${LDFLAGS:=$PHP_LDFLAGS}
export CFLAGS CPPFLAGS LDFLAGS
srcExists=
if [ -d /usr/src/php ]; then
srcExists=1
fi
docker-php-source extract
if [ -z "$srcExists" ]; then
touch /usr/src/php/.docker-delete-me
fi
cd /usr/src/php/ext
usage() {
echo "usage: $0 [-jN] [--ini-name file.ini] ext-name [ext-name ...]"
echo " ie: $0 gd mysqli"
echo " $0 pdo pdo_mysql"
echo " $0 -j5 gd mbstring mysqli pdo pdo_mysql shmop"
echo
echo 'if custom ./configure arguments are necessary, see docker-php-ext-configure'
echo
echo 'Possible values for ext-name:'
find . \
-mindepth 2 \
-maxdepth 2 \
-type f \
-name 'config.m4' \
| xargs -n1 dirname \
| xargs -n1 basename \
| sort \
| xargs
echo
echo 'Some of the above modules are already compiled into PHP; please check'
echo 'the output of "php -i" to see which modules are already loaded.'
}
opts="$(getopt -o 'h?j:' --long 'help,ini-name:,jobs:' -- "$@" || { usage >&2 && false; })"
eval set -- "$opts"
j=1
iniName=
while true; do
flag="$1"
shift
case "$flag" in
--help|-h|'-?') usage && exit 0 ;;
--ini-name) iniName="$1" && shift ;;
--jobs|-j) j="$1" && shift ;;
--) break ;;
*)
{
echo "error: unknown flag: $flag"
usage
} >&2
exit 1
;;
esac
done
exts=
for ext; do
if [ -z "$ext" ]; then
continue
fi
if [ ! -d "$ext" ]; then
echo >&2 "error: $PWD/$ext does not exist"
echo >&2
usage >&2
exit 1
fi
exts="$exts $ext"
done
if [ -z "$exts" ]; then
usage >&2
exit 1
fi
pm='unknown'
if [ -e /lib/apk/db/installed ]; then
pm='apk'
fi
apkDel=
if [ "$pm" = 'apk' ]; then
if [ -n "$PHPIZE_DEPS" ]; then
if apk info --installed .phpize-deps-configure > /dev/null; then
apkDel='.phpize-deps-configure'
elif ! apk info --installed .phpize-deps > /dev/null; then
apk add --no-cache --virtual .phpize-deps $PHPIZE_DEPS
apkDel='.phpize-deps'
fi
fi
fi
popDir="$PWD"
for ext in $exts; do
cd "$ext"
[ -e Makefile ] || docker-php-ext-configure "$ext"
make -j"$j"
if ! php -n -d 'display_errors=stderr' -r 'exit(ZEND_DEBUG_BUILD ? 0 : 1);' > /dev/null; then
# only "strip" modules if we aren't using a debug build of PHP
# (none of our builds are debug builds, but PHP might be recompiled with "--enable-debug" configure option)
# https://github.com/docker-library/php/issues/1268
find modules \
-maxdepth 1 \
-name '*.so' \
-exec sh -euxc ' \
strip --strip-all "$@" || :
' -- '{}' +
fi
make -j"$j" install
find modules \
-maxdepth 1 \
-name '*.so' \
-exec basename '{}' '.so' ';' \
| xargs -r docker-php-ext-enable ${iniName:+--ini-name "$iniName"}
make -j"$j" clean
cd "$popDir"
done
if [ "$pm" = 'apk' ] && [ -n "$apkDel" ]; then
apk del --no-network $apkDel
fi
if [ -e /usr/src/php/.docker-delete-me ]; then
docker-php-source delete
fi
+34
View File
@@ -0,0 +1,34 @@
#!/bin/sh
set -e
dir=/usr/src/php
usage() {
echo "usage: $0 COMMAND"
echo
echo "Manage php source tarball lifecycle."
echo
echo "Commands:"
echo " extract extract php source tarball into directory $dir if not already done."
echo " delete delete extracted php source located into $dir if not already done."
echo
}
case "$1" in
extract)
mkdir -p "$dir"
if [ ! -f "$dir/.docker-extracted" ]; then
tar -Jxf /usr/src/php.tar.xz -C "$dir" --strip-components=1
touch "$dir/.docker-extracted"
fi
;;
delete)
rm -rf "$dir"
;;
*)
usage
exit 1
;;
esac
+1 -1
View File
@@ -47,7 +47,7 @@ build:
test:
@echo -e "=====> Testing loaded extensions... \c"
@if [[ -z `docker image ls $(REGISTRY)$(IMAGE) | grep "\s$(VERSION)\s"` ]]; then \
@if ! docker image inspect $(REGISTRY)$(IMAGE):$(VERSION) > /dev/null 2>&1; then \
echo 'FAIL [Missing image!!!]'; \
exit 1; \
fi
+1 -1
View File
@@ -45,7 +45,7 @@ build:
test:
@echo -e "=====> Testing loaded extensions... \c"
@if [[ -z `docker image ls $(REGISTRY)$(IMAGE) | grep "\s$(VERSION)\s"` ]]; then \
@if ! docker image inspect $(REGISTRY)$(IMAGE):$(VERSION) > /dev/null 2>&1; then \
echo 'FAIL [Missing image!!!]'; \
exit 1; \
fi
+1 -1
View File
@@ -49,7 +49,7 @@ build:
test:
@echo -e "=====> Testing loaded extensions... \c"
@if [[ -z `docker image ls $(REGISTRY)$(IMAGE) | grep "\s$(VERSION)\s"` ]]; then \
@if ! docker image inspect $(REGISTRY)$(IMAGE):$(VERSION) > /dev/null 2>&1; then \
echo 'FAIL [Missing image!!!]'; \
exit 1; \
fi